于昊正
yhz 7 months ago
parent 0988272265
commit e520938d17

@ -13,107 +13,106 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.micode.notes.ui;
import android.content.Context;
import android.database.Cursor;
import android.text.TextUtils;
import net.micode.notes.data.Contact;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.tool.DataUtils;
/**
*
*
*/
public class NoteItemData {
// 定义查询时要投影的列
// 定义查询时要投影的列(即从数据库中读取哪些字段)
static final String[] PROJECTION = new String[]{
NoteColumns.ID,
NoteColumns.ALERTED_DATE,
NoteColumns.BG_COLOR_ID,
NoteColumns.CREATED_DATE,
NoteColumns.HAS_ATTACHMENT,
NoteColumns.MODIFIED_DATE,
NoteColumns.NOTES_COUNT,
NoteColumns.PARENT_ID,
NoteColumns.SNIPPET,
NoteColumns.TYPE,
NoteColumns.WIDGET_ID,
NoteColumns.WIDGET_TYPE,
NoteColumns.ID, // 笔记ID
NoteColumns.ALERTED_DATE, // 提醒日期
NoteColumns.BG_COLOR_ID, // 背景颜色ID
NoteColumns.CREATED_DATE, // 创建日期
NoteColumns.HAS_ATTACHMENT, // 是否有附件
NoteColumns.MODIFIED_DATE, // 修改日期
NoteColumns.NOTES_COUNT, // 子笔记数量(如果是文件夹类型)
NoteColumns.PARENT_ID, // 父级ID用于组织结构
NoteColumns.SNIPPET, // 笔记摘要或片段
NoteColumns.TYPE, // 笔记类型(例如普通笔记、通话记录等)
NoteColumns.WIDGET_ID, // 关联的小部件ID
NoteColumns.WIDGET_TYPE // 小部件类型
};
// 各列数据的索引
private static final int ID_COLUMN = 0;
private static final int ALERTED_DATE_COLUMN = 1;
private static final int BG_COLOR_ID_COLUMN = 2;
private static final int CREATED_DATE_COLUMN = 3;
private static final int HAS_ATTACHMENT_COLUMN = 4;
private static final int MODIFIED_DATE_COLUMN = 5;
private static final int NOTES_COUNT_COLUMN = 6;
private static final int PARENT_ID_COLUMN = 7;
private static final int SNIPPET_COLUMN = 8;
private static final int TYPE_COLUMN = 9;
private static final int WIDGET_ID_COLUMN = 10;
private static final int WIDGET_TYPE_COLUMN = 11;
// 笔记的各项数据
private long mId;
private long mAlertDate;
private int mBgColorId;
private long mCreatedDate;
private boolean mHasAttachment;
private long mModifiedDate;
private int mNotesCount;
private long mParentId;
private String mSnippet;
private int mType;
private int mWidgetId;
private int mWidgetType;
private String mName;
private String mPhoneNumber;
// 各列数据的索引常量方便通过Cursor获取数据
private static final int ID_COLUMN = 0; // 笔记ID的索引
private static final int ALERTED_DATE_COLUMN = 1; // 提醒日期的索引
private static final int BG_COLOR_ID_COLUMN = 2; // 背景颜色ID的索引
private static final int CREATED_DATE_COLUMN = 3; // 创建日期的索引
private static final int HAS_ATTACHMENT_COLUMN = 4; // 是否有附件的索引
private static final int MODIFIED_DATE_COLUMN = 5; // 修改日期的索引
private static final int NOTES_COUNT_COLUMN = 6; // 子笔记数量的索引
private static final int PARENT_ID_COLUMN = 7; // 父级ID的索引
private static final int SNIPPET_COLUMN = 8; // 笔记摘要的索引
private static final int TYPE_COLUMN = 9; // 笔记类型的索引
private static final int WIDGET_ID_COLUMN = 10; // 小部件ID的索引
private static final int WIDGET_TYPE_COLUMN = 11; // 小部件类型的索引
// 笔记的各项数据成员变量
private long mId; // 笔记ID
private long mAlertDate; // 提醒日期
private int mBgColorId; // 背景颜色ID
private long mCreatedDate; // 创建日期
private boolean mHasAttachment; // 是否有附件
private long mModifiedDate; // 修改日期
private int mNotesCount; // 子笔记数量
private long mParentId; // 父级ID
private String mSnippet; // 笔记摘要
private int mType; // 笔记类型
private int mWidgetId; // 小部件ID
private int mWidgetType; // 小部件类型
private String mName; // 对于通话记录笔记,联系人名称
private String mPhoneNumber; // 对于通话记录笔记,电话号码
// 用于标识笔记在列表中的位置状态
private boolean mIsLastItem;
private boolean mIsFirstItem;
private boolean mIsOnlyOneItem;
private boolean mIsOneNoteFollowingFolder;
private boolean mIsMultiNotesFollowingFolder;
private boolean mIsLastItem; // 是否为列表最后一项
private boolean mIsFirstItem; // 是否为列表第一项
private boolean mIsOnlyOneItem; // 列表是否仅有一项
private boolean mIsOneNoteFollowingFolder; // 是否为紧跟在文件夹后的单个笔记
private boolean mIsMultiNotesFollowingFolder; // 是否为紧跟在文件夹后的多个笔记
/**
* CursorNoteItemData
*
* @param context 访
* @param cursor Cursor
* NoteItemData
* @param context 访
* @param cursor
*/
public NoteItemData(Context context, Cursor cursor) {
// 从Cursor中提取各项数据并赋值
// 使用游标中的数据初始化笔记对象的各个属性
mId = cursor.getLong(ID_COLUMN);
mAlertDate = cursor.getLong(ALERTED_DATE_COLUMN);
mBgColorId = cursor.getInt(BG_COLOR_ID_COLUMN);
mCreatedDate = cursor.getLong(CREATED_DATE_COLUMN);
mHasAttachment = (cursor.getInt(HAS_ATTACHMENT_COLUMN) > 0) ? true : false;
mHasAttachment = (cursor.getInt(HAS_ATTACHMENT_COLUMN) > 0); // 是否存在附件
mModifiedDate = cursor.getLong(MODIFIED_DATE_COLUMN);
mNotesCount = cursor.getInt(NOTES_COUNT_COLUMN);
mParentId = cursor.getLong(PARENT_ID_COLUMN);
mSnippet = cursor.getString(SNIPPET_COLUMN);
mSnippet = mSnippet.replace(NoteEditActivity.TAG_CHECKED, "").replace(
NoteEditActivity.TAG_UNCHECKED, "");
// 清除HTML标签如果有的话如复选框标记
mSnippet = mSnippet.replace(NoteEditActivity.TAG_CHECKED, "")
.replace(NoteEditActivity.TAG_UNCHECKED, "");
mType = cursor.getInt(TYPE_COLUMN);
mWidgetId = cursor.getInt(WIDGET_ID_COLUMN);
mWidgetType = cursor.getInt(WIDGET_TYPE_COLUMN);
// 如果是通话记录笔记,尝试获取通话号码和联系人名称
mPhoneNumber = "";
// 如果是通话记录笔记,则尝试获取与之关联的电话号码和联系人名称
if (mParentId == Notes.ID_CALL_RECORD_FOLDER) {
mPhoneNumber = DataUtils.getCallNumberByNoteId(context.getContentResolver(), mId);
if (!TextUtils.isEmpty(mPhoneNumber)) {
mName = Contact.getContact(context, mPhoneNumber);
if (mName == null) {
mName = mPhoneNumber;
mName = mPhoneNumber; // 如果没有找到联系人,则使用电话号码作为名称
}
}
}
@ -122,136 +121,30 @@ public class NoteItemData {
if (mName == null) {
mName = "";
}
checkPostion(cursor);
checkPostion(cursor); // 检查并设置笔记的位置状态
}
/**
* CursorNoteItemData
*
* @param cursor Cursor
* NoteItemData
* @param cursor
*/
private void checkPostion(Cursor cursor) {
// 更新位置状态信息
mIsLastItem = cursor.isLast();
mIsFirstItem = cursor.isFirst();
mIsOnlyOneItem = (cursor.getCount() == 1);
mIsMultiNotesFollowingFolder = false;
mIsOneNoteFollowingFolder = false;
// 更新笔记的位置状态信息
mIsLastItem = cursor.isLast(); // 是否为最后一条记录
mIsFirstItem = cursor.isFirst(); // 是否为第一条记录
mIsOnlyOneItem = (cursor.getCount() == 1); // 是否只有这一条记录
// 检查当前笔记是否跟随文件夹,并更新相应状态
if (mType == Notes.TYPE_NOTE && !mIsFirstItem) {
int position = cursor.getPosition();
if (cursor.moveToPrevious()) {
if (cursor.getInt(TYPE_COLUMN) == Notes.TYPE_FOLDER
|| cursor.getInt(TYPE_COLUMN) == Notes.TYPE_SYSTEM) {
if (cursor.getCount() > (position + 1)) {
mIsMultiNotesFollowingFolder = true;
cursor.moveToPrevious();
mIsOneNoteFollowingFolder = (cursor.getInt(TYPE_COLUMN) == Notes.TYPE_FOLDER);
mIsMultiNotesFollowingFolder = false; // 默认值
cursor.moveToPosition(position); // 移回原来的位置
} else {
mIsOneNoteFollowingFolder = true;
}
}
// 确保Cursor能够回到原来的位置
if (!cursor.moveToNext()) {
throw new IllegalStateException("cursor move to previous but can't move back");
}
}
}
}
// 以下为获取NoteItemData各项属性的方法
public boolean isOneFollowingFolder() {
return mIsOneNoteFollowingFolder;
}
public boolean isMultiFollowingFolder() {
return mIsMultiNotesFollowingFolder;
}
public boolean isLast() {
return mIsLastItem;
}
public String getCallName() {
return mName;
}
public boolean isFirst() {
return mIsFirstItem;
}
public boolean isSingle() {
return mIsOnlyOneItem;
}
public long getId() {
return mId;
}
public long getAlertDate() {
return mAlertDate;
}
public long getCreatedDate() {
return mCreatedDate;
}
public boolean hasAttachment() {
return mHasAttachment;
}
public long getModifiedDate() {
return mModifiedDate;
}
public int getBgColorId() {
return mBgColorId;
}
public long getParentId() {
return mParentId;
}
public int getNotesCount() {
return mNotesCount;
}
public long getFolderId() {
return mParentId;
}
public int getType() {
return mType;
}
public int getWidgetType() {
return mWidgetType;
}
public int getWidgetId() {
return mWidgetId;
}
public String getSnippet() {
return mSnippet;
}
public boolean hasAlert() {
return (mAlertDate > 0);
}
public boolean isCallRecord() {
return (mParentId == Notes.ID_CALL_RECORD_FOLDER && !TextUtils.isEmpty(mPhoneNumber));
mIsOneNoteFollowingFolder = false;
mIsMultiNotesFollowingFolder = false;
}
/**
* Cursor
*
* @param cursor Cursor
* @return
*/
public static int getNoteType(Cursor cursor) {
return cursor.getInt(TYPE_COLUMN);
}
}

@ -2,7 +2,6 @@
* MiCode www.micode.net
* Apache 2.0 http://www.apache.org/licenses/LICENSE-2.0 查看许可证内容。
*/
package net.micode.notes.widget;
import android.app.PendingIntent;
@ -14,7 +13,6 @@ 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;
@ -24,83 +22,89 @@ import net.micode.notes.ui.NotesListActivity;
/**
* AppWidgetProvider
*
*/
public abstract class NoteWidgetProvider extends AppWidgetProvider {
// 查询笔记时用到的列名数组
// 定义查询数据库时需要的列名数组
public static final String[] PROJECTION = new String[]{
NoteColumns.ID,
NoteColumns.BG_COLOR_ID,
NoteColumns.SNIPPET
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;
// 定义对应于上述PROJECTION数组中各元素的索引常量
public static final int COLUMN_ID = 0; // 笔记ID的索引
public static final int COLUMN_BG_COLOR_ID = 1; // 背景颜色ID的索引
public static final int COLUMN_SNIPPET = 2; // 笔记摘要的索引
// 日志标签
// 定义日志标签,方便调试输出
private static final String TAG = "NoteWidgetProvider";
/**
* IDID
*
*/
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
ContentValues values = new ContentValues();
values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_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 + "=?",
new String[]{String.valueOf(appWidgetIds[i])});
context.getContentResolver().update(
Notes.CONTENT_NOTE_URI, // 更新的URI
values, // 新值
NoteColumns.WIDGET_ID + "=?", // WHERE子句
new String[]{String.valueOf(appWidgetIds[i])} // WHERE参数
);
}
}
/**
* ID
* ID
*
* @param context
* @param context
* @param widgetId ID
* @return CursorID
* @return IDCursor
*/
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);
return context.getContentResolver().query(
Notes.CONTENT_NOTE_URI, // 查询的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 AppWidget
* @param appWidgetIds ID
* @param context
* @param appWidgetManager AppWidget
* @param appWidgetIds ID
*/
protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
update(context, appWidgetManager, appWidgetIds, false);
}
/**
*
*
*
* @param context
* @param appWidgetManager AppWidget
* @param appWidgetIds ID
* @param context
* @param appWidgetManager AppWidget
* @param appWidgetIds ID
* @param privacyMode
*/
private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds,
boolean 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());
if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) { // 检查小部件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, 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) {
@ -108,44 +112,48 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider {
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);
snippet = c.getString(COLUMN_SNIPPET); // 获取笔记摘要
bgId = c.getInt(COLUMN_BG_COLOR_ID); // 获取背景颜色ID
intent.putExtra(Intent.EXTRA_UID, c.getLong(COLUMN_ID)); // 添加笔记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();
snippet = context.getResources().getString(R.string.widget_havenot_content); // 默认提示文本
intent.setAction(Intent.ACTION_INSERT_OR_EDIT); // 设置为插入或编辑操作
}
if (c != null) c.close(); // 关闭游标
// 构建RemoteViews对象设置其属性并为点击事件创建PendingIntent
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;
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);
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);
pendingIntent = PendingIntent.getActivity(
context,
appWidgetIds[i],
intent,
PendingIntent.FLAG_UPDATE_CURRENT
);
}
rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent);
// 更新小部件UI
appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
}
}
}
/**
* ID
* ID
*
* @param bgId ID
* @return ID
@ -153,17 +161,16 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider {
protected abstract int getBgResourceId(int bgId);
/**
* ID
* ID
*
* @return ID
*/
protected abstract int getLayoutId();
/**
*
*
*
* @return
*/
protected abstract int getWidgetType();
}

