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