Android 3.0正式版API Level 11中加入了一个天气预报例子,下面是manifest.xml中的关键代码,只是少了xml的编码头:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.android.weatherlistwidget">    <uses-sdk android:minSdkVersion="11" />    <application android:label="Weather Widget Sample">         <receiver android:name="WeatherWidgetProvider">            <intent-filter>                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />            </intent-filter>                   <meta-data android:name="android.appwidget.provider"                    android:resource="@xml/widgetinfo" />        </receiver>         <service android:name="WeatherWidgetService"            android:permission="android.permission.BIND_REMOTEVIEWS"            android:exported="false" />         <provider android:name="WeatherDataProvider"              android:authorities="com.example.android.weatherlistwidget.provider" />    </application></manifest>

这里WeatherDataProvider.java的源码为主要是ContentProvider相关的处理,这里作为appWidget的receiver

  class WeatherDataPoint {    String city; //城市    int degrees; //度数    WeatherDataPoint(String c, int d) {        city = c;        degrees = d;    }} public class WeatherDataProvider extends ContentProvider {    public static final Uri CONTENT_URI =        Uri.parse("content://com.example.android.weatherlistwidget.provider");    public static class Columns {        public static final String ID = "_id";        public static final String CITY = "city";        public static final String TEMPERATURE = "temperature";    }     private static final ArrayList<WeatherDataPoint> sData = new ArrayList<WeatherDataPoint>();    @Override    public boolean onCreate() {        sData.add(new WeatherDataPoint("San Francisco", 13));        sData.add(new WeatherDataPoint("New York", 1));        sData.add(new WeatherDataPoint("Seattle", 7));        sData.add(new WeatherDataPoint("Boston", 4));        sData.add(new WeatherDataPoint("Miami", 22));        sData.add(new WeatherDataPoint("Toronto", -10));        sData.add(new WeatherDataPoint("Calgary", -13));        sData.add(new WeatherDataPoint("Tokyo", 8));        sData.add(new WeatherDataPoint("Kyoto", 11));        sData.add(new WeatherDataPoint("London", -1));        sData.add(new WeatherDataPoint("Nomanisan", 27));        return true;    }    @Override    public synchronized Cursor query(Uri uri, String[] projection, String selection,            String[] selectionArgs, String sortOrder) {        assert(uri.getPathSegments().isEmpty());         final MatrixCursor c = new MatrixCursor(                new String[]{ Columns.ID, Columns.CITY, Columns.TEMPERATURE });        for (int i = 0; i < sData.size(); ++i) {            final WeatherDataPoint data = sData.get(i);            c.addRow(new Object[]{ new Integer(i), data.city, new Integer(data.degrees) });        }        return c;    }    @Override    public String getType(Uri uri) {        return "vnd.android.cursor.dir/vnd.weatherlistwidget.citytemperature";    }    @Override    public Uri insert(Uri uri, ContentValues values) {        return null;    }    @Override    public int delete(Uri uri, String selection, String[] selectionArgs) {        return 0;    }    @Override    public synchronized int update(Uri uri, ContentValues values, String selection,            String[] selectionArgs) {        assert(uri.getPathSegments().size() == 1);        final int index = Integer.parseInt(uri.getPathSegments().get(0));        final MatrixCursor c = new MatrixCursor(                new String[]{ Columns.ID, Columns.CITY, Columns.TEMPERATURE });        assert(0 <= index && index < sData.size());        final WeatherDataPoint data = sData.get(index);        data.degrees = values.getAsInteger(Columns.TEMPERATURE);         getContext().getContentResolver().notifyChange(uri, null);        return 1;    }}

上面可以看到,对于插入和删除没有做过多的处理,对于天气更新给出了详细的解决方法。

有关 WeatherWidgetProvider.java 主要是appWidget的核心,为provider

class WeatherDataProviderObserver extends ContentObserver { //监控数据库的变化    private AppWidgetManager mAppWidgetManager;    private ComponentName mComponentName;    WeatherDataProviderObserver(AppWidgetManager mgr, ComponentName cn, Handler h) {        super(h);        mAppWidgetManager = mgr;        mComponentName = cn;    }    @Override    public void onChange(boolean selfChange) {           mAppWidgetManager.notifyAppWidgetViewDataChanged(                mAppWidgetManager.getAppWidgetIds(mComponentName), R.id.weather_list);    }} public class WeatherWidgetProvider extends AppWidgetProvider {    public static String CLICK_ACTION = "com.example.android.weatherlistwidget.CLICK";    public static String REFRESH_ACTION = "com.example.android.weatherlistwidget.REFRESH";    public static String EXTRA_CITY_ID = "com.example.android.weatherlistwidget.city";    private static HandlerThread sWorkerThread;    private static Handler sWorkerQueue;    private static WeatherDataProviderObserver sDataObserver;    public WeatherWidgetProvider() {         sWorkerThread = new HandlerThread("WeatherWidgetProvider-worker"); //开一个线程,这里用到了HandlerThread        sWorkerThread.start();        sWorkerQueue = new Handler(sWorkerThread.getLooper()); //不了解Thread的Looper可以看下这个例子比较简单清晰    }    @Override    public void onEnabled(Context context) { //当appWidget添加到桌面上时           final ContentResolver r = context.getContentResolver();        if (sDataObserver == null) {            final AppWidgetManager mgr = AppWidgetManager.getInstance(context);            final ComponentName cn = new ComponentName(context, WeatherWidgetProvider.class);            sDataObserver = new WeatherDataProviderObserver(mgr, cn, sWorkerQueue);            r.registerContentObserver(WeatherDataProvider.CONTENT_URI, true, sDataObserver); //注册监控数据库变化的回调        }    }    @Override    public void onReceive(Context ctx, Intent intent) {        final String action = intent.getAction();        if (action.equals(REFRESH_ACTION)) { //接收数据库改变的回调广播               final Context context = ctx;            sWorkerQueue.removeMessages(0);            sWorkerQueue.post(new Runnable() {                @Override                public void run() {                    final ContentResolver r = context.getContentResolver();                    final Cursor c = r.query(WeatherDataProvider.CONTENT_URI, null, null, null,                            null);                    final int count = c.getCount();                    final int maxDegrees = 96;                    r.unregisterContentObserver(sDataObserver); //首先取消数据库监控                    for (int i = 0; i < count; ++i) {                        final Uri uri = ContentUris.withAppendedId(WeatherDataProvider.CONTENT_URI, i);                        final ContentValues values = new ContentValues();                        values.put(WeatherDataProvider.Columns.TEMPERATURE,                                new Random().nextInt(maxDegrees));                        r.update(uri, values, null, null); //更新数据库记录层                    }                    r.registerContentObserver(WeatherDataProvider.CONTENT_URI, true, sDataObserver); //重新设置监视数据库                    final AppWidgetManager mgr = AppWidgetManager.getInstance(context);                    final ComponentName cn = new ComponentName(context, WeatherWidgetProvider.class);                    mgr.notifyAppWidgetViewDataChanged(mgr.getAppWidgetIds(cn), R.id.weather_list); //提示Widget有数据更新并刷新UI                }            });        } else if (action.equals(CLICK_ACTION)) {             final int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,                    AppWidgetManager.INVALID_APPWIDGET_ID);            final String city = intent.getStringExtra(EXTRA_CITY_ID);            final String formatStr = ctx.getResources().getString(R.string.toast_format_string);            Toast.makeText(ctx, String.format(formatStr, city), Toast.LENGTH_SHORT).show();        }        super.onReceive(ctx, intent);    }    @Override    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {                 for (int i = 0; i < appWidgetIds.length; ++i) {                      final Intent intent = new Intent(context, WeatherWidgetService.class);   //当桌面上有多个这个相同的appWidget需要分别处理            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);            intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));            final RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);            rv.setRemoteAdapter(appWidgetIds[i], R.id.weather_list, intent);            rv.setEmptyView(R.id.weather_list, R.id.empty_view);            final Intent onClickIntent = new Intent(context, WeatherWidgetProvider.class);            onClickIntent.setAction(WeatherWidgetProvider.CLICK_ACTION);            onClickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);            onClickIntent.setData(Uri.parse(onClickIntent.toUri(Intent.URI_INTENT_SCHEME)));            final PendingIntent onClickPendingIntent = PendingIntent.getBroadcast(context, 0,                    onClickIntent, PendingIntent.FLAG_UPDATE_CURRENT);            rv.setPendingIntentTemplate(R.id.weather_list, onClickPendingIntent);            final Intent refreshIntent = new Intent(context, WeatherWidgetProvider.class);            refreshIntent.setAction(WeatherWidgetProvider.REFRESH_ACTION);            final PendingIntent refreshPendingIntent = PendingIntent.getBroadcast(context, 0,                    refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT);            rv.setOnClickPendingIntent(R.id.refresh, refreshPendingIntent);            appWidgetManager.updateAppWidget(appWidgetIds[i], rv);        }        super.onUpdate(context, appWidgetManager, appWidgetIds);    }}

对于WeatherWidgetService.java这个Service集成于RemoteViewsService,主要是UI上的处理

public class WeatherWidgetService extends RemoteViewsService {    @Override    public RemoteViewsFactory onGetViewFactory(Intent intent) {        return new StackRemoteViewsFactory(this.getApplicationContext(), intent);    }}class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {    private Context mContext;    private Cursor mCursor;    private int mAppWidgetId;    public StackRemoteViewsFactory(Context context, Intent intent) {        mContext = context;        mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,                AppWidgetManager.INVALID_APPWIDGET_ID);    }    public void onCreate() {    }    public void onDestroy() {        if (mCursor != null) {            mCursor.close();        }    }    public int getCount() {        return mCursor.getCount();    }    public RemoteViews getViewAt(int position) {        String city = "Unknown City";        int temp = 0;        if (mCursor.moveToPosition(position)) {            final int cityColIndex = mCursor.getColumnIndex(WeatherDataProvider.Columns.CITY);            final int tempColIndex = mCursor.getColumnIndex(                    WeatherDataProvider.Columns.TEMPERATURE);            city = mCursor.getString(cityColIndex);            temp = mCursor.getInt(tempColIndex);        }        final String formatStr = mContext.getResources().getString(R.string.item_format_string);        final int itemId = (position % 2 == 0 ? R.layout.light_widget_item                : R.layout.dark_widget_item);        RemoteViews rv = new RemoteViews(mContext.getPackageName(), itemId);        rv.setTextViewText(R.id.widget_item, String.format(formatStr, temp, city));        final Intent fillInIntent = new Intent();        final Bundle extras = new Bundle();        extras.putString(WeatherWidgetProvider.EXTRA_CITY_ID, city);        fillInIntent.putExtras(extras);        rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);        return rv;    }    public RemoteViews getLoadingView() {        return null;    }    public int getViewTypeCount() {        return 2;    }    public long getItemId(int position) {        return position;    }    public boolean hasStableIds() {        return true;    }    public void onDataSetChanged() {        if (mCursor != null) {            mCursor.close();        }        mCursor = mContext.getContentResolver().query(WeatherDataProvider.CONTENT_URI, null, null,                null, null);    }}

更多相关文章

  1. [Android]aidl命令
  2. Android——类型转换 时间处理
  3. 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
  4. 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
  5. android 编译过程及错误处理
  6. Android设备如何保证数据同步写入磁盘
  7. Android(安卓)SQLite操作类--封装
  8. Android(安卓)中数据库查询方法 query() 中的 selectionArgs 的
  9. android 从matrix获取处理过的图片的实际宽度

随机推荐

  1. Android SDK版本名和API level对照表
  2. SDK1.5下 android判断是否存在网络
  3. android文件操作OpenFileInput OpenFileO
  4. android 判断是白天还是晚上,然后设置地图
  5. Android 系统开发学习杂记
  6. Android Gradle 构建工具(Android Gradle
  7. Android开发中如何定义和使用数组
  8. Failed to install the following Androi
  9. Android 最火快速开发框架AndroidAnnotat
  10. Android(安卓)adb shell启动应用程序的方