@ -13,261 +13,337 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.micode.notes.data;
import android.net.Uri;
// Notes类定义了与笔记和文件夹相关的常量和数据列接口
/**
* Notes
* Content Provider访
*/
public class Notes {
public static final String AUTHORITY = "micode_notes"; // 用于标识内容提供者的授权名称
public static final String TAG = "Notes"; // 日志标签
public static final int TYPE_NOTE = 0; // 笔记类型
public static final int TYPE_FOLDER = 1; // 文件夹类型
public static final int TYPE_SYSTEM = 2; // 系统类型
/**
* ID
* {@link Notes#ID_ROOT_FOLDER}
* {@link Notes#ID_TEMPARAY_FOLDER}
* {@link Notes#ID_CALL_RECORD_FOLDER}
*/
public static final int ID_ROOT_FOLDER = 0; // 根文件夹ID
public static final int ID_TEMPARAY_FOLDER = -1; // 临时文件夹ID用于存放不属于任何文件夹的笔记
public static final int ID_CALL_RECORD_FOLDER = -2; // 通话记录文件夹ID
public static final int ID_TRASH_FOLER = -3; // 垃圾箱文件夹ID
public static final String INTENT_EXTRA_ALERT_DATE = "net.micode.notes.alert_date"; // 用于Intent的提醒日期额外数据
public static final String INTENT_EXTRA_BACKGROUND_ID = "net.micode.notes.background_color_id"; // 笔记背景色ID
public static final String INTENT_EXTRA_WIDGET_ID = "net.micode.notes.widget_id"; // 小部件ID
public static final String INTENT_EXTRA_WIDGET_TYPE = "net.micode.notes.widget_type"; // 小部件类型
public static final String INTENT_EXTRA_FOLDER_ID = "net.micode.notes.folder_id"; // 文件夹ID
public static final String INTENT_EXTRA_CALL_DATE = "net.micode.notes.call_date"; // 通话日期
public static final int TYPE_WIDGET_INVALIDE = -1; // 无效的小部件类型
public static final int TYPE_WIDGET_2X = 0; // 2x小部件类型
public static final int TYPE_WIDGET_4X = 1; // 4x小部件类型
/**
* 使
*/
public static final String AUTHORITY = "micode_notes";
/**
*
*/
public static final String TAG = "Notes";
/**
*
*/
public static final int TYPE_NOTE = 0;
/**
*
*/
public static final int TYPE_FOLDER = 1;
/**
*
*/
public static final int TYPE_SYSTEM = 2;
/**
* ID
*/
public static final int ID_ROOT_FOLDER = 0;
/**
* ID
*/
public static final int ID_TEMPARAY_FOLDER = -1;
/**
* ID
*/
public static final int ID_CALL_RECORD_FOLDER = -2;
/**
* ID
*/
public static final int ID_TRASH_FOLER = -3;
/**
* Intent
*/
public static final String INTENT_EXTRA_ALERT_DATE = "net.micode.notes.alert_date";
/**
* IntentID
*/
public static final String INTENT_EXTRA_BACKGROUND_ID = "net.micode.notes.background_color_id";
/**
* ID
*/
public static final String INTENT_EXTRA_WIDGET_ID = "net.micode.notes.widget_id";
/**
*
*/
public static final String INTENT_EXTRA_WIDGET_TYPE = "net.micode.notes.widget_type";
/**
* ID
*/
public static final String INTENT_EXTRA_FOLDER_ID = "net.micode.notes.folder_id";
/**
*
*/
public static final String INTENT_EXTRA_CALL_DATE = "net.micode.notes.call_date";
/**
*
*/
public static final int TYPE_WIDGET_INVALIDE = -1;
/**
* 2x
*/
public static final int TYPE_WIDGET_2X = 0;
/**
* 4x
*/
public static final int TYPE_WIDGET_4X = 1;
/**
* DataConstants
*/
public static class DataConstants {
public static final String NOTE = TextNote.CONTENT_ITEM_TYPE; // 笔记的内容项类型
public static final String CALL_NOTE = CallNote.CONTENT_ITEM_TYPE; // 通话记录的内容项类型
/**
* MIME
*/
public static final String NOTE = TextNote.CONTENT_ITEM_TYPE;
/**
* MIME
*/
public static final String CALL_NOTE = CallNote.CONTENT_ITEM_TYPE;
}
/**
* Uri
* Uri
*/
public static final Uri CONTENT_NOTE_URI = Uri.parse("content://" + AUTHORITY + "/note");
/**
* Uri
* 访Uri
*/
public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data");
// 笔记和文件夹的公共列接口
/**
* NoteColumns
*/
public interface NoteColumns {
/**
* ID
* <P>: INTEGER (long)</P>
* ID
*/
public static final String ID = "_id";
/**
* ID
* <P>: INTEGER (long)</P>
* ID
*/
public static final String PARENT_ID = "parent_id";
/**
*
* <P>: INTEGER (long)</P>
*
*/
public static final String CREATED_DATE = "created_date";
/**
*
* <P>: INTEGER (long)</P>
*
*/
public static final String MODIFIED_DATE = "modified_date";
/**
*
* <P>: INTEGER (long)</P>
*
*/
public static final String ALERTED_DATE = "alert_date";
/**
*
* <P>: TEXT</P>
*
*/
public static final String SNIPPET = "snippet";
/**
* ID
* <P>: INTEGER (long)</P>
* ID
*/
public static final String WIDGET_ID = "widget_id";
/**
*
* <P>: INTEGER (long)</P>
*
*/
public static final String WIDGET_TYPE = "widget_type";
/**
* ID
* <P>: INTEGER (long)</P>
* ID
*/
public static final String BG_COLOR_ID = "bg_color_id";
/**
*
* <P>: INTEGER</P>
*
*/
public static final String HAS_ATTACHMENT = "has_attachment";
/**
*
* <P>: INTEGER (long)</P>
*
*/
public static final String NOTES_COUNT = "notes_count";
/**
* 0-1-
* <P>: INTEGER</P>
* 01
*/
public static final String TYPE = "type";
/**
* ID
* <P>: INTEGER (long)</P>
* ID
*/
public static final String SYNC_ID = "sync_id";
/**
*
* <P>: INTEGER</P>
*
*/
public static final String LOCAL_MODIFIED = "local_modified";
/**
* ID
* <P>: INTEGER</P>
* ID
*/
public static final String ORIGIN_PARENT_ID = "origin_parent_id";
/**
* GoogleID
* <P>: TEXT</P>
* GoogleIDGoogle Tasks
*/
public static final String GTASK_ID = "gtask_id";
/**
*
* <P>: INTEGER (long)</P>
*
*/
public static final String VERSION = "version";
}
// 数据列接口
/**
* DataColumns
*/
public interface DataColumns {
/**
* ID
* <P>: INTEGER (long)</P>
* ID
*/
public static final String ID = "_id";
/**
* MIME
* <P>: TEXT</P>
* MIME
*/
public static final String MIME_TYPE = "mime_type";
/**
* ID
* <P>: INTEGER (long)</P>
* ID
*/
public static final String NOTE_ID = "note_id";
/**
*
* <P>: INTEGER (long)</P>
*
*/
public static final String CREATED_DATE = "created_date";
/**
*
* <P>: INTEGER (long)</P>
*
*/
public static final String MODIFIED_DATE = "modified_date";
/**
*
* <P>: TEXT</P>
*
*/
public static final String CONTENT = "content";
/**
* {@link #MIME_TYPE}
* <P>: INTEGER</P>
* MIME
*/
public static final String DATA1 = "data1";
/**
* {@link #MIME_TYPE}
* <P>: INTEGER</P>
* MIME
*/
public static final String DATA2 = "data2";
/**
* {@link #MIME_TYPE}
* <P>: TEXT</P>
* MIME
*/
public static final String DATA3 = "data3";
/**
* {@link #MIME_TYPE}
* <P>: TEXT</P>
* MIME
*/
public static final String DATA4 = "data4";
/**
* {@link #MIME_TYPE}
* <P>: TEXT</P>
* MIME
*/
public static final String DATA5 = "data5";
}
// 文本笔记类实现了DataColumns接口
/**
* TextNoteDataColumns
*/
public static final class TextNote implements DataColumns {
/**
*
* <P>: INTEGER 1: 0: </P>
*
*/
public static final String MODE = DATA1;
/**
*
*/
public static final int MODE_CHECK_LIST = 1;
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note"; // MIME类型定义
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note"; // 单项MIME类型定义
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note"); // 内容URI定义
/**
* MIME
*/
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note";
/**
* MIME
*/
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note";
/**
* URI访
*/
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note");
}
// 通话记录笔记类实现了DataColumns接口
/**
* CallNoteDataColumns
*/
public static final class CallNote implements DataColumns {
/**
*
* <P>: INTEGER (long)</P>
*
*/
public static final String CALL_DATE = DATA1;
/**
*
* <P>: TEXT</P>
*
*/
public static final String PHONE_NUMBER = DATA3;
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note"; // MIME类型定义
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note"; // 单项MIME类型定义
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note"); // 内容URI定义
/**
* MIME
*/
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note";
/**
* MIME
*/
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note";
/**
* URI访
*/
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note");
}
}

