1 /* 2 * Copyright (C) 2011 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.example.android.stackwidget; 18 19 import java.util.ArrayList; 20 import java.util.List; 21 22 import android.appwidget.AppWidgetManager; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.os.Bundle; 26 import android.widget.RemoteViews; 27 import android.widget.RemoteViewsService; 28 29 public class StackWidgetService extends RemoteViewsService { 30 @Override onGetViewFactory(Intent intent)31 public RemoteViewsFactory onGetViewFactory(Intent intent) { 32 return new StackRemoteViewsFactory(this.getApplicationContext(), intent); 33 } 34 } 35 36 class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory { 37 private static final int mCount = 10; 38 private List<WidgetItem> mWidgetItems = new ArrayList<WidgetItem>(); 39 private Context mContext; 40 private int mAppWidgetId; 41 StackRemoteViewsFactory(Context context, Intent intent)42 public StackRemoteViewsFactory(Context context, Intent intent) { 43 mContext = context; 44 mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 45 AppWidgetManager.INVALID_APPWIDGET_ID); 46 } 47 onCreate()48 public void onCreate() { 49 // In onCreate() you setup any connections / cursors to your data source. Heavy lifting, 50 // for example downloading or creating content etc, should be deferred to onDataSetChanged() 51 // or getViewAt(). Taking more than 20 seconds in this call will result in an ANR. 52 for (int i = 0; i < mCount; i++) { 53 mWidgetItems.add(new WidgetItem(i + "!")); 54 } 55 56 // We sleep for 3 seconds here to show how the empty view appears in the interim. 57 // The empty view is set in the StackWidgetProvider and should be a sibling of the 58 // collection view. 59 try { 60 Thread.sleep(3000); 61 } catch (InterruptedException e) { 62 e.printStackTrace(); 63 } 64 } 65 onDestroy()66 public void onDestroy() { 67 // In onDestroy() you should tear down anything that was setup for your data source, 68 // eg. cursors, connections, etc. 69 mWidgetItems.clear(); 70 } 71 getCount()72 public int getCount() { 73 return mCount; 74 } 75 getViewAt(int position)76 public RemoteViews getViewAt(int position) { 77 // position will always range from 0 to getCount() - 1. 78 79 // We construct a remote views item based on our widget item xml file, and set the 80 // text based on the position. 81 RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item); 82 rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text); 83 84 // Next, we set a fill-intent which will be used to fill-in the pending intent template 85 // which is set on the collection view in StackWidgetProvider. 86 Bundle extras = new Bundle(); 87 extras.putInt(StackWidgetProvider.EXTRA_ITEM, position); 88 Intent fillInIntent = new Intent(); 89 fillInIntent.putExtras(extras); 90 rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent); 91 92 // You can do heaving lifting in here, synchronously. For example, if you need to 93 // process an image, fetch something from the network, etc., it is ok to do it here, 94 // synchronously. A loading view will show up in lieu of the actual contents in the 95 // interim. 96 try { 97 System.out.println("Loading view " + position); 98 Thread.sleep(500); 99 } catch (InterruptedException e) { 100 e.printStackTrace(); 101 } 102 103 // Return the remote views object. 104 return rv; 105 } 106 getLoadingView()107 public RemoteViews getLoadingView() { 108 // You can create a custom loading view (for instance when getViewAt() is slow.) If you 109 // return null here, you will get the default loading view. 110 return null; 111 } 112 getViewTypeCount()113 public int getViewTypeCount() { 114 return 1; 115 } 116 getItemId(int position)117 public long getItemId(int position) { 118 return position; 119 } 120 hasStableIds()121 public boolean hasStableIds() { 122 return true; 123 } 124 onDataSetChanged()125 public void onDataSetChanged() { 126 // This is triggered when you call AppWidgetManager notifyAppWidgetViewDataChanged 127 // on the collection view corresponding to this factory. You can do heaving lifting in 128 // here, synchronously. For example, if you need to process an image, fetch something 129 // from the network, etc., it is ok to do it here, synchronously. The widget will remain 130 // in its current state while work is being done here, so you don't need to worry about 131 // locking up the widget. 132 } 133 }