Home | History | Annotate | Download | only in settings
      1 /*
      2  * Copyright (C) 2012 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.settings;
     18 
     19 import android.appwidget.AppWidgetManager;
     20 import android.appwidget.AppWidgetProviderInfo;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.os.Bundle;
     24 import android.os.Parcelable;
     25 import android.util.Log;
     26 
     27 import java.text.Collator;
     28 import java.util.ArrayList;
     29 import java.util.Collections;
     30 import java.util.Comparator;
     31 import java.util.List;
     32 
     33 public class AppWidgetLoader<Item extends AppWidgetLoader.LabelledItem> {
     34     private static final String TAG = "AppWidgetAdapter";
     35     private static final boolean LOGD = AppWidgetPickActivity.LOGD;
     36 
     37     private Context mContext;
     38     private AppWidgetManager mAppWidgetManager;
     39     ItemConstructor<Item> mItemConstructor;
     40 
     41     interface LabelledItem {
     42         CharSequence getLabel();
     43     }
     44 
     45     public AppWidgetLoader(Context context, AppWidgetManager appWidgetManager,
     46             ItemConstructor<Item> itemConstructor) {
     47         mContext = context;
     48         mAppWidgetManager = appWidgetManager;
     49         mItemConstructor = itemConstructor;
     50     }
     51 
     52     /**
     53      * Create list entries for any custom widgets requested through
     54      * {@link AppWidgetManager#EXTRA_CUSTOM_INFO}.
     55      */
     56     void putCustomAppWidgets(List<Item> items, Intent intent) {
     57         // get and validate the extras they gave us
     58         ArrayList<AppWidgetProviderInfo> customInfo = null;
     59         ArrayList<Bundle> customExtras = null;
     60         try_custom_items: {
     61             customInfo = intent.getParcelableArrayListExtra(AppWidgetManager.EXTRA_CUSTOM_INFO);
     62             if (customInfo == null || customInfo.size() == 0) {
     63                 Log.i(TAG, "EXTRA_CUSTOM_INFO not present.");
     64                 break try_custom_items;
     65             }
     66 
     67             int customInfoSize = customInfo.size();
     68             for (int i=0; i<customInfoSize; i++) {
     69                 Parcelable p = customInfo.get(i);
     70                 if (p == null || !(p instanceof AppWidgetProviderInfo)) {
     71                     customInfo = null;
     72                     Log.e(TAG, "error using EXTRA_CUSTOM_INFO index=" + i);
     73                     break try_custom_items;
     74                 }
     75             }
     76 
     77             customExtras = intent.getParcelableArrayListExtra(AppWidgetManager.EXTRA_CUSTOM_EXTRAS);
     78             if (customExtras == null) {
     79                 customInfo = null;
     80                 Log.e(TAG, "EXTRA_CUSTOM_INFO without EXTRA_CUSTOM_EXTRAS");
     81                 break try_custom_items;
     82             }
     83 
     84             int customExtrasSize = customExtras.size();
     85             if (customInfoSize != customExtrasSize) {
     86                 customInfo = null;
     87                 customExtras = null;
     88                 Log.e(TAG, "list size mismatch: EXTRA_CUSTOM_INFO: " + customInfoSize
     89                         + " EXTRA_CUSTOM_EXTRAS: " + customExtrasSize);
     90                 break try_custom_items;
     91             }
     92 
     93 
     94             for (int i=0; i<customExtrasSize; i++) {
     95                 Parcelable p = customExtras.get(i);
     96                 if (p == null || !(p instanceof Bundle)) {
     97                     customInfo = null;
     98                     customExtras = null;
     99                     Log.e(TAG, "error using EXTRA_CUSTOM_EXTRAS index=" + i);
    100                     break try_custom_items;
    101                 }
    102             }
    103         }
    104 
    105         if (LOGD) Log.d(TAG, "Using " + customInfo.size() + " custom items");
    106         putAppWidgetItems(customInfo, customExtras, items, 0, true);
    107     }
    108 
    109 
    110     /**
    111      * Create list entries for the given {@link AppWidgetProviderInfo} widgets,
    112      * inserting extras if provided.
    113      */
    114     void putAppWidgetItems(List<AppWidgetProviderInfo> appWidgets,
    115             List<Bundle> customExtras, List<Item> items, int categoryFilter,
    116             boolean ignoreFilter) {
    117         if (appWidgets == null) return;
    118         final int size = appWidgets.size();
    119         for (int i = 0; i < size; i++) {
    120             AppWidgetProviderInfo info = appWidgets.get(i);
    121 
    122             // We remove any widgets whose category isn't included in the filter
    123             if (!ignoreFilter && (info.widgetCategory & categoryFilter) == 0) {
    124                 continue;
    125             }
    126 
    127             Item item = mItemConstructor.createItem(mContext, info,
    128                     customExtras != null ? customExtras.get(i) : null);
    129 
    130             items.add(item);
    131         }
    132     }
    133 
    134     public interface ItemConstructor<Item> {
    135         Item createItem(Context context, AppWidgetProviderInfo info, Bundle extras);
    136     }
    137 
    138 
    139     /**
    140      * Build and return list of items to be shown in dialog. This will mix both
    141      * installed {@link AppWidgetProviderInfo} and those provided through
    142      * {@link AppWidgetManager#EXTRA_CUSTOM_INFO}, sorting them alphabetically.
    143      */
    144     protected List<Item> getItems(Intent intent) {
    145         boolean sortCustomAppWidgets =
    146                 intent.getBooleanExtra(AppWidgetManager.EXTRA_CUSTOM_SORT, true);
    147 
    148         List<Item> items = new ArrayList<Item>();
    149 
    150         // Default category is home screen
    151         int categoryFilter = intent.getIntExtra(AppWidgetManager.EXTRA_CATEGORY_FILTER,
    152                 AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);
    153 
    154         putInstalledAppWidgets(items, categoryFilter);
    155 
    156         // Sort all items together by label
    157         if (sortCustomAppWidgets) {
    158             putCustomAppWidgets(items, intent);
    159         }
    160         Collections.sort(items, new Comparator<Item>() {
    161             Collator mCollator = Collator.getInstance();
    162 
    163             public int compare(Item lhs, Item rhs) {
    164                 return mCollator.compare(lhs.getLabel(), rhs.getLabel());
    165             }
    166         });
    167         if (!sortCustomAppWidgets) {
    168             List<Item> customItems = new ArrayList<Item>();
    169             putCustomAppWidgets(customItems, intent);
    170             items.addAll(customItems);
    171         }
    172         return items;
    173     }
    174 
    175     /**
    176      * Create list entries for installed {@link AppWidgetProviderInfo} widgets.
    177      */
    178     void putInstalledAppWidgets(List<Item> items, int categoryFilter) {
    179         List<AppWidgetProviderInfo> installed =
    180                 mAppWidgetManager.getInstalledProviders(categoryFilter);
    181         putAppWidgetItems(installed, null, items, categoryFilter, false);
    182     }
    183 }
    184