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.
5._Open-source-software-rea.../NoteWidgetProvider.java

160 lines
8.1 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.

package net.micode.notes.widget;
// 导入必要的 Android 和应用相关的类和包
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, // 笔记的唯一 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";
// 覆写 onDeleted 方法,当小部件被用户移除时调用
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
// 创建一个 ContentValues 对象,用于更新数据库
ContentValues values = new ContentValues();
// 将小部件 ID 设置为无效 ID以便从数据库中移除相关关联
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 + "=?", // WHERE 子句:匹配指定小部件 ID
new String[]{String.valueOf(appWidgetIds[i])}); // WHERE 参数
}
}
// 私有方法:根据小部件 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 + "<>?", // 条件:小部件 ID 匹配且不在垃圾箱中
new String[]{String.valueOf(widgetId), String.valueOf(Notes.ID_TRASH_FOLER)}, // 参数值
null); // 排序方式(此处为 null即不排序
}
// 受保护方法:更新小部件显示内容的公共接口
protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// 默认调用私有方法,并将隐私模式设置为 false
update(context, appWidgetManager, appWidgetIds, false);
}
// 私有方法:根据隐私模式,更新小部件显示内容
private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds,
boolean privacyMode) {
// 遍历所有小部件 ID
for (int i = 0; i < appWidgetIds.length; i++) {
// 如果小部件 ID 无效,则跳过
if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) {
// 获取默认的背景颜色 ID
int bgId = ResourceParser.getDefaultBgId(context);
// 初始化笔记摘要为空字符串
String snippet = "";
// 创建一个 Intent指定跳转到 NoteEditActivity
Intent intent = new Intent(context, NoteEditActivity.class);
// 设置 Intent 的标志,确保活动以单一实例模式启动
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
// 将小部件 ID 和类型作为额外数据加入 Intent
intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]);
intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType());
// 查询数据库,获取与当前小部件 ID 关联的笔记信息
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;
}
// 从查询结果中获取笔记摘要和背景颜色 ID
snippet = c.getString(COLUMN_SNIPPET);
bgId = c.getInt(COLUMN_BG_COLOR_ID);
// 将笔记 ID 添加到 Intent 的额外数据中
intent.putExtra(Intent.EXTRA_UID, c.getLong(COLUMN_ID));
// 设置 Intent 的操作类型为查看
intent.setAction(Intent.ACTION_VIEW);
} else {
// 如果查询结果为空,则设置默认的内容和操作类型
snippet = context.getResources().getString(R.string.widget_havenot_content);
intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
}
// 如果 Cursor 对象不为空,则关闭以释放资源
if (c != null) {
c.close();
}
// 创建 RemoteViews 对象,用于更新小部件的布局
RemoteViews rv = new RemoteViews(context.getPackageName(), getLayoutId());
// 设置小部件的背景图片资源
rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId));
// 将背景颜色 ID 添加到 Intent 的额外数据中
intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId);
// 声明 PendingIntent 对象,用于处理小部件的点击事件
PendingIntent pendingIntent = null;
if (privacyMode) {
// 如果处于隐私模式,则显示隐私模式文本
rv.setTextViewText(R.id.widget_text,
context.getString(R.string.widget_under_visit_mode));
// 设置 PendingIntent点击时跳转到 NotesListActivity
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 = PendingIntent.getActivity(context, appWidgetIds[i], intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
// 为小部件的文本区域设置点击事件
rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent);
// 更新小部件显示内容
appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
}
}
}
// 抽象方法:获取背景资源的 ID具体实现由子类提供
protected abstract int getBgResourceId(int bgId);
// 抽象方法:获取小部件布局的资源 ID具体实现由子类提供
protected abstract int getLayoutId();
// 抽象方法:获取小部件的类型,具体实现由子类提供
protected abstract int getWidgetType();
}