Home | History | Annotate | Download | only in widget
      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
     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
     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 
     81     protected abstract String getAction();
     82 
     83     protected abstract int getListId();
     84 
     85     /**
     86      * Update the widget appWidgetId
     87      */
     88     protected abstract void updateWidget(Context context, int appWidgetId);
     89 
     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      */
    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
    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 
    165     protected void deletePreferences(final int widgetId) {
    166     }
    167 
    168     /**
    169      * Remove preferences when deleting widget
    170      */
    171     @Override
    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