From f8040d695ec2c7e53676b185015c15f0eb4cc58a Mon Sep 17 00:00:00 2001 From: ywzx <2965788399@qq.com> Date: Fri, 18 Oct 2024 16:44:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B3=A8=E9=87=8A=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NoteWidgetProvider.java | 254 ++++++++++++++++++++----------------- NoteWidgetProvider_2x.java | 56 ++++++++ NoteWidgetProvider_4x.java | 65 ++++++++++ 3 files changed, 260 insertions(+), 115 deletions(-) create mode 100644 NoteWidgetProvider_2x.java create mode 100644 NoteWidgetProvider_4x.java diff --git a/NoteWidgetProvider.java b/NoteWidgetProvider.java index ec6f819..3582889 100644 --- a/NoteWidgetProvider.java +++ b/NoteWidgetProvider.java @@ -14,119 +14,143 @@ * 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, - 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) { - ContentValues values = new ContentValues(); - values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_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])}); - } - } - - 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); - } - - 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 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 rv = new RemoteViews(context.getPackageName(), getLayoutId()); - rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId)); - intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId); - /** - * Generate the pending intent to start host for the widget - */ - PendingIntent pendingIntent = null; - 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); - } - } - } - - protected abstract int getBgResourceId(int bgId); - - protected abstract int getLayoutId(); - - protected abstract int getWidgetType(); +package net.micode.notes.widget; + +import android.app.PendingIntent; // 用于处理延迟执行的Intent +import android.appwidget.AppWidgetManager; // 管理应用小部件的类 +import android.appwidget.AppWidgetProvider; // 小部件的基类 +import android.content.ContentValues; // 用于向ContentProvider提供新值 +import android.content.Context; // 提供应用环境信息的类 +import android.content.Intent; // 用于不同组件间通信的类 +import android.database.Cursor; // 用于遍历查询结果的类 +import android.util.Log; // 用于打印日志信息 +import android.widget.RemoteViews; // 用于在远程视图中更新小部件的UI + +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; // 编辑笔记的Activity +import net.micode.notes.ui.NotesListActivity; // 笔记列表的Activity + +// 定义一个抽象类,用于实现自定义笔记小部件 +public abstract class NoteWidgetProvider extends AppWidgetProvider { + // 定义查询笔记时需要的列 + public static final String [] PROJECTION = new String [] { + NoteColumns.ID, // 笔记ID + NoteColumns.BG_COLOR_ID, // 笔记背景颜色ID + NoteColumns.SNIPPET // 笔记摘要 + }; + + // 定义列的索引,用于从Cursor中获取数据 + 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) { + // 更新被删除小部件对应的笔记中的WIDGET_ID为无效值 + ContentValues values = new ContentValues(); + values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_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])}); + } + } + + // 根据小部件ID获取笔记信息 + 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); + } + + // 更新小部件的UI(公开方法) + protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + update(context, appWidgetManager, appWidgetIds, false); + } + + // 更新小部件的UI(私有方法,支持隐私模式) + 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) { + // 获取默认背景ID和摘要文本 + int bgId = ResourceParser.getDefaultBgId(context); + String snippet = ""; + // 创建跳转到编辑笔记Activity的Intent + 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) { + // 如果有多条记录,打印错误日志并关闭Cursor + Log.e(TAG, "Multiple message with same widget id:" + appWidgetIds[i]); + c.close(); + return; + } + // 从Cursor中获取摘要和背景ID,并设置Intent的额外数据 + 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 { + // 如果没有找到笔记,设置默认摘要文本和Intent动作 + 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)); + 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, appWidgetIds[i], new Intent( + context, NotesListActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); + } else { + // 非隐私模式下,设置文本为摘要,并创建跳转到编辑笔记的PendingIntent + 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 + protected abstract int getBgResourceId(int bgId); + + // 抽象方法,用于获取小部件的布局ID + protected abstract int getLayoutId(); + + // 抽象方法,用于获取小部件的类型 + protected abstract int getWidgetType(); } diff --git a/NoteWidgetProvider_2x.java b/NoteWidgetProvider_2x.java new file mode 100644 index 0000000..d273f4e --- /dev/null +++ b/NoteWidgetProvider_2x.java @@ -0,0 +1,56 @@ +/* + * 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.appwidget.AppWidgetManager; // 导入AppWidgetManager类,用于管理应用小部件 +import android.content.Context; // 导入Context类,用于提供应用环境的全局信息 + +import net.micode.notes.R; // 导入R类,用于访问应用的资源,如布局文件、字符串等 +import net.micode.notes.data.Notes; // 导入Notes类,可能包含笔记的存储、类型定义等 +import net.micode.notes.tool.ResourceParser; // 导入ResourceParser工具类,用于解析资源 + +// NoteWidgetProvider_2x类,继承自NoteWidgetProvider,用于显示2x大小的笔记小部件 +public class NoteWidgetProvider_2x extends NoteWidgetProvider { + + // 当小部件需要更新时调用此方法 + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + // 调用父类的update方法,传入上下文、小部件管理器和小部件ID数组 + super.update(context, appWidgetManager, appWidgetIds); + } + + // 获取当前小部件布局的资源ID + @Override + protected int getLayoutId() { + // 返回R.layout.widget_2x,这是定义2x大小小部件布局的XML文件的资源ID + return R.layout.widget_2x; + } + + // 根据传入的背景ID,获取对应的背景资源ID + @Override + protected int getBgResourceId(int bgId) { + // 使用ResourceParser.WidgetBgResources的getWidget2xBgResource方法,根据背景ID获取2x小部件的背景资源ID + return ResourceParser.WidgetBgResources.getWidget2xBgResource(bgId); + } + + // 获取当前小部件的类型 + @Override + protected int getWidgetType() { + // 返回Notes.TYPE_WIDGET_2X,这是一个定义在Notes类中的常量,表示2x大小的小部件类型 + return Notes.TYPE_WIDGET_2X; + } +} \ No newline at end of file diff --git a/NoteWidgetProvider_4x.java b/NoteWidgetProvider_4x.java new file mode 100644 index 0000000..ca135f2 --- /dev/null +++ b/NoteWidgetProvider_4x.java @@ -0,0 +1,65 @@ +/* + * 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; + +// 导入必要的Android和项目相关的类 +import android.appwidget.AppWidgetManager; // 用于管理应用小部件的类 +import android.content.Context; // 提供应用环境全局信息的类 + +import net.micode.notes.R; // 访问应用资源的类 +import net.micode.notes.data.Notes; // 可能包含笔记数据的存储、类型定义等 +import net.micode.notes.tool.ResourceParser; // 用于解析资源的工具类 + +// NoteWidgetProvider_4x类,继承自NoteWidgetProvider,用于显示4x大小的笔记小部件 +public class NoteWidgetProvider_4x extends NoteWidgetProvider { + + // 当小部件需要更新时,系统会调用此方法 + // 参数包括上下文(Context)、小部件管理器(AppWidgetManager)和小部件ID数组(int[]) + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + // 调用父类的update方法,将更新请求传递给父类处理 + // 父类可能会根据小部件ID数组更新一个或多个小部件 + super.update(context, appWidgetManager, appWidgetIds); + } + + // 获取当前小部件布局的资源ID + // 这个方法被父类中的某些方法调用,用于加载小部件的UI布局 + @Override + protected int getLayoutId() { + // 返回R.layout.widget_4x,这是定义4x大小小部件布局的XML文件的资源ID + return R.layout.widget_4x; + } + + // 根据传入的背景ID,获取对应的背景资源ID + // 这个方法可能被父类中的某些方法调用,用于设置小部件的背景 + @Override + protected int getBgResourceId(int bgId) { + // 使用ResourceParser.WidgetBgResources的getWidget4xBgResource方法 + // 根据背景ID获取4x小部件的背景资源ID + return ResourceParser.WidgetBgResources.getWidget4xBgResource(bgId); + } + + // 获取当前小部件的类型 + // 这个方法可能被父类中的某些方法调用,用于区分不同类型的小部件 + @Override + protected int getWidgetType() { + // 返回Notes.TYPE_WIDGET_4X,这是一个定义在Notes类中的常量 + // 表示4x大小的小部件类型 + return Notes.TYPE_WIDGET_4X; + } +} \ No newline at end of file