/* * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.micode.notes.widget; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.util.Log; import android.widget.RemoteViews; import net.micode.notes.R; import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.tool.ResourceParser; import net.micode.notes.ui.NoteEditActivity; import net.micode.notes.ui.NotesListActivity; // NoteWidgetProvider是一个抽象类,它扩展了AppWidgetProvider,用于处理笔记小部件的通用逻辑 public abstract class NoteWidgetProvider extends AppWidgetProvider { // 定义了用于查询笔记小部件信息的列投影 public static final String[] PROJECTION = new String[]{ NoteColumns.ID, NoteColumns.BG_COLOR_ID, NoteColumns.SNIPPET }; // 定义了列投影的索引 public static final int COLUMN_ID = 0; public static final int COLUMN_BG_COLOR_ID = 1; public static final int COLUMN_SNIPPET = 2; // 日志标签 private static final String TAG = "NoteWidgetProvider"; // 当小部件从宿主删除时调用 @Override public void onDeleted(Context context, int[] appWidgetIds) { // 更新数据库,将已删除的小部件ID设置为无效 ContentValues values = new ContentValues(); values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); for (int appWidgetId : appWidgetIds) { context.getContentResolver().update(Notes.CONTENT_NOTE_URI, values, NoteColumns.WIDGET_ID + "=?", new String[]{String.valueOf(appWidgetId)}); } } // 根据小部件ID获取笔记小部件信息 private Cursor getNoteWidgetInfo(Context context, int widgetId) { // 查询数据库,获取与小部件ID关联的笔记信息,排除位于回收站的笔记 return context.getContentResolver().query(Notes.CONTENT_NOTE_URI, PROJECTION, NoteColumns.WIDGET_ID + "=? AND " + NoteColumns.PARENT_ID + "<>?", new String[]{String.valueOf(widgetId), String.valueOf(Notes.ID_TRASH_FOLDER)}, null); } // 更新小部件的通用方法(带隐私模式参数的重载方法调用不带参数的版本) protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { update(context, appWidgetManager, appWidgetIds, false); } // 更新小部件的私有方法 private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, boolean privacyMode) { for (int appWidgetId : appWidgetIds) { if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) { int bgId = ResourceParser.getDefaultBgId(context); // 获取默认背景ID String snippet = ""; // 初始化摘要文本 Intent intent = new Intent(context, NoteEditActivity.class); // 创建跳转到编辑活动的意图 intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); // 设置活动启动标志 intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetId); // 添加小部件ID作为额外数据 intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType()); // 添加小部件类型作为额外数据 // 查询与小部件ID关联的笔记信息 Cursor c = getNoteWidgetInfo(context, appWidgetId); if (c != null && c.moveToFirst()) { if (c.getCount() > 1) { // 如果查询结果超过一条,记录错误日志并关闭游标 Log.e(TAG, "Multiple messages with same widget id:" + appWidgetId); c.close(); return; } // 从游标中获取摘要文本和背景ID snippet = c.getString(COLUMN_SNIPPET); bgId = c.getInt(COLUMN_BG_COLOR_ID); // 添加笔记ID作为额外数据,并设置意图动作为查看 intent.putExtra(Intent.EXTRA_UID, c.getLong(COLUMN_ID)); intent.setAction(Intent.ACTION_VIEW); } else { // 如果没有查询到笔记信息,则设置默认摘要文本,并设置意图动作为插入或编辑 snippet = context.getResources().getString(R.string.widget_havenot_content); intent.setAction(Intent.ACTION_INSERT_OR_EDIT); } // 关闭游标(如果已打开) if (c != null) { c.close(); } // 创建RemoteViews对象,用于更新小部件视图 RemoteViews rv = new RemoteViews(context.getPackageName(), getLayoutId()); // 设置小部件背景图片 rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId)); // 添加背景ID作为额外数据到意图中 intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId); // 根据隐私模式生成PendingIntent PendingIntent pendingIntent = null; if (privacyMode) { // 如果启用隐私模式,则设置文本为隐私提示,并创建跳转到笔记列表活动的PendingIntent rv.setTextViewText(R.id.widget_text, context.getString(R.string.widget_under_visit_mode)); pendingIntent = PendingIntent.getActivity(context, appWidgetId, new Intent( context, NotesListActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); } else { // 否则,设置文本为摘要文本,并创建跳转到编辑活动的PendingIntent rv.setTextViewText(R.id.widget_text, snippet); pendingIntent = PendingIntent.getActivity(context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT); } // 设置点击事件的PendingIntent rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent); // 更新小部件视图 appWidgetManager.updateAppWidget(appWidgetId, rv); } } } // 抽象方法,子类需要实现以返回背景资源ID protected abstract int getBgResourceId(int bgId); // 抽象方法,子类需要实现以返回布局资源ID protected abstract int getLayoutId(); // 抽象方法,子类需要实现以返回小部件类型 protected abstract int getWidgetType(); }