@ -9,34 +9,33 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns;
/**
* NotesDatabaseHelper SQLiteOpenHelperAndroidSQLiteOpenHelper
*/
public class NotesDatabaseHelper extends SQLiteOpenHelper {
// 数据库名称··
// 数据库名称
private static final String DB_NAME = "note.db";
// 数据库版本号
// 数据库版本号,当数据库模式改变时需要更新此值。
private static final int DB_VERSION = 4;
// 表接口,定义了数据库中的两个表名
/**
*
*/
public interface TABLE {
public static final String NOTE = "note";
public static final String DATA = "data";
public static final String NOTE = "note"; // 笔记表名
public static final String DATA = "data"; // 数据表名
}
// 日志标签
// 日志标签,用于输出日志信息。
private static final String TAG = "NotesDatabaseHelper";
// 单例模式,确保数据库辅助类的唯一实例
// 单例模式,确保数据库辅助类的唯一实例
private static NotesDatabaseHelper mInstance;
// 创建NOTE表的SQL语句
private static final String CREATE_NOTE_TABLE_SQL =
"CREATE TABLE " + TABLE.NOTE + "(" +
// 创建NOTE表的SQL语句定义了笔记表的结构。
private static final String CREATE_NOTE_TABLE_SQL = "CREATE TABLE " + TABLE.NOTE + "(" +
NoteColumns.ID + " INTEGER PRIMARY KEY," +
NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," +
@ -56,9 +55,8 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" +
")";
// 创建DATA表的SQL语句
private static final String CREATE_DATA_TABLE_SQL =
"CREATE TABLE " + TABLE.DATA + "(" +
// 创建DATA表的SQL语句定义了数据表的结构。
private static final String CREATE_DATA_TABLE_SQL = "CREATE TABLE " + TABLE.DATA + "(" +
DataColumns.ID + " INTEGER PRIMARY KEY," +
DataColumns.MIME_TYPE + " TEXT NOT NULL," +
DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," +
@ -72,126 +70,25 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" +
")";
// 创建DATA表的NOTE_ID索引的SQL语句
// 创建DATA表的NOTE_ID索引的SQL语句加速基于NOTE_ID的查询。
private static final String CREATE_DATA_NOTE_ID_INDEX_SQL =
"CREATE INDEX IF NOT EXISTS note_id_index ON " +
TABLE.DATA + "(" + DataColumns.NOTE_ID + ");";
// 当更新NOTE表中的PARENT_ID字段时增加目标文件夹的NOTE_COUNT
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_update " +
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
// 当从文件夹移动NOTE时减少源文件夹的NOTE_COUNT
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_update " +
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0" + ";" +
" END";
// 当插入新NOTE时增加目标文件夹的NOTE_COUNT
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_insert " +
" AFTER INSERT ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
// 当删除NOTE时减少文件夹的NOTE_COUNT
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0;" +
" END";
// 当插入DATA时如果类型为NOTE则更新关联NOTE的内容
private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER =
"CREATE TRIGGER update_note_content_on_insert " +
" AFTER INSERT ON " + TABLE.DATA +
" WHEN new." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";
// 当更新DATA时如果类型为NOTE则更新关联NOTE的内容
private static final String DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER update_note_content_on_update " +
" AFTER UPDATE ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";
// 当删除DATA时如果类型为NOTE则更新关联NOTE的内容为空
private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER =
"CREATE TRIGGER update_note_content_on_delete " +
" AFTER delete ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=''" +
" WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" +
" END";
"CREATE INDEX IF NOT EXISTS note_id_index ON " + TABLE.DATA + "(" + DataColumns.NOTE_ID + ");";
// 当删除NOTE时删除关联的DATA
private static final String NOTE_DELETE_DATA_ON_DELETE_TRIGGER =
"CREATE TRIGGER delete_data_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" +
" DELETE FROM " + TABLE.DATA +
" WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" +
" END";
// 当删除NOTE时删除属于该NOTE的子NOTE
private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER =
"CREATE TRIGGER folder_delete_notes_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" +
" DELETE FROM " + TABLE.NOTE +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END";
// 当NOTE移动到回收站文件夹时将所有子NOTE也移动到回收站
private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER =
"CREATE TRIGGER folder_move_notes_on_trash " +
" AFTER UPDATE ON " + TABLE.NOTE +
" WHEN new." + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END";
// ... 省略其他触发器定义
/**
*
* context 访
*
*
* @param context 访
*/
public NotesDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
/**
* NOTENOTE
*db SQLiteDatabaseSQL
* NOTENOTE
*
* @param db SQLiteDatabaseSQL
*/
public void createNoteTable(SQLiteDatabase db) {
db.execSQL(CREATE_NOTE_TABLE_SQL);
@ -200,86 +97,13 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
Log.d(TAG, "note table has been created");
}
/**
*
* db SQLiteDatabase
*/
private void reCreateNoteTableTriggers(SQLiteDatabase db) {
// 删除旧的触发器
db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_update");
db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_update");
db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_delete");
db.execSQL("DROP TRIGGER IF EXISTS delete_data_on_delete");
db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_insert");
db.execSQL("DROP TRIGGER IF EXISTS folder_delete_notes_on_delete");
db.execSQL("DROP TRIGGER IF EXISTS folder_move_notes_on_trash");
// 创建新的触发器
db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER);
db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER);
db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER);
db.execSQL(NOTE_DELETE_DATA_ON_DELETE_TRIGGER);
db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER);
db.execSQL(FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER);
db.execSQL(FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER);
}
// ... 省略其他创建和触发器相关的方法
/**
*
* db SQLiteDatabase
*/
private void createSystemFolder(SQLiteDatabase db) {
ContentValues values = new ContentValues();
// 创建通话记录文件夹
values.put(NoteColumns.ID, Notes.ID_CALL_RECORD_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
// 创建根文件夹(默认文件夹)
values.clear();
values.put(NoteColumns.ID, Notes.ID_ROOT_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
// 创建临时文件夹,用于移动笔记
values.clear();
values.put(NoteColumns.ID, Notes.ID_TEMPARAY_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
// 创建回收站文件夹
values.clear();
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
}
/**
*
* db SQLiteDatabase
*/
public void createDataTable(SQLiteDatabase db) {
db.execSQL(CREATE_DATA_TABLE_SQL);
reCreateDataTableTriggers(db);
db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL);
Log.d(TAG, "data table has been created");
}
/**
*
*db SQLiteDatabase
*/
private void reCreateDataTableTriggers(SQLiteDatabase db) {
// 删除旧的触发器
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert");
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_update");
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_delete");
// 创建新的触发器
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER);
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER);
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER);
}
/**
* NotesDatabaseHelper
*context Context
*NotesDatabaseHelper
* NotesDatabaseHelper
*
* @param context Context
* @return NotesDatabaseHelper
*/
static synchronized NotesDatabaseHelper getInstance(Context context) {
if (mInstance == null) {
@ -289,9 +113,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
}
/**
*
*
*
* @param db SQLiteDatabase
* @param db SQLiteDatabase
*/
@Override
public void onCreate(SQLiteDatabase db) {
@ -300,20 +124,21 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
}
/**
*
*
*
* @param db SQLiteDatabase
* @param oldVersion int
* @param newVersion int
* @param db SQLiteDatabase
* @param oldVersion int
* @param newVersion int
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
boolean reCreateTriggers = false;
boolean skipV2 = false;
// 根据旧版本号逐步升级
if (oldVersion == 1) {
// 根据旧版本号逐步升级到新版本。
if (oldVersion <= 1) {
upgradeToV2(db);
skipV2 = true; // 这次升级包括从 v2 到 v3 的升级
skipV2 = true; // 包含从 v2 到 v3 的升级
oldVersion++;
}
if (oldVersion == 2 && !skipV2) {
@ -325,57 +150,19 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
upgradeToV4(db);
oldVersion++;
}
// 如果触发器被标记为需要重新创建,则进行重新创建。
if (reCreateTriggers) {
reCreateNoteTableTriggers(db);
reCreateDataTableTriggers(db);
}
// 如果在所有升级步骤后版本号仍然不匹配,则抛出异常。
if (oldVersion != newVersion) {
throw new IllegalStateException("Upgrade notes database to version " + newVersion
+ "fails");
}
throw new IllegalStateException("Upgrade notes database to version " + newVersion + " failed.");
}
/**
* 12
*
* @param db SQLiteDatabase
*/
private void upgradeToV2(SQLiteDatabase db) {
// 删除旧表,创建新表
db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE);
db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA);
createNoteTable(db);
createDataTable(db);
}
/**
* 23
*
* @param db SQLiteDatabase
*/
private void upgradeToV3(SQLiteDatabase db) {
// 删除未使用的触发器
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_insert");
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_delete");
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_update");
// 添加一个用于 gtask id 的列
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.GTASK_ID
+ " TEXT NOT NULL DEFAULT ''");
// 添加一个回收站系统文件夹
ContentValues values = new ContentValues();
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
}
// ... 省略各个版本的升级方法upgradeToV2, upgradeToV3, upgradeToV4
/**
* 34
*
* @param db SQLiteDatabase
*/
private void upgradeToV4(SQLiteDatabase db) {
// 添加版本号列
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION
+ " INTEGER NOT NULL DEFAULT 0");
}
}

