WidgetService.java revision 161f50d0fabdaa384a63ce69f595861c5e69795f
18a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira/* 28a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * Copyright (C) 2012 The Android Open Source Project 38a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * 48a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * Licensed under the Apache License, Version 2.0 (the "License"); 58a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * you may not use this file except in compliance with the License. 68a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * You may obtain a copy of the License at 78a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * 88a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * http://www.apache.org/licenses/LICENSE-2.0 98a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * 108a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * Unless required by applicable law or agreed to in writing, software 118a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * distributed under the License is distributed on an "AS IS" BASIS, 128a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * See the License for the specific language governing permissions and 148a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * limitations under the License. 158a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira */ 168a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereirapackage com.android.mail.widget; 178a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 188a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport com.android.mail.R; 198a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport com.android.mail.providers.Account; 208a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport com.android.mail.providers.Conversation; 218a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport com.android.mail.providers.Folder; 228a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport com.android.mail.providers.UIProvider; 238a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport com.android.mail.utils.DelayedTaskHandler; 248a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport com.android.mail.utils.LogUtils; 258a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport com.android.mail.utils.Utils; 268a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 278a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport android.appwidget.AppWidgetManager; 288a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport android.content.ContentResolver; 298a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport android.content.Context; 308a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport android.content.CursorLoader; 318a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport android.content.Intent; 328a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport android.content.Loader; 338a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport android.content.Loader.OnLoadCompleteListener; 348a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport android.database.Cursor; 358a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport android.os.Looper; 368a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport android.text.SpannableStringBuilder; 378a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport android.text.TextUtils; 388a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport android.text.format.DateUtils; 398a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport android.view.View; 408a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport android.widget.RemoteViews; 418a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereiraimport android.widget.RemoteViewsService; 428a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 438a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereirapublic class WidgetService extends RemoteViewsService { 448a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira /** 458a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * Lock to avoid race condition between widgets. 468a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira */ 478a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private static Object sWidgetLock = new Object(); 488a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 498a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira @Override 508a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira public RemoteViewsFactory onGetViewFactory(Intent intent) { 518a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira return new MailFactory(getApplicationContext(), intent); 528a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 538a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 548a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira /** 558a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * Remote Views Factory for Mail Widget. 568a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira */ 578a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private static class MailFactory 588a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira implements RemoteViewsService.RemoteViewsFactory, OnLoadCompleteListener<Cursor> { 598a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private static final int MAX_CONVERSATIONS_COUNT = 25; 608a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private static final int MAX_SENDERS_LENGTH = 25; 618a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private static final String LOG_TAG = new LogUtils().getLogTag(); 628a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 638a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private final Context mContext; 648a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private final int mAppWidgetId; 658a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private final Account mAccount; 668a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private final Folder mFolder; 678a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private final WidgetConversationViewBuilder mWidgetConversationViewBuilder; 688a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private Cursor mConversationCursor; 698a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private CursorLoader mFolderLoader; 708a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private FolderUpdateHandler mFolderUpdateHandler; 718a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private int mFolderCount; 728a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private boolean mShouldShowViewMore; 738a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private boolean mFolderInformationShown = false; 748a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private ContentResolver mResolver; 758a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 768a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira public MailFactory(Context context, Intent intent) { 778a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mContext = context; 788a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mAppWidgetId = intent.getIntExtra( 798a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); 80518ee42d4f5cfbcac07dc61fdcac4de8c32c0e26Mindy Pereira mAccount = new Account(intent.getStringExtra(WidgetProvider.EXTRA_ACCOUNT)); 81518ee42d4f5cfbcac07dc61fdcac4de8c32c0e26Mindy Pereira mFolder = new Folder(intent.getStringExtra(WidgetProvider.EXTRA_FOLDER)); 828a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mWidgetConversationViewBuilder = new WidgetConversationViewBuilder(mContext, mAccount); 838a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mResolver = context.getContentResolver(); 848a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 858a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 868a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira @Override 878a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira public void onCreate() { 888a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira // Save the map between widgetId and account to preference 898a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira BaseWidgetProvider.saveWidgetInformation(mContext, mAppWidgetId, mAccount, mFolder); 908a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 918a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira // If the account of this widget has been removed, we want to update the widget to 928a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira // "Tap to configure" mode. 938a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira if (!BaseWidgetProvider.isWidgetConfigured(mContext, mAppWidgetId, mAccount, mFolder)) { 948a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira BaseWidgetProvider.updateWidget(mContext, mAppWidgetId, mAccount, mFolder); 958a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 968a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 97cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira mConversationCursor = mResolver.query(mFolder.conversationListUri, 988a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira UIProvider.CONVERSATION_PROJECTION, null, null, null); 998a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 100cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira mFolderLoader = new CursorLoader(mContext, mFolder.uri, UIProvider.FOLDERS_PROJECTION, 101cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira null, null, null); 1028a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mFolderLoader.registerListener(0, this); 1038a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mFolderUpdateHandler = new FolderUpdateHandler(mContext.getResources().getInteger( 1048a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira R.integer.widget_folder_refresh_delay_ms)); 1058a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mFolderUpdateHandler.scheduleTask(); 1068a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 1078a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 1088a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 1098a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira @Override 1108a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira public void onDestroy() { 1118a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira synchronized (sWidgetLock) { 1128a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira if (mConversationCursor != null && !mConversationCursor.isClosed()) { 1138a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mConversationCursor.close(); 1148a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mConversationCursor = null; 1158a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 1168a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 1178a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 1188a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira if (mFolderLoader != null) { 1198a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mFolderLoader.reset(); 1208a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mFolderLoader = null; 1218a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 1228a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 1238a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 1248a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira @Override 1258a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira public void onDataSetChanged() { 1268a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira synchronized (sWidgetLock) { 1278a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira // TODO: use loader manager. 1288a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mConversationCursor.requery(); 1298a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 1308a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mFolderUpdateHandler.scheduleTask(); 1318a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 1328a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 1338a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira /** 1348a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * Returns the number of items should be shown in the widget list. This method also updates 1358a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * the boolean that indicates whether the "show more" item should be shown. 1368a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * @return the number of items to be displayed in the list. 1378a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira */ 1388a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira @Override 1398a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira public int getCount() { 1408a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira synchronized (sWidgetLock) { 1418a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira final int count = getConversationCount(); 1428a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mShouldShowViewMore = count < mConversationCursor.getCount() 1438a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira || count < mFolderCount; 1448a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira return count + (mShouldShowViewMore ? 1 : 0); 1458a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 1468a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 1478a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 1488a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira /** 1498a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * Returns the number of conversations that should be shown in the widget. This method 1508a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * doesn't update the boolean that indicates that the "show more" item should be included 1518a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * in the list. 1528a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * @return 1538a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira */ 1548a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private int getConversationCount() { 1558a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira synchronized (sWidgetLock) { 1568a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira return Math.min(mConversationCursor.getCount(), MAX_CONVERSATIONS_COUNT); 1578a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 1588a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 1598a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 1608a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira /** 1618a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * @return the {@link RemoteViews} for a specific position in the list. 1628a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira */ 1638a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira @Override 1648a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira public RemoteViews getViewAt(int position) { 1658a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira synchronized (sWidgetLock) { 1668a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira // "View more conversations" view. 1678a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira if (mConversationCursor == null 1688a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira || (mShouldShowViewMore && position >= getConversationCount())) { 1698a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira return getViewMoreConversationsView(); 1708a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 1718a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 1728a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira if (!mConversationCursor.moveToPosition(position)) { 1738a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira // If we ever fail to move to a position, return the "View More conversations" 1748a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira // view. 1758a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira LogUtils.e(LOG_TAG, 1768a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira "Failed to move to position %d in the cursor.", position); 1778a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira return getViewMoreConversationsView(); 1788a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 1798a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 180a831b2f1ba6d3c18d5e54563df8bae1f589c4257Mindy Pereira Conversation conversation = new Conversation(mConversationCursor); 1818a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira // Split the senders and status from the instructions. 1828a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira SpannableStringBuilder senderBuilder = new SpannableStringBuilder(); 1838a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira SpannableStringBuilder statusBuilder = new SpannableStringBuilder(); 1844fa30618ad6683915858c0da1a9e08d53810d851Mindy Pereira senderBuilder.append(conversation.senders); 1854fa30618ad6683915858c0da1a9e08d53810d851Mindy Pereira // TODO: (mindyp) create stylized sender text. 1868a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 1878a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira // Get styled date. 1888a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira CharSequence date = DateUtils.getRelativeTimeSpanString( 1898a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mContext, conversation.dateMs); 1908a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 1918a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira // Load up our remote view. 1928a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira RemoteViews remoteViews = mWidgetConversationViewBuilder.getStyledView( 1938a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira senderBuilder, statusBuilder, date, filterTag(conversation.subject), 1948a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira conversation.snippet, conversation.folderList, conversation.hasAttachments); 1958a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 1968a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira // On click intent. 1978a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira remoteViews.setOnClickFillInIntent(R.id.widget_conversation, 198161f50d0fabdaa384a63ce69f595861c5e69795fMindy Pereira Utils.createViewConversationIntent(conversation, mFolder, mAccount)); 1998a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 2008a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira return remoteViews; 2018a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 2028a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 2038a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 2048a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira /** 2058a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * @return the "View more conversations" view. 2068a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira */ 2078a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private RemoteViews getViewMoreConversationsView() { 2088a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira RemoteViews view = new RemoteViews(mContext.getPackageName(), R.layout.widget_loading); 2098a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira view.setTextViewText( 2108a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira R.id.loading_text, mContext.getText(R.string.view_more_conversations)); 211161f50d0fabdaa384a63ce69f595861c5e69795fMindy Pereira view.setOnClickFillInIntent(R.id.widget_loading, 212161f50d0fabdaa384a63ce69f595861c5e69795fMindy Pereira Utils.createViewFolderIntent(mFolder, mAccount)); 2138a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira return view; 2148a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 2158a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 2168a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira @Override 2178a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira public RemoteViews getLoadingView() { 2188a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira RemoteViews view = new RemoteViews(mContext.getPackageName(), R.layout.widget_loading); 2198a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira view.setTextViewText( 2208a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira R.id.loading_text, mContext.getText(R.string.loading_conversation)); 2218a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira return view; 2228a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 2238a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 2248a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira @Override 2258a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira public int getViewTypeCount() { 2268a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira return 2; 2278a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 2288a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 2298a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira @Override 2308a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira public long getItemId(int position) { 2318a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira return position; 2328a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 2338a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 2348a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira @Override 2358a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira public boolean hasStableIds() { 2368a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira return false; 2378a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 2388a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 2398a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira @Override 2408a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira public void onLoadComplete(Loader<Cursor> loader, Cursor data) { 2418a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira if (!data.moveToFirst()) { 2428a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira return; 2438a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 2448a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 2458a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira final int unreadCount = data.getInt(UIProvider.FOLDER_UNREAD_COUNT_COLUMN); 2468a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira final String folderName = data.getString(UIProvider.FOLDER_NAME_COLUMN); 2478a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mFolderCount = data.getInt(UIProvider.FOLDER_TOTAL_COUNT_COLUMN); 2488a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 2498a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira RemoteViews remoteViews = new RemoteViews(mContext.getPackageName(), R.layout.widget); 2508a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext); 2518a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 2528a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira if (!mFolderInformationShown && !TextUtils.isEmpty(folderName)) { 2538a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira // We want to do a full update to the widget at least once, as the widget 2548a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira // manager doesn't cache the state of the remote views when doing a partial 2558a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira // widget update. This causes the label name to be shown as blank if the state 2568a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira // of the widget is restored. 2578a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira BaseWidgetProvider.configureValidAccountWidget( 2588a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mContext, remoteViews, mAppWidgetId, mAccount, mFolder, folderName); 2598a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira appWidgetManager.updateAppWidget(mAppWidgetId, remoteViews); 2608a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mFolderInformationShown = true; 2618a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 2628a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 2638a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira remoteViews.setViewVisibility(R.id.widget_folder, View.VISIBLE); 2648a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira remoteViews.setTextViewText(R.id.widget_folder, folderName); 2658a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira remoteViews.setViewVisibility(R.id.widget_unread_count, View.VISIBLE); 2668a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira remoteViews.setTextViewText( 2678a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira R.id.widget_unread_count, Utils.getUnreadCountString(mContext, unreadCount)); 2688a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 2698a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira appWidgetManager.partiallyUpdateAppWidget(mAppWidgetId, remoteViews); 2708a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 2718a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 2728a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira /** 2738a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * If the subject contains the tag of a mailing-list (text surrounded with []), return the 2748a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * subject with that tag ellipsized, e.g. "[android-gmail-team] Hello" -> "[andr...] Hello" 2758a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira */ 2768a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private static String filterTag(String subject) { 2778a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira String result = subject; 2788a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira if (subject.length() > 0 && subject.charAt(0) == '[') { 2798a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira int end = subject.indexOf(']'); 2808a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira if (end > 0) { 2818a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira String tag = subject.substring(1, end); 2828a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira result = "[" + Utils.ellipsize(tag, 7) + "]" + subject.substring(end + 1); 2838a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 2848a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 2858a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 2868a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira return result; 2878a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 2888a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 2898a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira /** 2908a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira * A {@link DelayedTaskHandler} to throttle label update to a reasonable rate. 2918a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira */ 2928a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira private class FolderUpdateHandler extends DelayedTaskHandler { 2938a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira public FolderUpdateHandler(int refreshDelay) { 2948a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira super(Looper.myLooper(), refreshDelay); 2958a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 2968a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira 2978a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira @Override 2988a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira protected void performTask() { 2998a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira // Start the loader. The cached data will be returned if present. 3008a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira if (mFolderLoader != null) { 3018a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira mFolderLoader.startLoading(); 3028a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 3038a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 3048a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 3058a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira } 3068a8c50d8fcc4f20549c9f395edbad017a940e72bMindy Pereira} 307