You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

185 lines
7.7 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* 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;
/**
* 便签桌面小部件基类
* 实现便签小部件的基础功能,包括:
* - 小部件删除时的资源释放
* - 小部件内容更新逻辑
* - 便签数据与小部件的绑定关系管理
* 子类需实现特定尺寸小部件的布局和资源获取逻辑
*/
public abstract class NoteWidgetProvider extends AppWidgetProvider {
// 数据库查询字段投影(仅获取必要字段提升性能)
public static final String[] PROJECTION = new String[]{
NoteColumns.ID, // 便签ID
NoteColumns.BG_COLOR_ID, // 便签背景颜色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";
/**
* 处理小部件删除事件
* 当用户删除小部件时清除数据库中关联的Widget ID
* @param context 应用上下文
* @param appWidgetIds 被删除的小部件ID数组
*/
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
ContentValues values = new ContentValues();
values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); // 设置为无效ID
for (int i = 0; i < appWidgetIds.length; i++) {
context.getContentResolver().update(Notes.CONTENT_NOTE_URI,
values,
NoteColumns.WIDGET_ID + "=?",
new String[] { String.valueOf(appWidgetIds[i])});
}
}
/**
* 获取与小部件关联的便签信息
* @param context 应用上下文
* @param widgetId 小部件ID
* @return 包含便签ID、背景色ID和摘要的Cursor
*/
private Cursor getNoteWidgetInfo(Context context, int widgetId) {
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_FOLER) },
null);
}
/**
* 更新小部件显示内容(公共接口)
* @param context 应用上下文
* @param appWidgetManager AppWidgetManager实例
* @param appWidgetIds 待更新的小部件ID数组
*/
protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
update(context, appWidgetManager, appWidgetIds, false);
}
/**
* 更新小部件显示内容(私有实现)
* @param context 应用上下文
* @param appWidgetManager AppWidgetManager实例
* @param appWidgetIds 待更新的小部件ID数组
* @param privacyMode 是否隐私模式(显示保护信息)
*/
private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds,
boolean privacyMode) {
for (int i = 0; i < appWidgetIds.length; i++) {
if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) {
int bgId = ResourceParser.getDefaultBgId(context); // 默认背景色
String snippet = ""; // 便签摘要
Intent intent = new Intent(context, NoteEditActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]);
intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType());
// 从数据库获取关联的便签信息
Cursor c = getNoteWidgetInfo(context, appWidgetIds[i]);
if (c != null && c.moveToFirst()) {
if (c.getCount() > 1) {
Log.e(TAG, "Multiple message with same widget id:" + appWidgetIds[i]);
c.close();
return;
}
snippet = c.getString(COLUMN_SNIPPET);
bgId = c.getInt(COLUMN_BG_COLOR_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));
intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId);
PendingIntent pendingIntent;
if (privacyMode) {
// 隐私模式下显示保护信息
rv.setTextViewText(R.id.widget_text, context.getString(R.string.widget_under_visit_mode));
pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], new Intent(
context, NotesListActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
} else {
// 正常模式下显示便签摘要
rv.setTextViewText(R.id.widget_text, snippet);
pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
}
}
}
/**
* 获取小部件背景资源ID抽象方法
* 由子类实现不同尺寸小部件的背景资源获取逻辑
* @param bgId 背景颜色逻辑ID
* @return 对应的背景资源ID
*/
protected abstract int getBgResourceId(int bgId);
/**
* 获取小部件布局资源ID抽象方法
* 由子类实现不同尺寸小部件的布局资源获取逻辑
* @return 布局资源ID
*/
protected abstract int getLayoutId();
/**
* 获取小部件类型(抽象方法)
* 由子类实现不同类型小部件的类型标识
* @return 小部件类型
*/
protected abstract int getWidgetType();
}