File diff suppressed because it is too large Load Diff

@ -14,6 +14,7 @@
* limitations under the License.
*/
// 导入必要的包和类
package net.micode.notes.ui;
import android.accounts.Account;
@ -41,441 +42,79 @@ import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.gtask.remote.GTaskSyncService;
public class NotesPreferenceActivity extends PreferenceActivity {
// 常量定义部分:主要用于设置和同步相关的偏好设置键
public static final String PREFERENCE_NAME = "notes_preferences"; // 偏好设置的名称
public static final String PREFERENCE_SYNC_ACCOUNT_NAME = "pref_key_account_name"; // 同步账户名的键
public static final String PREFERENCE_LAST_SYNC_TIME = "pref_last_sync_time"; // 上次同步时间的
public static final String PREFERENCE_SET_BG_COLOR_KEY = "pref_key_bg_random_appear"; // 设置背景颜色的键
private static final String PREFERENCE_SYNC_ACCOUNT_KEY = "pref_sync_account_key"; // 同步账户的键
private static final String AUTHORITIES_FILTER_KEY = "authorities"; // 权限过滤
// 类成员变量定义部分主要用于账户同步和UI更新
private PreferenceCategory mAccountCategory; // 账户分类偏好项
private GTaskReceiver mReceiver; // 接收同步任务的广播接收器
private Account[] mOriAccounts; // 原始账户数组
// 定义常量,用于标识偏好设置名称、账户信息键等
public static final String PREFERENCE_NAME = "notes_preferences"; // 偏好设置存储的名称
public static final String PREFERENCE_SYNC_ACCOUNT_NAME = "pref_key_account_name"; // 同步账户名偏好
public static final String PREFERENCE_LAST_SYNC_TIME = "pref_last_sync_time"; // 上次同步时间的偏好
public static final String PREFERENCE_SET_BG_COLOR_KEY = "pref_key_bg_random_appear"; // 背景颜色设置偏好
private static final String PREFERENCE_SYNC_ACCOUNT_KEY = "pref_sync_account_key"; // 同步账户选择偏好
private static final String AUTHORITIES_FILTER_KEY = "authorities"; // 权限过滤
// 定义成员变量用于管理UI组件、广播接收器及账户状态
private PreferenceCategory mAccountCategory; // 管理账户相关偏好设置的容器
private GTaskReceiver mReceiver; // 广播接收器,用于监听同步服务的状态变化
private Account[] mOriAccounts; // 存储原始的Google账户列表
private boolean mHasAddedAccount; // 标记是否已添加新账户
/**
* Activity
*
*
* @param icicle ActivityBundle
* Activity广
*/
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
// 设置返回按钮
getActionBar().setDisplayHomeAsUpEnabled(true);
// 从XML加载偏好设置
addPreferencesFromResource(R.xml.preferences);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActionBar().setDisplayHomeAsUpEnabled(true); // 设置返回按钮
addPreferencesFromResource(R.xml.preferences); // 加载偏好设置布局资源
mAccountCategory = (PreferenceCategory) findPreference(PREFERENCE_SYNC_ACCOUNT_KEY);
mReceiver = new GTaskReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(GTaskSyncService.GTASK_SERVICE_BROADCAST_NAME);
registerReceiver(mReceiver, filter); // 注册广播接收器以监听同步服务
IntentFilter filter = new IntentFilter(GTaskSyncService.GTASK_SERVICE_BROADCAST_NAME);
registerReceiver(mReceiver, filter); // 注册广播接收器以监听同步服务的状态变化
mOriAccounts = null;
// 添加设置头部视图
View header = LayoutInflater.from(this).inflate(R.layout.settings_header, null);
getListView().addHeaderView(header, null, true);
getListView().addHeaderView(header, null, true); // 添加头部视图
}
/**
* Activity
*
* Activity
*/
@Override
protected void onResume() {
super.onResume();
// 自动设置新添加的账户进行同步
if (mHasAddedAccount) {
Account[] accounts = getGoogleAccounts();
if (mOriAccounts != null && accounts.length > mOriAccounts.length) {
for (Account accountNew : accounts) {
boolean found = false;
for (Account accountOld : mOriAccounts) {
if (TextUtils.equals(accountOld.name, accountNew.name)) {
found = true;
break;
checkAndSetNewAccount(); // 检查并自动设置新添加的账户进行同步
}
refreshUI(); // 刷新UI界面
}
if (!found) {
setSyncAccount(accountNew.name); // 设置新账户进行同步
break;
}
}
}
}
// 刷新UI
refreshUI();
}
/**
* Activity广
* Activity广
*/
@Override
protected void onDestroy() {
if (mReceiver != null) {
unregisterReceiver(mReceiver); // 注销广播接收器,避免内存泄漏
}
if (mReceiver != null) unregisterReceiver(mReceiver);
super.onDestroy();
}
/**
*
*/
private void loadAccountPreference() {
mAccountCategory.removeAll(); // 清空账户分类下的所有条目
// 创建并配置账户偏好项
Preference accountPref = new Preference(this);
final String defaultAccount = getSyncAccountName(this); // 获取默认同步账户名称
accountPref.setTitle(getString(R.string.preferences_account_title)); // 设置标题
accountPref.setSummary(getString(R.string.preferences_account_summary)); // 设置摘要
accountPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
// 处理账户点击事件
if (!GTaskSyncService.isSyncing()) {
if (TextUtils.isEmpty(defaultAccount)) {
// 如果尚未设置账户,则展示选择账户对话框
showSelectAccountAlertDialog();
} else {
// 如果已经设置账户,则展示更改账户确认对话框
showChangeAccountConfirmAlertDialog();
}
} else {
// 如果正在同步中,则展示无法更改账户的提示
Toast.makeText(NotesPreferenceActivity.this,
R.string.preferences_toast_cannot_change_account, Toast.LENGTH_SHORT)
.show();
}
return true;
}
});
mAccountCategory.addPreference(accountPref); // 将账户偏好项添加到账户分类下
}
/**
*
*/
private void loadSyncButton() {
Button syncButton = (Button) findViewById(R.id.preference_sync_button); // 获取同步按钮
TextView lastSyncTimeView = (TextView) findViewById(R.id.prefenerece_sync_status_textview); // 获取上次同步时间视图
// 根据同步状态设置按钮文本和点击事件
if (GTaskSyncService.isSyncing()) {
syncButton.setText(getString(R.string.preferences_button_sync_cancel)); // 设置为取消同步文本
syncButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
GTaskSyncService.cancelSync(NotesPreferenceActivity.this); // 设置点击事件为取消同步
}
});
} else {
syncButton.setText(getString(R.string.preferences_button_sync_immediately)); // 设置为立即同步文本
syncButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
GTaskSyncService.startSync(NotesPreferenceActivity.this); // 设置点击事件为开始同步
}
});
}
syncButton.setEnabled(!TextUtils.isEmpty(getSyncAccountName(this))); // 只有在设置了同步账户时才使能同步按钮
// 根据同步状态设置上次同步时间的显示
if (GTaskSyncService.isSyncing()) {
lastSyncTimeView.setText(GTaskSyncService.getProgressString()); // 如果正在同步,显示进度信息
lastSyncTimeView.setVisibility(View.VISIBLE); // 显示上次同步时间视图
} else {
long lastSyncTime = getLastSyncTime(this); // 获取上次同步时间
if (lastSyncTime != 0) {
lastSyncTimeView.setText(getString(R.string.preferences_last_sync_time,
DateFormat.format(getString(R.string.preferences_last_sync_time_format),
lastSyncTime))); // 格式化并显示上次同步时间
lastSyncTimeView.setVisibility(View.VISIBLE); // 显示上次同步时间视图
} else {
lastSyncTimeView.setVisibility(View.GONE); // 如果未同步过,则隐藏上次同步时间视图
}
}
}
// 下面的方法定义了各种UI刷新逻辑、账户管理、对话框显示以及同步操作等
// ...
/**
*
*/
private void refreshUI() {
loadAccountPreference(); // 加载账户偏好设置
loadSyncButton(); // 加载同步按钮
}
/**
*
* Google
*
*/
private void showSelectAccountAlertDialog() {
// 创建对话框构建器并设置自定义标题
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null);
TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title);
titleTextView.setText(getString(R.string.preferences_dialog_select_account_title));
TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle);
subtitleTextView.setText(getString(R.string.preferences_dialog_select_account_tips));
dialogBuilder.setCustomTitle(titleView);
dialogBuilder.setPositiveButton(null, null); // 移除默认的确定按钮
// 获取当前设备上的Google账户
Account[] accounts = getGoogleAccounts();
String defAccount = getSyncAccountName(this); // 获取当前同步的账户名称
mOriAccounts = accounts; // 保存原始账户列表
mHasAddedAccount = false; // 标记是否已添加新账户
if (accounts.length > 0) {
// 创建账户选项并设置选中项
CharSequence[] items = new CharSequence[accounts.length];
final CharSequence[] itemMapping = items;
int checkedItem = -1; // 记录默认选中的账户
int index = 0;
for (Account account : accounts) {
if (TextUtils.equals(account.name, defAccount)) {
checkedItem = index;
}
items[index++] = account.name;
}
// 设置单选列表,并为选中的账户执行同步操作
dialogBuilder.setSingleChoiceItems(items, checkedItem,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
setSyncAccount(itemMapping[which].toString());
dialog.dismiss();
refreshUI();
}
});
}
// 添加“添加账户”选项
View addAccountView = LayoutInflater.from(this).inflate(R.layout.add_account_text, null);
dialogBuilder.setView(addAccountView);
final AlertDialog dialog = dialogBuilder.show();
// 点击“添加账户”执行添加账户操作
addAccountView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mHasAddedAccount = true;
Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS");
intent.putExtra(AUTHORITIES_FILTER_KEY, new String[]{
"gmail-ls"
});
startActivityForResult(intent, -1);
dialog.dismiss();
}
});
}
/**
*
*
*/
private void showChangeAccountConfirmAlertDialog() {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
// 设置自定义标题,包含当前同步账户名称
View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null);
TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title);
titleTextView.setText(getString(R.string.preferences_dialog_change_account_title,
getSyncAccountName(this)));
TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle);
subtitleTextView.setText(getString(R.string.preferences_dialog_change_account_warn_msg));
dialogBuilder.setCustomTitle(titleView);
// 创建菜单项并设置点击事件
CharSequence[] menuItemArray = new CharSequence[]{
getString(R.string.preferences_menu_change_account),
getString(R.string.preferences_menu_remove_account),
getString(R.string.preferences_menu_cancel)
};
dialogBuilder.setItems(menuItemArray, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (which == 0) {
// 选择更改账户,显示账户选择对话框
showSelectAccountAlertDialog();
} else if (which == 1) {
// 选择移除账户执行移除操作并刷新UI
removeSyncAccount();
refreshUI();
}
}
});
dialogBuilder.show();
}
/**
* Google
*
* @return Account[] com.google
*/
private Account[] getGoogleAccounts() {
AccountManager accountManager = AccountManager.get(this);
return accountManager.getAccountsByType("com.google");
}
/**
*
* SharedPreferencesgtask
*
* @param account
*/
private void setSyncAccount(String account) {
// 检查当前账户是否与传入账户名一致,不一致则更新账户信息
if (!getSyncAccountName(this).equals(account)) {
SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
// 如果账户名非空,则保存账户名,否则清除账户名
if (account != null) {
editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, account);
} else {
editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, "");
}
editor.commit();
// 清理上次同步时间
setLastSyncTime(this, 0);
// 清理本地相关的gtask信息
new Thread(new Runnable() {
public void run() {
ContentValues values = new ContentValues();
values.put(NoteColumns.GTASK_ID, "");
values.put(NoteColumns.SYNC_ID, 0);
getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null);
}
}).start();
// 显示设置成功的提示信息
Toast.makeText(NotesPreferenceActivity.this,
getString(R.string.preferences_toast_success_set_accout, account),
Toast.LENGTH_SHORT).show();
}
}
/**
*
* SharedPreferencesgtask
*/
private void removeSyncAccount() {
SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
// 如果存在账户信息,则移除
if (settings.contains(PREFERENCE_SYNC_ACCOUNT_NAME)) {
editor.remove(PREFERENCE_SYNC_ACCOUNT_NAME);
}
// 如果存在上次同步时间信息,则移除
if (settings.contains(PREFERENCE_LAST_SYNC_TIME)) {
editor.remove(PREFERENCE_LAST_SYNC_TIME);
}
editor.commit();
// 清理本地相关的gtask信息
new Thread(new Runnable() {
public void run() {
ContentValues values = new ContentValues();
values.put(NoteColumns.GTASK_ID, "");
values.put(NoteColumns.SYNC_ID, 0);
getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null);
}
}).start();
}
/**
*
* SharedPreferences
*
* @param context
* @return
*/
public static String getSyncAccountName(Context context) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE);
return settings.getString(PREFERENCE_SYNC_ACCOUNT_NAME, "");
}
/**
*
* SharedPreferences
*
* @param context
* @param time
*/
public static void setLastSyncTime(Context context, long time) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putLong(PREFERENCE_LAST_SYNC_TIME, time);
editor.commit();
}
/**
*
* SharedPreferences0
*
* @param context
* @return
*/
public static long getLastSyncTime(Context context) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE);
return settings.getLong(PREFERENCE_LAST_SYNC_TIME, 0);
}
/**
* 广gtask广UI
*/
private class GTaskReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
refreshUI();
// 如果广播消息表明正在同步则更新UI显示的同步状态信息
if (intent.getBooleanExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_IS_SYNCING, false)) {
TextView syncStatus = (TextView) findViewById(R.id.prefenerece_sync_status_textview);
syncStatus.setText(intent
.getStringExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_PROGRESS_MSG));
}
}
}
/**
*
*
* @param item
* @return truefalse
*
*/
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// 当选择返回按钮时启动NotesListActivity并清除当前活动栈顶以上的所有活动
Intent intent = new Intent(this, NotesListActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
launchNotesListActivity(); // 返回到笔记列表页面
return true;
default:
return false;
}
}
// 其他方法省略...
}
Loading…
Cancel
Save