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.
git-test/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java

225 lines
8.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;
/**
* 笔记小组件基类
* <p>
* 该抽象类为所有笔记小组件提供核心功能包括小组件数据管理、UI更新、点击事件处理
* 和小组件删除管理。它支持不同的小组件类型和布局,通过抽象方法让子类实现特定的
* 布局和资源配置
* </p>
*/
public abstract class NoteWidgetProvider extends AppWidgetProvider {
/**
* 小组件数据查询的投影列数组
* <p>
* 定义了从数据库查询笔记数据时需要获取的列包括笔记ID、背景颜色ID和摘要内容
* </p>
*/
public static final String [] PROJECTION = new String [] {
NoteColumns.ID,
NoteColumns.BG_COLOR_ID,
NoteColumns.SNIPPET
};
/**
* 查询结果中ID列的索引
*/
public static final int COLUMN_ID = 0;
/**
* 查询结果中背景颜色ID列的索引
*/
public static final int COLUMN_BG_COLOR_ID = 1;
/**
* 查询结果中摘要内容列的索引
*/
public static final int COLUMN_SNIPPET = 2;
/**
* 日志标签,用于小组件相关的日志输出
*/
private static final String TAG = "NoteWidgetProvider";
/**
* 当小组件被删除时调用的方法
* <p>
* 该方法将数据库中与被删除小组件关联的笔记的WIDGET_ID字段更新为无效值
* 解除笔记与已删除小组件的关联关系
* </p>
* @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);
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关联的笔记信息
* <p>
* 该方法从数据库中查询与给定小组件ID关联的笔记数据并排除已删除到回收站的笔记
* </p>
* @param context 上下文对象
* @param widgetId 要查询的小组件ID
* @return 返回包含笔记信息的Cursor对象使用PROJECTION中定义的列
*/
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和数据
* <p>
* 该方法是update方法的公共保护接口默认使用非隐私模式更新小组件
* </p>
* @param context 上下文对象
* @param appWidgetManager 小组件管理器
* @param appWidgetIds 要更新的小组件ID数组
*/
protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
update(context, appWidgetManager, appWidgetIds, false);
}
/**
* 更新小组件的UI和数据私有实现
* <p>
* 该方法负责实际更新小组件的内容,支持隐私模式和正常模式:
* 1. 查询与小组件关联的笔记信息
* 2. 根据查询结果设置小组件显示的文本和背景
* 3. 创建点击小组件时的PendingIntent
* 4. 在隐私模式下显示特定提示文本并跳转到笔记列表
* 5. 在正常模式下显示笔记内容并支持查看或创建笔记
* </p>
* @param context 上下文对象
* @param 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 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);
}
}
}
/**
* 根据背景颜色ID获取对应的背景资源ID
* <p>
* 该方法由子类实现用于将数据库中的背景颜色ID转换为实际的资源ID
* </p>
* @param bgId 数据库中的背景颜色ID
* @return 对应的背景资源ID
*/
protected abstract int getBgResourceId(int bgId);
/**
* 获取小组件的布局ID
* <p>
* 该方法由子类实现返回特定小组件类型的布局资源ID
* </p>
* @return 小组件布局资源ID
*/
protected abstract int getLayoutId();
/**
* 获取小组件类型
* <p>
* 该方法由子类实现,返回特定小组件的类型标识
* </p>
* @return 小组件类型标识
*/
protected abstract int getWidgetType();
}