RemoteViewsService.java revision 9b3a2cf2a0a482ce8212eb2775176dd4c23e8e9a
1499cb9f516062b654952d282f211bee44c31a3c2Winson Chung/* 2499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * Copyright (C) 2007 The Android Open Source Project 3499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * 4499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * Licensed under the Apache License, Version 2.0 (the "License"); 5499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * you may not use this file except in compliance with the License. 6499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * You may obtain a copy of the License at 7499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * 8499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * http://www.apache.org/licenses/LICENSE-2.0 9499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * 10499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * Unless required by applicable law or agreed to in writing, software 11499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * distributed under the License is distributed on an "AS IS" BASIS, 12499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * See the License for the specific language governing permissions and 14499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * limitations under the License. 15499cb9f516062b654952d282f211bee44c31a3c2Winson Chung */ 16499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 17499cb9f516062b654952d282f211bee44c31a3c2Winson Chungpackage android.widget; 18499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 19499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport java.util.HashMap; 20499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport java.util.Map; 21499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 22499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.app.Service; 23499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.content.Intent; 24499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.os.IBinder; 25499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.util.Pair; 26499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 27499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport com.android.internal.widget.IRemoteViewsFactory; 28499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 29499cb9f516062b654952d282f211bee44c31a3c2Winson Chung/** 30499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * The service to be connected to for a remote adapter to request RemoteViews. Users should 31499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * extend the RemoteViewsService to provide the appropriate RemoteViewsFactory's used to 32499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * populate the remote collection view (ListView, GridView, etc). 33499cb9f516062b654952d282f211bee44c31a3c2Winson Chung */ 34499cb9f516062b654952d282f211bee44c31a3c2Winson Chungpublic abstract class RemoteViewsService extends Service { 35499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 36499cb9f516062b654952d282f211bee44c31a3c2Winson Chung private static final String LOG_TAG = "RemoteViewsService"; 37499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 38499cb9f516062b654952d282f211bee44c31a3c2Winson Chung // multimap implementation for reference counting 399b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung private HashMap<Intent.FilterComparison, Pair<RemoteViewsFactory, Integer>> mRemoteViewFactories; 40499cb9f516062b654952d282f211bee44c31a3c2Winson Chung private final Object mLock = new Object(); 41499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 42499cb9f516062b654952d282f211bee44c31a3c2Winson Chung /** 43499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * An interface for an adapter between a remote collection view (ListView, GridView, etc) and 44499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * the underlying data for that view. The implementor is responsible for making a RemoteView 45499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * for each item in the data set. 466394c0e52cf641d93f678fd052499aa952e3595dWinson Chung * 476394c0e52cf641d93f678fd052499aa952e3595dWinson Chung * @see android.widget.Adapter 486eceb00db916e2435a1625af631623bf95ae0e7fWinson Chung * @see android.appwidget.AppWidgetManager 49499cb9f516062b654952d282f211bee44c31a3c2Winson Chung */ 50499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public interface RemoteViewsFactory { 516394c0e52cf641d93f678fd052499aa952e3595dWinson Chung /** 526394c0e52cf641d93f678fd052499aa952e3595dWinson Chung * Called when your factory is first constructed. The same factory may be shared across 536394c0e52cf641d93f678fd052499aa952e3595dWinson Chung * multiple RemoteViewAdapters depending on the intent passed. 546394c0e52cf641d93f678fd052499aa952e3595dWinson Chung */ 55499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public void onCreate(); 566394c0e52cf641d93f678fd052499aa952e3595dWinson Chung /** 576eceb00db916e2435a1625af631623bf95ae0e7fWinson Chung * Called when notifyDataSetChanged() is triggered on the remote adapter. This allows a 586eceb00db916e2435a1625af631623bf95ae0e7fWinson Chung * RemoteViewsFactory to respond to data changes by updating any internal references. 596eceb00db916e2435a1625af631623bf95ae0e7fWinson Chung * 606eceb00db916e2435a1625af631623bf95ae0e7fWinson Chung * @see android.appwidget.AppWidgetManager#notifyAppWidgetViewDataChanged(int[], int) 616394c0e52cf641d93f678fd052499aa952e3595dWinson Chung */ 626394c0e52cf641d93f678fd052499aa952e3595dWinson Chung public void onDataSetChanged(); 636394c0e52cf641d93f678fd052499aa952e3595dWinson Chung /** 646394c0e52cf641d93f678fd052499aa952e3595dWinson Chung * Called when the last RemoteViewsAdapter that is associated with this factory is 656394c0e52cf641d93f678fd052499aa952e3595dWinson Chung * unbound. 666394c0e52cf641d93f678fd052499aa952e3595dWinson Chung */ 67499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public void onDestroy(); 68499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 69499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public int getCount(); 70499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public RemoteViews getViewAt(int position); 71499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public RemoteViews getLoadingView(); 72499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public int getViewTypeCount(); 73499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public long getItemId(int position); 74499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public boolean hasStableIds(); 75499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 76499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 77499cb9f516062b654952d282f211bee44c31a3c2Winson Chung /** 78499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * A private proxy class for the private IRemoteViewsFactory interface through the 79499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * public RemoteViewsFactory interface. 80499cb9f516062b654952d282f211bee44c31a3c2Winson Chung */ 81499cb9f516062b654952d282f211bee44c31a3c2Winson Chung private class RemoteViewsFactoryAdapter extends IRemoteViewsFactory.Stub { 82499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public RemoteViewsFactoryAdapter(RemoteViewsFactory factory) { 83499cb9f516062b654952d282f211bee44c31a3c2Winson Chung mFactory = factory; 84499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 856394c0e52cf641d93f678fd052499aa952e3595dWinson Chung public void onDataSetChanged() { 866394c0e52cf641d93f678fd052499aa952e3595dWinson Chung mFactory.onDataSetChanged(); 876394c0e52cf641d93f678fd052499aa952e3595dWinson Chung } 88499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public int getCount() { 89499cb9f516062b654952d282f211bee44c31a3c2Winson Chung return mFactory.getCount(); 90499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 91499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public RemoteViews getViewAt(int position) { 92499cb9f516062b654952d282f211bee44c31a3c2Winson Chung return mFactory.getViewAt(position); 93499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 94499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public RemoteViews getLoadingView() { 95499cb9f516062b654952d282f211bee44c31a3c2Winson Chung return mFactory.getLoadingView(); 96499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 97499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public int getViewTypeCount() { 98499cb9f516062b654952d282f211bee44c31a3c2Winson Chung return mFactory.getViewTypeCount(); 99499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 100499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public long getItemId(int position) { 101499cb9f516062b654952d282f211bee44c31a3c2Winson Chung return mFactory.getItemId(position); 102499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 103499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public boolean hasStableIds() { 104499cb9f516062b654952d282f211bee44c31a3c2Winson Chung return mFactory.hasStableIds(); 105499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 106499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 107499cb9f516062b654952d282f211bee44c31a3c2Winson Chung private RemoteViewsFactory mFactory; 108499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 109499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 110499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public RemoteViewsService() { 1119b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung mRemoteViewFactories = 1129b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung new HashMap<Intent.FilterComparison, Pair<RemoteViewsFactory, Integer>>(); 113499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 114499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 115499cb9f516062b654952d282f211bee44c31a3c2Winson Chung @Override 116499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public IBinder onBind(Intent intent) { 117499cb9f516062b654952d282f211bee44c31a3c2Winson Chung synchronized (mLock) { 118499cb9f516062b654952d282f211bee44c31a3c2Winson Chung // increment the reference count to the particular factory associated with this intent 1199b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung Intent.FilterComparison fc = new Intent.FilterComparison(intent); 120499cb9f516062b654952d282f211bee44c31a3c2Winson Chung Pair<RemoteViewsFactory, Integer> factoryRef = null; 121499cb9f516062b654952d282f211bee44c31a3c2Winson Chung RemoteViewsFactory factory = null; 1229b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung if (!mRemoteViewFactories.containsKey(fc)) { 123499cb9f516062b654952d282f211bee44c31a3c2Winson Chung factory = onGetViewFactory(intent); 124499cb9f516062b654952d282f211bee44c31a3c2Winson Chung factoryRef = new Pair<RemoteViewsFactory, Integer>(factory, 1); 1259b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung mRemoteViewFactories.put(fc, factoryRef); 126499cb9f516062b654952d282f211bee44c31a3c2Winson Chung factory.onCreate(); 127499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } else { 1289b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung Pair<RemoteViewsFactory, Integer> oldFactoryRef = mRemoteViewFactories.get(fc); 129499cb9f516062b654952d282f211bee44c31a3c2Winson Chung factory = oldFactoryRef.first; 130499cb9f516062b654952d282f211bee44c31a3c2Winson Chung int newRefCount = oldFactoryRef.second.intValue() + 1; 131499cb9f516062b654952d282f211bee44c31a3c2Winson Chung factoryRef = new Pair<RemoteViewsFactory, Integer>(oldFactoryRef.first, newRefCount); 1329b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung mRemoteViewFactories.put(fc, factoryRef); 133499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 134499cb9f516062b654952d282f211bee44c31a3c2Winson Chung return new RemoteViewsFactoryAdapter(factory); 135499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 136499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 137499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 138499cb9f516062b654952d282f211bee44c31a3c2Winson Chung @Override 139499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public boolean onUnbind(Intent intent) { 140499cb9f516062b654952d282f211bee44c31a3c2Winson Chung synchronized (mLock) { 1419b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung Intent.FilterComparison fc = new Intent.FilterComparison(intent); 1429b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung if (mRemoteViewFactories.containsKey(fc)) { 143499cb9f516062b654952d282f211bee44c31a3c2Winson Chung // this alleviates the user's responsibility of having to clear all factories 1449b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung Pair<RemoteViewsFactory, Integer> oldFactoryRef = 1459b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung mRemoteViewFactories.get(fc); 146499cb9f516062b654952d282f211bee44c31a3c2Winson Chung int newRefCount = oldFactoryRef.second.intValue() - 1; 147499cb9f516062b654952d282f211bee44c31a3c2Winson Chung if (newRefCount <= 0) { 148499cb9f516062b654952d282f211bee44c31a3c2Winson Chung oldFactoryRef.first.onDestroy(); 1499b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung mRemoteViewFactories.remove(fc); 150499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } else { 1519b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung Pair<RemoteViewsFactory, Integer> factoryRef = 1529b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung new Pair<RemoteViewsFactory, Integer>(oldFactoryRef.first, newRefCount); 1539b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung mRemoteViewFactories.put(fc, factoryRef); 154499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 155499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 156499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 157499cb9f516062b654952d282f211bee44c31a3c2Winson Chung return super.onUnbind(intent); 158499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 159499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 160499cb9f516062b654952d282f211bee44c31a3c2Winson Chung /** 161499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * To be implemented by the derived service to generate appropriate factories for 162499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * the data. 163499cb9f516062b654952d282f211bee44c31a3c2Winson Chung */ 164499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public abstract RemoteViewsFactory onGetViewFactory(Intent intent); 165499cb9f516062b654952d282f211bee44c31a3c2Winson Chung} 166