1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.messaging.widget; 18 19 import android.appwidget.AppWidgetManager; 20 import android.appwidget.AppWidgetProvider; 21 import android.content.ComponentName; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.os.Bundle; 26 27 import com.android.messaging.util.LogUtil; 28 29 public abstract class BaseWidgetProvider extends AppWidgetProvider { 30 protected static final String TAG = LogUtil.BUGLE_WIDGET_TAG; 31 32 public static final int WIDGET_CONVERSATION_REQUEST_CODE = 987; 33 34 static final String WIDGET_SIZE_KEY = "widgetSizeKey"; 35 36 public static final int SIZE_LARGE = 0; // undefined == 0, which is the default, large 37 public static final int SIZE_SMALL = 1; 38 public static final int SIZE_MEDIUM = 2; 39 public static final int SIZE_PRE_JB = 3; 40 41 /** 42 * Update all widgets in the list 43 */ 44 @Override onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)45 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { 46 super.onUpdate(context, appWidgetManager, appWidgetIds); 47 48 for (int i = 0; i < appWidgetIds.length; ++i) { 49 updateWidget(context, appWidgetIds[i]); 50 } 51 } 52 53 @Override onReceive(Context context, Intent intent)54 public void onReceive(Context context, Intent intent) { 55 if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { 56 LogUtil.v(TAG, "onReceive intent: " + intent + " for " + this.getClass()); 57 } 58 final String action = intent.getAction(); 59 60 // The base class AppWidgetProvider's onReceive handles the normal widget intents. Here 61 // we're looking for an intent sent by our app when it knows a message has 62 // been sent or received (or a conversation has been read) and is telling the widget it 63 // needs to update. 64 if (getAction().equals(action)) { 65 final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); 66 final int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, 67 this.getClass())); 68 69 if (appWidgetIds.length > 0) { 70 // We need to update all Bugle app widgets on the home screen. 71 if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { 72 LogUtil.v(TAG, "onReceive notifyAppWidgetViewDataChanged listId: " + 73 getListId() + " first widgetId: " + appWidgetIds[0]); 74 } 75 appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, getListId()); 76 } 77 } else { 78 super.onReceive(context, intent); 79 } 80 } 81 82 @Override onEnabled(Context context)83 public void onEnabled(Context context) { 84 super.onEnabled(context); 85 context.getApplicationContext().registerReceiver(this, new IntentFilter(getAction())); 86 } 87 getAction()88 protected abstract String getAction(); 89 getListId()90 protected abstract int getListId(); 91 92 /** 93 * Update the widget appWidgetId 94 */ updateWidget(Context context, int appWidgetId)95 protected abstract void updateWidget(Context context, int appWidgetId); 96 getWidgetSize(AppWidgetManager appWidgetManager, int appWidgetId)97 private int getWidgetSize(AppWidgetManager appWidgetManager, int appWidgetId) { 98 if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { 99 LogUtil.v(TAG, "BaseWidgetProvider.getWidgetSize"); 100 } 101 102 // Get the dimensions 103 final Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId); 104 105 // Get min width and height. 106 final int minWidth = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH); 107 final int minHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT); 108 109 // First find out rows and columns based on width provided. 110 final int rows = getCellsForSize(minHeight); 111 final int columns = getCellsForSize(minWidth); 112 113 if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { 114 LogUtil.v(TAG, "BaseWidgetProvider.getWidgetSize row: " + rows 115 + " columns: " + columns); 116 } 117 118 int size = SIZE_MEDIUM; 119 if (rows == 1) { 120 size = SIZE_SMALL; // Our widget doesn't let itself get this small. Perhaps in the 121 // future will add a super-mini widget. 122 } else if (columns > 3) { 123 size = SIZE_LARGE; 124 } 125 126 // put the size in the bundle so our service know what size it's dealing with. 127 final int savedSize = options.getInt(WIDGET_SIZE_KEY); 128 if (savedSize != size) { 129 options.putInt(WIDGET_SIZE_KEY, size); 130 appWidgetManager.updateAppWidgetOptions(appWidgetId, options); 131 132 // The size changed. We have to force the widget to rebuild the list. 133 appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, getListId()); 134 135 if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { 136 LogUtil.v(TAG, "BaseWidgetProvider.getWidgetSize old size: " + savedSize 137 + " new size saved: " + size); 138 } 139 } 140 141 return size; 142 } 143 144 /** 145 * Returns number of cells needed for given size of the widget. 146 * 147 * @param size Widget size in dp. 148 * @return Size in number of cells. 149 */ getCellsForSize(int size)150 private static int getCellsForSize(int size) { 151 // The hardwired sizes in this function come from the hardwired formula found in 152 // Android's UI guidelines for widget design: 153 // http://developer.android.com/guide/practices/ui_guidelines/widget_design.html 154 return (size + 30) / 70; 155 } 156 157 @Override onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions)158 public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, 159 int appWidgetId, Bundle newOptions) { 160 161 final int widgetSize = getWidgetSize(appWidgetManager, appWidgetId); 162 163 if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { 164 LogUtil.v(TAG, "BaseWidgetProvider.onAppWidgetOptionsChanged new size: " + 165 widgetSize); 166 } 167 168 super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions); 169 } 170 deletePreferences(final int widgetId)171 protected void deletePreferences(final int widgetId) { 172 } 173 174 /** 175 * Remove preferences when deleting widget 176 */ 177 @Override onDeleted(Context context, int[] appWidgetIds)178 public void onDeleted(Context context, int[] appWidgetIds) { 179 super.onDeleted(context, appWidgetIds); 180 181 if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { 182 LogUtil.v(TAG, "BaseWidgetProvider.onDeleted"); 183 } 184 185 for (final int widgetId : appWidgetIds) { 186 deletePreferences(widgetId); 187 } 188 } 189 190 } 191