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.weatherlistwidget; 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.content.ContentUris; 26 import android.database.Cursor; 27 import android.net.Uri; 28 import android.os.Bundle; 29 import android.widget.RemoteViews; 30 import android.widget.RemoteViewsService; 31 32 /** 33 * This is the service that provides the factory to be bound to the collection service. 34 */ 35 public class WeatherWidgetService extends RemoteViewsService { 36 @Override 37 public RemoteViewsFactory onGetViewFactory(Intent intent) { 38 return new StackRemoteViewsFactory(this.getApplicationContext(), intent); 39 } 40 } 41 42 /** 43 * This is the factory that will provide data to the collection widget. 44 */ 45 class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory { 46 private Context mContext; 47 private Cursor mCursor; 48 private int mAppWidgetId; 49 50 public StackRemoteViewsFactory(Context context, Intent intent) { 51 mContext = context; 52 mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 53 AppWidgetManager.INVALID_APPWIDGET_ID); 54 } 55 56 public void onCreate() { 57 // Since we reload the cursor in onDataSetChanged() which gets called immediately after 58 // onCreate(), we do nothing here. 59 } 60 61 public void onDestroy() { 62 if (mCursor != null) { 63 mCursor.close(); 64 } 65 } 66 67 public int getCount() { 68 return mCursor.getCount(); 69 } 70 71 public RemoteViews getViewAt(int position) { 72 // Get the data for this position from the content provider 73 String city = "Unknown City"; 74 int temp = 0; 75 if (mCursor.moveToPosition(position)) { 76 final int cityColIndex = mCursor.getColumnIndex(WeatherDataProvider.Columns.CITY); 77 final int tempColIndex = mCursor.getColumnIndex( 78 WeatherDataProvider.Columns.TEMPERATURE); 79 city = mCursor.getString(cityColIndex); 80 temp = mCursor.getInt(tempColIndex); 81 } 82 83 // Return a proper item with the proper city and temperature. Just for fun, we alternate 84 // the items to make the list easier to read. 85 final String formatStr = mContext.getResources().getString(R.string.item_format_string); 86 final int itemId = (position % 2 == 0 ? R.layout.light_widget_item 87 : R.layout.dark_widget_item); 88 RemoteViews rv = new RemoteViews(mContext.getPackageName(), itemId); 89 rv.setTextViewText(R.id.widget_item, String.format(formatStr, temp, city)); 90 91 // Set the click intent so that we can handle it and show a toast message 92 final Intent fillInIntent = new Intent(); 93 final Bundle extras = new Bundle(); 94 extras.putString(WeatherWidgetProvider.EXTRA_CITY_ID, city); 95 fillInIntent.putExtras(extras); 96 rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent); 97 98 return rv; 99 } 100 public RemoteViews getLoadingView() { 101 // We aren't going to return a default loading view in this sample 102 return null; 103 } 104 105 public int getViewTypeCount() { 106 // Technically, we have two types of views (the dark and light background views) 107 return 2; 108 } 109 110 public long getItemId(int position) { 111 return position; 112 } 113 114 public boolean hasStableIds() { 115 return true; 116 } 117 118 public void onDataSetChanged() { 119 // Refresh the cursor 120 if (mCursor != null) { 121 mCursor.close(); 122 } 123 mCursor = mContext.getContentResolver().query(WeatherDataProvider.CONTENT_URI, null, null, 124 null, null); 125 } 126 } 127