diff --git a/BackupUtils.java b/BackupUtils.java new file mode 100644 index 0000000..f285f6f --- /dev/null +++ b/BackupUtils.java @@ -0,0 +1,434 @@ +/* + * 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.tool; + +// 导入Android框架和Java标准库中的类 +import android.content.Context; // 提供应用环境信息的类 +import android.database.Cursor; // 用于在数据库查询结果中遍历行的类 +import android.os.Environment; // 提供有关设备环境的信息,如存储状态 +import android.text.TextUtils; // 提供用于处理文本(如检查空字符串)的实用方法 +import android.text.format.DateFormat; // 提供日期和时间格式化的方法 +import android.util.Log; // 提供日志记录的类 + +import net.micode.notes.R; // 包含项目资源引用的类(尽管在这段代码中未直接使用) +import net.micode.notes.data.Notes; // 可能是一个包含数据模型和相关常量的类 +import net.micode.notes.data.Notes.DataColumns; // Notes类内部的一个静态内部类,定义了数据表的列名 +import net.micode.notes.data.Notes.DataConstants; // Notes类内部的一个静态内部类,定义了数据相关的常量 +import net.micode.notes.data.Notes.NoteColumns; // Notes类内部的一个静态内部类,定义了笔记数据表的列名 + +import java.io.File; // 表示文件和目录路径名的抽象表示形式 +import java.io.FileNotFoundException; // 当尝试打开文件失败时抛出的异常 +import java.io.FileOutputStream; // 文件输出流,用于将数据写入文件 +import java.io.IOException; // 发生I/O错误时抛出的通用异常类 +import java.io.PrintStream; // 打印流,用于打印各种数据表示形式 + +// 声明BackupUtils类 +public class BackupUtils { + // 定义一个静态常量TAG,用于日志记录中的标签 + private static final String TAG = "BackupUtils"; + + // 定义一个静态变量sInstance,用于存储BackupUtils类的单例实例 + private static BackupUtils sInstance; + + // 定义一个私有构造函数,防止外部通过new关键字创建实例 + // 注意:构造函数在这段代码中并未直接给出,但它是单例模式实现的关键部分 + + // 定义一个公开的静态同步方法getInstance,用于获取BackupUtils类的实例 + public static synchronized BackupUtils getInstance(Context context) { + // 如果sInstance为null,说明还没有创建实例,则创建一个新的实例并赋值给sInstance + if (sInstance == null) { + sInstance = new BackupUtils(context); // 注意:这里的构造函数是假设的,实际代码中需要定义 + } + // 返回sInstance,即BackupUtils类的单例实例 + return sInstance; + } +} + + /** + * Following states are signs to represents backup or restore + * status + */ + // Currently, the sdcard is not mounted + // 定义一些静态常量,用于表示不同的状态 +public static final int STATE_SD_CARD_UNMOUONTED = 0; // SD卡未挂载的状态码 +// 备注:这里有一个拼写错误,应该是"UNMOUNTED"而不是"UNMOUONTED" + +public static final int STATE_BACKUP_FILE_NOT_EXIST = 1; // 备份文件不存在的状态码 + +public static final int STATE_DATA_DESTROIED = 2; // 数据被破坏(可能由其他程序更改)的状态码 +// 备注:这里有一个拼写错误,应该是"DESTROYED"而不是"DESTROIED" + +public static final int STATE_SYSTEM_ERROR = 3; // 系统错误导致备份或恢复失败的状态码 + +public static final int STATE_SUCCESS = 4; // 备份或恢复成功的状态码 + +// 定义一个私有成员变量,用于文本导出功能 +private TextExport mTextExport; + +// 私有构造函数,防止外部直接实例化BackupUtils类 +// 备注:这是单例模式实现的一部分,构造函数接受一个Context参数 +private BackupUtils(Context context) { + mTextExport = new TextExport(context); // 初始化mTextExport成员变量 +} + +// 定义一个私有静态方法,用于检查外部存储是否可用 +private static boolean externalStorageAvailable() { + // 通过比较Environment.getExternalStorageState()的返回值和Environment.MEDIA_MOUNTED来判断 + return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); +} + +// 定义一个公开的方法,用于导出数据到文本文件 +// 备注:这个方法返回的是一个状态码,表示导出操作的结果 +public int exportToText() { + return mTextExport.exportToText(); // 调用TextExport类的exportToText方法 +} + +// 定义一个公开的方法,用于获取导出的文本文件的文件名 +public String getExportedTextFileName() { + return mTextExport.mFileName; // 直接访问TextExport类的mFileName成员变量 +} + +// 定义一个公开的方法,用于获取导出的文本文件的目录 +public String getExportedTextFileDir() { + return mTextExport.mFileDirectory; // 直接访问TextExport类的mFileDirectory成员变量 +} + +// 定义一个私有静态内部类,用于实现文本导出的具体逻辑 +private static class TextExport { + // 定义一个静态常量数组,用于指定从数据库查询时需要返回的列 + private static final String[] NOTE_PROJECTION = { + NoteColumns.ID, // 笔记的ID + NoteColumns.MODIFIED_DATE, // 笔记的最后修改日期 + NoteColumns.SNIPPET, // 笔记的摘要或简短内容 + NoteColumns.TYPE // 笔记的类型 + }; + + // 备注:TextExport类的其他部分(如构造函数、exportToText方法以及mFileName和mFileDirectory成员变量) + // 在这段代码中未给出,但我们可以推断它们存在并用于实现文本导出的功能。 +} + + // 定义静态常量,用于表示数据库查询结果中笔记ID的索引位置 +private static final int NOTE_COLUMN_ID = 0; + +// 定义静态常量,用于表示数据库查询结果中笔记修改日期的索引位置 +private static final int NOTE_COLUMN_MODIFIED_DATE = 1; + +// 定义静态常量,用于表示数据库查询结果中笔记摘要的索引位置 +private static final int NOTE_COLUMN_SNIPPET = 2; + +// 定义一个静态常量数组,包含需要从数据库查询的数据列 +private static final String[] DATA_PROJECTION = { + DataColumns.CONTENT, // 数据内容 + DataColumns.MIME_TYPE, // MIME类型 + DataColumns.DATA1, // 第一个数据字段 + DataColumns.DATA2, // 第二个数据字段 + DataColumns.DATA3, // 第三个数据字段 + DataColumns.DATA4 // 第四个数据字段 +}; + +// 定义静态常量,用于表示数据查询结果中内容列的索引位置 +private static final int DATA_COLUMN_CONTENT = 0; + +// 定义静态常量,用于表示数据查询结果中MIME类型列的索引位置 +private static final int DATA_COLUMN_MIME_TYPE = 1; + +// 这里有一个问题:DATA_COLUMN_CALL_DATE(电话日期)与DATA_PROJECTION数组不匹配 +// 因为DATA_PROJECTION中没有与电话日期对应的列,这可能会导致索引越界错误 +private static final int DATA_COLUMN_CALL_DATE = 2; + +// 定义静态常量,用于表示数据查询结果中电话号码列的索引位置 +// 但这里也有问题:根据DATA_PROJECTION数组,DATA_COLUMN_PHONE_NUMBER应该指向索引4, +// 这个定义是正确的,但是之前的DATA_COLUMN_CALL_DATE使用了索引2,可能会导致混淆 +private static final int DATA_COLUMN_PHONE_NUMBER = 4; + +// 定义一个实例变量,用于存储文本格式的字符串数组 +// 这个数组可能从资源文件中获取,用于格式化导出的文本 +private final String[] TEXT_FORMAT; + +// 定义静态常量,用于表示格式化字符串数组中文件夹名称的索引位置 +private static final int FORMAT_FOLDER_NAME = 0; + +// 定义静态常量,用于表示格式化字符串数组中笔记日期的索引位置 +private static final int FORMAT_NOTE_DATE = 1; + +// 定义静态常量,用于表示格式化字符串数组中笔记内容的索引位置 +private static final int FORMAT_NOTE_CONTENT = 2; + +// 定义一个实例变量,用于存储上下文(Context)对象 +private Context mContext; + +// 定义一个实例变量,用于存储导出的文本文件的文件名 +private String mFileName; + +// 定义一个实例变量,用于存储导出的文本文件的目录 +private String mFileDirectory; + +// 构造函数,用于初始化TextExport对象 +public TextExport(Context context) { + // 从资源文件中获取格式化字符串数组,并赋值给TEXT_FORMAT实例变量 + TEXT_FORMAT = context.getResources().getStringArray(R.array.format_for_exported_note); + // 将传入的上下文对象赋值给mContext实例变量 + mContext = context; + // 初始化mFileName和mFileDirectory实例变量为空字符串 + mFileName = ""; + mFileDirectory = ""; +} + // 定义一个私有方法,接收一个文件夹ID(字符串)和一个打印流(PrintStream)作为参数,无返回值 +private void exportFolderToText(String folderId, PrintStream ps) { + // 使用getContentResolver()方法从内容提供者处查询属于指定文件夹的笔记 + // Notes.CONTENT_NOTE_URI是内容提供者的URI,NOTE_PROJECTION是查询返回的列投影 + // NoteColumns.PARENT_ID + "=?"是查询的选择条件,new String[] { folderId }是选择条件的参数 + Cursor notesCursor = mContext.getContentResolver().query(Notes.CONTENT_NOTE_URI, + NOTE_PROJECTION, NoteColumns.PARENT_ID + "=?", new String[] { folderId }, null); + + // 检查查询返回的Cursor是否不为null + if (notesCursor != null) { + // 移动Cursor到第一行,如果查询结果不为空,则进入if语句 + if (notesCursor.moveToFirst()) { + // 使用do-while循环遍历查询结果集 + do { + // 打印笔记的最后修改日期 + // 使用getFormat(FORMAT_NOTE_DATE)获取格式化字符串,然后使用DateFormat.format()和getString(R.string.format_datetime_mdhm) + // 格式化最后修改日期,最后通过PrintStream的println方法打印出来 + ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format( + mContext.getString(R.string.format_datetime_mdhm), + notesCursor.getLong(NOTE_COLUMN_MODIFIED_DATE)))); + + // 查询属于当前笔记的数据 + // 从Cursor中获取笔记的ID + String noteId = notesCursor.getString(NOTE_COLUMN_ID); + // 调用exportNoteToText方法导出当前笔记的文本内容到PrintStream中 + // 注意:exportNoteToText方法需要在当前类中定义,但您没有提供其实现 + exportNoteToText(noteId, ps); + } while (notesCursor.moveToNext()); // 循环直到Cursor遍历完所有行 + } + // 关闭Cursor,释放资源 + notesCursor.close(); + } +} + + /** + * Export note identified by id to a print stream + */ + // 定义一个私有方法,用于将指定笔记ID的笔记内容导出到文本输出流(PrintStream)中 +private void exportNoteToText(String noteId, PrintStream ps) { + // 使用内容解析器查询与指定笔记ID匹配的笔记数据 + // 这里的Notes.CONTENT_DATA_URI是内容提供者的URI,DATA_PROJECTION是我们要查询的列投影 + // DataColumns.NOTE_ID + "=?"是查询条件,表示我们要查询的笔记ID + // new String[] { noteId }是查询条件的参数,即具体的笔记ID值 + Cursor dataCursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, + DATA_PROJECTION, DataColumns.NOTE_ID + "=?", new String[] { noteId }, null); + + // 检查查询返回的Cursor是否不为空 + if (dataCursor != null) { + // 移动Cursor到第一行数据(如果有的话) + if (dataCursor.moveToFirst()) { + // 使用do-while循环遍历Cursor中的所有行 + do { + // 从当前行中获取MIME类型 + String mimeType = dataCursor.getString(DATA_COLUMN_MIME_TYPE); + + // 判断MIME类型是否为CALL_NOTE,即电话笔记 + if (DataConstants.CALL_NOTE.equals(mimeType)) { + // 如果是电话笔记,则打印电话号码 + String phoneNumber = dataCursor.getString(DATA_COLUMN_PHONE_NUMBER); + long callDate = dataCursor.getLong(DATA_COLUMN_CALL_DATE); + String location = dataCursor.getString(DATA_COLUMN_CONTENT); // 这里location可能表示电话笔记的附加信息或位置,但命名可能有些误导 + + // 如果电话号码不为空,则按照指定格式打印电话号码 + if (!TextUtils.isEmpty(phoneNumber)) { + ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), phoneNumber)); + } + + // 打印通话日期,使用指定的日期时间格式 + ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), DateFormat + .format(mContext.getString(R.string.format_datetime_mdhm), callDate))); + + // 如果location(附加信息)不为空,则按照指定格式打印它 + if (!TextUtils.isEmpty(location)) { + ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), location)); + } + } + // 判断MIME类型是否为普通笔记 + else if (DataConstants.NOTE.equals(mimeType)) { + // 如果是普通笔记,则打印笔记内容 + String content = dataCursor.getString(DATA_COLUMN_CONTENT); + if (!TextUtils.isEmpty(content)) { + ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), content)); + } + } + } while (dataCursor.moveToNext()); // 移动到下一行,继续循环 + } + // 关闭Cursor以释放资源 + dataCursor.close(); + } + +} + // print a line separator between note + try {//这段代码尝试向PrintStream对象ps写入一个字节数组, + //该数组包含一个换行符(Character.LINE_SEPARATOR)和一个字符(Character.LETTER_NUMBER, + //如果写入过程中发生IOException,则捕获异常并通过日志打印错误信息。 + ps.write(new byte[] { + Character.LINE_SEPARATOR, Character.LETTER_NUMBER + }); + } catch (IOException e) { + Log.e(TAG, e.toString()); + } + } + + /** + * Note will be exported as text which is user readable + */ + public int exportToText() { + //这是一个方法的声明,名为exportToText,它返回一个整型值,表示导出操作的状态。方法上方的注释说明笔记将被导出为用户可读的文本格式。 + if (!externalStorageAvailable()) { + //这段代码检查外部存储是否可用。如果不可用,则记录一条调试日志,并返回表示SD卡未挂载的状态码。 + Log.d(TAG, "Media was not mounted"); + return STATE_SD_CARD_UNMOUONTED; + } + + PrintStream ps = getExportToTextPrintStream(); + //获取一个PrintStream对象,用于将文本写入文件。如果获取失败(即ps为null),则记录一条错误日志,并返回表示系统错误的状态码。 + if (ps == null) { + Log.e(TAG, "get print stream error"); + return STATE_SYSTEM_ERROR; + } + // First export folder and its notes + //使用ContentResolver查询数据库,获取所有文件夹(不包括垃圾文件夹)和通话记录文件夹的游标。 + Cursor folderCursor = mContext.getContentResolver().query( + Notes.CONTENT_NOTE_URI, + NOTE_PROJECTION, + "(" + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + " AND " + + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + ") OR " + + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER, null, null); +//如果游标不为空,遍历所有文件夹,对每个文件夹执行一系列操作 + if (folderCursor != null) { + if (folderCursor.moveToFirst()) { + do { + // Print folder's name + String folderName = ""; + if(folderCursor.getLong(NOTE_COLUMN_ID) == Notes.ID_CALL_RECORD_FOLDER) { + folderName = mContext.getString(R.string.call_record_folder_name); + } else { + folderName = folderCursor.getString(NOTE_COLUMN_SNIPPET); + } + if (!TextUtils.isEmpty(folderName)) { + ps.println(String.format(getFormat(FORMAT_FOLDER_NAME), folderName)); + } + String folderId = folderCursor.getString(NOTE_COLUMN_ID); + exportFolderToText(folderId, ps); + } while (folderCursor.moveToNext()); + } + folderCursor.close(); + } + + // Export notes in root's folder + //再次使用ContentResolver查询数据库,这次获取所有根目录下的笔记的游标。 + Cursor noteCursor = mContext.getContentResolver().query( + Notes.CONTENT_NOTE_URI, + NOTE_PROJECTION, + NoteColumns.TYPE + "=" + +Notes.TYPE_NOTE + " AND " + NoteColumns.PARENT_ID + + "=0", null, null); +//如果游标不为空,遍历所有根目录下的笔记,对每个笔记执行一系列操作 + if (noteCursor != null) { + if (noteCursor.moveToFirst()) { + do { + ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format( + mContext.getString(R.string.format_datetime_mdhm), + noteCursor.getLong(NOTE_COLUMN_MODIFIED_DATE)))); + // Query data belong to this note + String noteId = noteCursor.getString(NOTE_COLUMN_ID); + exportNoteToText(noteId, ps); + } while (noteCursor.moveToNext()); + } + noteCursor.close(); + } + ps.close();//关闭PrintStream对象,完成文件写入。 + + return STATE_SUCCESS;//返回表示操作成功的状态码。 + } + + /** + * Get a print stream pointed to the file {@generateExportedTextFile} + */ + private PrintStream getExportToTextPrintStream() { + //这是一个私有方法,返回一个PrintStream对象,用于将文本写入文件。 + File file = generateFileMountedOnSDcard(mContext, R.string.file_path, + R.string.file_name_txt_format); + //调用generateFileMountedOnSDcard方法生成一个文件,并返回该文件的File对象。 + //这个方法需要三个参数:上下文mContext,文件路径的资源IDR.string.file_path,和文件名格式的资源IDR.string.file_name_txt_format。 + if (file == null) { + Log.e(TAG, "create file to exported failed"); + return null;//如果generateFileMountedOnSDcard方法返回null,表示文件创建失败,则记录一条错误日志,并返回null。 + } + mFileName = file.getName(); + mFileDirectory = mContext.getString(R.string.file_path);//获取文件的名称和文件所在的目录路径,并将它们分别赋值给mFileName和mFileDirectory变量。 + PrintStream ps = null;//声明一个PrintStream对象ps,初始化为null。 + try { + //尝试创建一个FileOutputStream对象fos,用于向文件写入数据。然后,使用fos创建一个PrintStream对象ps。 + //如果在创建FileOutputStream或PrintStream时发生FileNotFoundException或NullPointerException,则捕获异常,打印堆栈跟踪,并返回null。 + FileOutputStream fos = new FileOutputStream(file); + ps = new PrintStream(fos); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return null; + } catch (NullPointerException e) { + e.printStackTrace(); + return null; + } + return ps;//返回PrintStream对象ps。 + } + } + + /** + * Generate the text file to store imported data + */ + private static File generateFileMountedOnSDcard(Context context, int filePathResId, int fileNameFormatResId) { + //这是一个私有静态方法,返回一个File对象,表示在SD卡上创建的文件。 + StringBuilder sb = new StringBuilder();//创建一个StringBuilder对象sb,并向其中追加SD卡的根目录路径。 + sb.append(Environment.getExternalStorageDirectory()); + sb.append(context.getString(filePathResId));//向sb中追加文件路径字符串,该字符串是从资源文件中获取的。 + File filedir = new File(sb.toString());//使用sb.toString()创建一个表示文件目录的File对象filedir。 + sb.append(context.getString( + //向sb中追加文件名,文件名是根据提供的格式资源ID和当前时间格式化的。 + fileNameFormatResId, + DateFormat.format(context.getString(R.string.format_date_ymd), + System.currentTimeMillis()))); + File file = new File(sb.toString());//使用sb.toString()创建一个表示文件的File对象file。 + + try { + //尝试检查文件目录是否存在,如果不存在则创建它。然后,检查文件是否存在,如果不存在则创建新文件。 +//如果在检查或创建目录/文件时发生SecurityException或IOException,则捕获异常,打印堆栈跟踪。 + if (!filedir.exists()) { + filedir.mkdir(); + } + if (!file.exists()) { + file.createNewFile(); + } + return file; + } catch (SecurityException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return null;//如果方法执行过程中出现任何异常,或者文件无法被创建,则返回null。 + } +} + + diff --git a/DataUtils.java b/DataUtils.java new file mode 100644 index 0000000..b228a39 --- /dev/null +++ b/DataUtils.java @@ -0,0 +1,311 @@ +/* + * 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.tool;//指定了当前类所在的包名。 + +import android.content.ContentProviderOperation; +import android.content.ContentProviderResult; +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.OperationApplicationException; +import android.database.Cursor; +import android.os.RemoteException; +import android.util.Log; + +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.CallNote; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.ui.NotesListAdapter.AppWidgetAttribute; + +import java.util.ArrayList; +import java.util.HashSet;//以上导入了代码中使用的其他类。 + + +public class DataUtils {//定义了一个名为DataUtils的公共类,这个类用于封装与数据操作相关的工具方法。 + public static final String TAG = "DataUtils";//定义了一个公共静态最终变量TAG,用于日志记录时的标签。 + public static boolean batchDeleteNotes(ContentResolver resolver, HashSet ids) { + //定义了一个公共静态方法batchDeleteNotes,用于批量删除笔记。该方法接收一个ContentResolver对象和一个包含笔记ID的HashSet集合作为参数,返回一个布尔值表示操作是否成功。 + if (ids == null) { + Log.d(TAG, "the ids is null"); + return true;//定义了一个公共静态方法batchDeleteNotes,用于批量删除笔记。该方法接收一个ContentResolver对象和一个包含笔记ID的HashSet集合作为参数,返回一个布尔值表示操作是否成功。 + } + if (ids.size() == 0) { + Log.d(TAG, "no id is in the hashset"); + return true;//如果ID集合为空,则记录一条调试日志并返回true + } + + ArrayList operationList = new ArrayList(); + //创建一个ArrayList对象,用于存储将要执行的内容提供者操作。 + for (long id : ids) {//遍历ID集合中的每个ID。 + if(id == Notes.ID_ROOT_FOLDER) { + Log.e(TAG, "Don't delete system folder root"); + continue;//如果当前ID是系统根文件夹的ID,则记录一条错误日志并跳过当前循环迭代,不删除根文件夹。 + } + ContentProviderOperation.Builder builder = ContentProviderOperation + .newDelete(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); + //创建一个新的删除操作构建器,指定要删除的内容URI(通过ContentUris.withAppendedId方法将笔记ID附加到笔记内容URI上)。 + operationList.add(builder.build());//将构建好的删除操作添加到操作列表中。 + } + try { + ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); + //尝试批量执行操作列表中的所有操作。applyBatch方法接收内容提供者的授权字符串和操作列表,返回操作结果数组。 + if (results == null || results.length == 0 || results[0] == null) { + Log.d(TAG, "delete notes failed, ids:" + ids.toString()); + return false; + }//如果操作结果数组为null、长度为0或第一个结果为null,则认为删除操作失败,记录一条调试日志并返回false。 + return true;//如果操作成功执行,返回true。 + } catch (RemoteException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + } catch (OperationApplicationException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + }//如果操作成功执行,返回true。 + return false;//如果发生异常,返回false + } + + public static void moveNoteToFoler(ContentResolver resolver, long id, long srcFolderId, long desFolderId) { + //定义一个静态方法 moveNoteToFoler(注意这里有个拼写错误,应为 moveNoteToFolder),接受四个参数:ContentResolver resolver(用于与内容提供者交互的工具),long id(要移动的笔记的ID),long srcFolderId(源文件夹ID),long desFolderId(目标文件夹ID)。 + ContentValues values = new ContentValues();//创建一个 ContentValues 对象,用于存储要更新的数据。 + values.put(NoteColumns.PARENT_ID, desFolderId);//将目标文件夹ID赋值给 PARENT_ID,表示笔记应该移动到的文件夹。 + values.put(NoteColumns.ORIGIN_PARENT_ID, srcFolderId);//将源文件夹ID赋值给 ORIGIN_PARENT_ID,可能用于记录笔记原来所在的文件夹 + values.put(NoteColumns.LOCAL_MODIFIED, 1);//将 LOCAL_MODIFIED 设置为1 + resolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id), values, null, null); + //使用 ContentResolver 的 update 方法更新指定ID的笔记。ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id) 用于生成指向特定笔记的URI,values 包含要更新的字段。 + } + + public static boolean batchMoveToFolder(ContentResolver resolver, HashSet ids, + long folderId) {//定义一个静态方法 batchMoveToFolder,接受三个参数:ContentResolver resolver,一个包含多个笔记ID的 HashSet ids,以及目标文件夹ID long folderId。返回一个布尔值表示操作是否成功。 + if (ids == null) { + Log.d(TAG, "the ids is null"); + return true;//如果传入的ID集合为null,则记录日志并返回true + } + + ArrayList operationList = new ArrayList(); + //创建一个 ArrayList 来存储一系列的内容提供者操作(ContentProviderOperation),这些操作将批量执行。 + for (long id : ids) {//遍历ID集合,为每个ID创建一个更新操作的构建器,指定要更新的笔记的URI。 + ContentProviderOperation.Builder builder = ContentProviderOperation + .newUpdate(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); + builder.withValue(NoteColumns.PARENT_ID, folderId);//设置目标文件夹ID。 + builder.withValue(NoteColumns.LOCAL_MODIFIED, 1);//设置 LOCAL_MODIFIED 为1。 + operationList.add(builder.build());//将构建好的操作添加到操作列表中。 + } + + try {//尝试批量执行操作列表中的操作。Notes.AUTHORITY 是内容提供者的权限名。 + ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); + if (results == null || results.length == 0 || results[0] == null) { + Log.d(TAG, "delete notes failed, ids:" + ids.toString()); + return false;//如果操作结果为空、长度为0或第一个结果为null,则记录日志并返回false。 + } + return true; + } catch (RemoteException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + } catch (OperationApplicationException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));//捕获并处理 RemoteException 和 OperationApplicationException 异常,记录错误日志。 + } + return false;//如果出现异常,则返回false。 + } + + /** + * Get the all folder count except system folders {@link Notes#TYPE_SYSTEM}} + */ + public static int getUserFolderCount(ContentResolver resolver) {//定义一个静态方法getUserFolderCount,它接受一个ContentResolver对象作为参数,用于与内容提供者交互。 + Cursor cursor =resolver.query(Notes.CONTENT_NOTE_URI,//使用ContentResolver的query方法发起查询。Notes.CONTENT_NOTE_URI是查询的URI,指向笔记数据的集合。 + new String[] { "COUNT(*)" },//指定查询的列,这里只查询一个列,即"COUNT(*)",用于计算满足条件的行数。 + NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?",//指定查询的条件。这里条件是笔记类型(NoteColumns.TYPE)等于某个值,并且父ID(NoteColumns.PARENT_ID)不等于另一个值。 + new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)}, + null);//为查询条件提供具体的值。第一个值是文件夹的类型(Notes.TYPE_FOLDER),第二个值是垃圾文件夹的ID(Notes.ID_TRASH_FOLER)。 +//查询的排序规则为null,表示不需要排序。 + int count = 0;//初始化一个变量count用于存储查询结果。 + if(cursor != null) {//检查Cursor对象是否不为null,即查询是否成功返回了结果。 + if(cursor.moveToFirst()) {//尝试将Cursor移动到第一行,如果Cursor不为空且至少有一行数据,则此操作成功。 + try { + count = cursor.getInt(0);//从Cursor的第一列(索引为0)获取整数值,即满足条件的行数,并将其赋值给count。 + } catch (IndexOutOfBoundsException e) { + Log.e(TAG, "get folder count failed:" + e.toString()); + //捕获IndexOutOfBoundsException异常,这通常发生在尝试访问不存在的列时。使用Log.e打印错误日志。 + } finally { + cursor.close();//无论是否发生异常,都确保关闭Cursor以释放资源。 + } + } + } + return count;//返回计算得到的文件夹数量。 + } + + public static boolean visibleInNoteDatabase(ContentResolver resolver, long noteId, int type) { + //定义一个静态方法visibleInNoteDatabase,它接受ContentResolver对象、笔记ID和笔记类型作为参数。 + Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), + null, + NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER, + new String [] {String.valueOf(type)}, + null);//使用ContentUris.withAppendedId方法将笔记ID附加到URI上,以查询特定笔记的详细信息。 + + boolean exist = false;//初始化一个布尔变量exist,用于表示笔记是否存在且满足条件。 + if (cursor != null) { + if (cursor.getCount() > 0) { + exist = true; + } + cursor.close(); + } + return exist;//检查Cursor是否不为null,如果Cursor的计数大于0,则设置exist为true。最后关闭Cursor并返回exist。 + } + + public static boolean existInNoteDatabase(ContentResolver resolver, long noteId) {//检查指定ID的笔记是否存在。 + Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), + null, null, null, null); + + boolean exist = false; + if (cursor != null) { + if (cursor.getCount() > 0) { + exist = true; + } + cursor.close(); + } + return exist; + } + + public static boolean existInDataDatabase(ContentResolver resolver, long dataId) { + //定义一个静态方法existInDataDatabase,它接受一个ContentResolver和一个长整型dataId作为参数,返回一个布尔值表示是否存在。 + Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), + null, null, null, null);//使用ContentResolver的query方法查询数据库。ContentUris.withAppendedId方法用于生成带有指定ID的URI。这里查询的是Notes.CONTENT_DATA_URI,即数据项的URI,并且指定了dataId。查询的列、选择条件、选择参数和排序方式均为null,表示查询所有列且不设置过滤条件。 + + boolean exist = false;//初始化一个布尔变量exist为false,用于记录数据项是否存在。 + if (cursor != null) {//检查cursor是否为null,确保查询成功。 + if (cursor.getCount() > 0) { + exist = true;//如果cursor中的记录数大于0,则数据项存在,将exist设置为true。 + } + cursor.close();//关闭cursor,释放资源。 + } + return exist;//返回exist的值。 + } + + public static boolean checkVisibleFolderName(ContentResolver resolver, String name) { + //定义一个静态方法checkVisibleFolderName,它接受一个ContentResolver和一个字符串name作为参数,返回一个布尔值表示是否存在。 + Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, null, + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + + " AND " + NoteColumns.SNIPPET + "=?", + new String[] { name }, null); + //使用ContentResolver的query方法查询数据库。查询的URI是Notes.CONTENT_NOTE_URI,即笔记的URI。 + //查询条件是类型为文件夹(NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER),父ID不等于垃圾文件夹ID(NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER),并且摘要(即名称)等于指定的name。 + boolean exist = false;//初始化一个布尔变量exist为false。 + if(cursor != null) {//检查cursor是否为null。 + if(cursor.getCount() > 0) { + exist = true;//如果cursor中的记录数大于0,则文件夹存在,将exist设置为true。 + } + cursor.close();//关闭cursor。 + } + return exist;//返回exist的值。 + } + + public static HashSet getFolderNoteWidget(ContentResolver resolver, long folderId) {//定义一个静态方法getFolderNoteWidget, + //它接受一个ContentResolver和一个长整型folderId作为参数,返回一个HashSet。 + Cursor c = resolver.query(Notes.CONTENT_NOTE_URI, + new String[] { NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE }, + NoteColumns.PARENT_ID + "=?", + new String[] { String.valueOf(folderId) }, + null);//使用ContentResolver的query方法查询数据库。查询的URI是Notes.CONTENT_NOTE_URI。查询的列是WIDGET_ID和WIDGET_TYPE。查询条件是父ID等于指定的folderId。 + + HashSet set = null;//初始化一个HashSet类型的变量set为null。 + if (c != null) {//检查cursor是否为null。 + if (c.moveToFirst()) {//如果cursor移动到第一条记录。 + set = new HashSet();//初始化set。 + do {//开始一个循环,遍历cursor中的所有记录。 + try {//创建一个AppWidgetAttribute对象,并从cursor中获取WIDGET_ID和WIDGET_TYPE的值,添加到set中。如果发生IndexOutOfBoundsException异常,则记录错误日志。 + AppWidgetAttribute widget = new AppWidgetAttribute(); + widget.widgetId = c.getInt(0); + widget.widgetType = c.getInt(1); + set.add(widget); + } catch (IndexOutOfBoundsException e) { + Log.e(TAG, e.toString()); + } + } while (c.moveToNext());//循环直到cursor中没有更多记录。 + } + c.close();//关闭cursor。 + } + return set;//返回set。 + } + + public static String getCallNumberByNoteId(ContentResolver resolver, long noteId) { + //定义一个静态方法getCallNumberByNoteId,它接受一个ContentResolver和一个长整型noteId作为参数,返回一个字符串,即电话号码。 + Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI, + new String [] { CallNote.PHONE_NUMBER }, + CallNote.NOTE_ID + "=? AND " + CallNote.MIME_TYPE + "=?", + new String [] { String.valueOf(noteId), CallNote.CONTENT_ITEM_TYPE }, + null);//使用ContentResolver的query方法查询数据库。查询的URI是Notes.CONTENT_DATA_URI。查询的列是PHONE_NUMBER。查询条件是笔记ID等于指定的noteId,并且MIME类型等于CallNote.CONTENT_ITEM_TYPE。 + + if (cursor != null && cursor.moveToFirst()) {//检查cursor是否为null并且是否能移动到第一条记录。 + try { + return cursor.getString(0); + } catch (IndexOutOfBoundsException e) { + Log.e(TAG, "Get call number fails " + e.toString()); + } finally { + cursor.close(); + }//从cursor中获取电话号码,并返回。如果发生IndexOutOfBoundsException异常,则记录错误日志。无论如何,最后都要关闭cursor。 + } + return "";//如果查询失败或没有找到匹配的记录,则返回空字符串。 + } + + public static long getNoteIdByPhoneNumberAndCallDate(ContentResolver resolver, String phoneNumber, long callDate) { + //定义了一个静态方法,该方法接收一个ContentResolver对象、一个电话号码字符串和一个通话日期(长整型),用于查询笔记ID。 + Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI,//使用ContentResolver的query方法查询Notes.CONTENT_DATA_URI,这是一个URI,指向提供笔记数据的内容提供者。 + new String [] { CallNote.NOTE_ID },//指定查询返回的列,这里只请求返回笔记的ID。 + CallNote.CALL_DATE + "=? AND " + CallNote.MIME_TYPE + "=? AND PHONE_NUMBERS_EQUAL(" + + CallNote.PHONE_NUMBER + ",?)",//定义查询的选择条件,包括通话日期匹配、MIME类型匹配(确保是笔记的正确类型),以及电话号码匹配 + new String [] { String.valueOf(callDate), CallNote.CONTENT_ITEM_TYPE, phoneNumber },//为上述条件提供具体的值,分别是通话日期、MIME类型和电话号码。 + null);//不需要排序,所以传递null。 + + if (cursor != null) {//检查Cursor对象是否非空。 + if (cursor.moveToFirst()) {//尝试将游标移动到第一行,检查是否有数据。 + try { + return cursor.getLong(0); + } catch (IndexOutOfBoundsException e) { + Log.e(TAG, "Get call note id fails " + e.toString()); + }//尝试从第一行获取并返回笔记ID。如果发生IndexOutOfBoundsException(可能是因为查询结果没有包含期望的列),则记录错误日志。 + } + cursor.close(); + } + return 0;//关闭Cursor,如果没有找到匹配的笔记ID,则返回0。 + } + + public static String getSnippetById(ContentResolver resolver, long noteId) {//定义了一个静态方法,用于根据笔记ID获取笔记摘要。 + Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI,//使用ContentResolver查询Notes.CONTENT_NOTE_URI,这是指向笔记数据的URI。 + new String [] { NoteColumns.SNIPPET },//指定查询返回的列,这里只请求返回笔记的摘要。 + NoteColumns.ID + "=?",//定义查询的选择条件,即笔记ID匹配。 + new String [] { String.valueOf(noteId)},为上述条件提供具体的值,即笔记ID。 + null);//不需要排序,所以传递null。 + + if (cursor != null) {//检查Cursor对象是否非空。 + String snippet = "";//初始化摘要字符串。 + if (cursor.moveToFirst()) {//尝试将游标移动到第一行,检查是否有数据。 + snippet = cursor.getString(0);//从第一行获取并设置摘要。 + } + cursor.close();//关闭Cursor。 + return snippet; + } + throw new IllegalArgumentException("Note is not found with id: " + noteId);//如果没有找到匹配的笔记,则抛出异常。 + } + + public static String getFormattedSnippet(String snippet) {//定义了一个静态方法,用于格式化摘要字符串。 + if (snippet != null) {//检查摘要是否非空。 + snippet = snippet.trim();//去除摘要前后的空格。 + int index = snippet.indexOf('\n');//查找摘要中第一个换行符的位置。 + if (index != -1) {//如果找到了换行符。 + snippet = snippet.substring(0, index);//只保留换行符之前的部分。 + } + } + return snippet;//返回格式化后的摘要。 + } +} diff --git a/GTaskStringUtils.java b/GTaskStringUtils.java new file mode 100644 index 0000000..6e77fc7 --- /dev/null +++ b/GTaskStringUtils.java @@ -0,0 +1,118 @@ +/* + * 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.tool;//这一行声明了类所在的包名,即net.micode.notes.tool。这是Java中组织类的一种方式,有助于模块化代码和避免命名冲突。 + +public class GTaskStringUtils { + //这一行定义了一个公开的类GTaskStringUtils。在Java中,public关键字意味着这个类可以被任何其他类访问。 + +//接下来的部分是一系列使用final static String定义的常量。在Java中,final意味着变量的值一旦被赋予就不能被改变,static意味着变量属于类而不是类的任何特定对象实例,String是变量的数据类型。 + + public final static String GTASK_JSON_ACTION_ID = "action_id";//这行代码定义了一个常量GTASK_JSON_ACTION_ID,其值为"action_id"。这个常量可能用于标识JSON对象中的某个动作ID字段。 + + public final static String GTASK_JSON_ACTION_LIST = "action_list";//定义了一个常量GTASK_JSON_ACTION_LIST,值为"action_list",可能用于表示JSON中的动作列表字段。 + + public final static String GTASK_JSON_ACTION_TYPE = "action_type";//定义了一个常量GTASK_JSON_ACTION_TYPE,值为"action_type",用于标识JSON中的动作类型字段。 + + public final static String GTASK_JSON_ACTION_TYPE_CREATE = "create";//定义了一个常量GTASK_JSON_ACTION_TYPE_CREATE,值为"create",表示创建动作的类型。 + + public final static String GTASK_JSON_ACTION_TYPE_GETALL = "get_all";//定义了一个常量GTASK_JSON_ACTION_TYPE_GETALL,值为"get_all",表示获取所有数据的动作类型。 + + public final static String GTASK_JSON_ACTION_TYPE_MOVE = "move";//定义了一个常量GTASK_JSON_ACTION_TYPE_MOVE,值为"move",表示移动的动作类型。 + + public final static String GTASK_JSON_ACTION_TYPE_UPDATE = "update";//定义了一个常量GTASK_JSON_ACTION_TYPE_UPDATE,值为"update",表示更新的动作类型。 +//后续的代码继续定义了与GTask相关的各种JSON字段的常量,包括创建者ID、子实体、客户端版本、完成状态、当前列表ID、默认列表ID、删除状态、目标列表、目标父级、目标父级类型、实体增量、 +//实体类型、获取删除标志、ID、索引、最后修改时间、最新同步点、列表ID、列表集合、名称、新ID、笔记、父级ID、前一个兄弟ID、结果集合、源列表、任务集合、类型(分为组和任务两种)和用户等。 + public final static String GTASK_JSON_CREATOR_ID = "creator_id"; + + public final static String GTASK_JSON_CHILD_ENTITY = "child_entity"; + + public final static String GTASK_JSON_CLIENT_VERSION = "client_version"; + + public final static String GTASK_JSON_COMPLETED = "completed"; + + public final static String GTASK_JSON_CURRENT_LIST_ID = "current_list_id"; + + public final static String GTASK_JSON_DEFAULT_LIST_ID = "default_list_id"; + + public final static String GTASK_JSON_DELETED = "deleted"; + + public final static String GTASK_JSON_DEST_LIST = "dest_list"; + + public final static String GTASK_JSON_DEST_PARENT = "dest_parent"; + + public final static String GTASK_JSON_DEST_PARENT_TYPE = "dest_parent_type"; + + public final static String GTASK_JSON_ENTITY_DELTA = "entity_delta"; + + public final static String GTASK_JSON_ENTITY_TYPE = "entity_type"; + + public final static String GTASK_JSON_GET_DELETED = "get_deleted"; + + public final static String GTASK_JSON_ID = "id"; + + public final static String GTASK_JSON_INDEX = "index"; + + public final static String GTASK_JSON_LAST_MODIFIED = "last_modified"; + + public final static String GTASK_JSON_LATEST_SYNC_POINT = "latest_sync_point"; + + public final static String GTASK_JSON_LIST_ID = "list_id"; + + public final static String GTASK_JSON_LISTS = "lists"; + + public final static String GTASK_JSON_NAME = "name"; + + public final static String GTASK_JSON_NEW_ID = "new_id"; + + public final static String GTASK_JSON_NOTES = "notes"; + + public final static String GTASK_JSON_PARENT_ID = "parent_id"; + + public final static String GTASK_JSON_PRIOR_SIBLING_ID = "prior_sibling_id"; + + public final static String GTASK_JSON_RESULTS = "results"; + + public final static String GTASK_JSON_SOURCE_LIST = "source_list"; + + public final static String GTASK_JSON_TASKS = "tasks"; + + public final static String GTASK_JSON_TYPE = "type"; + + public final static String GTASK_JSON_TYPE_GROUP = "GROUP"; + + public final static String GTASK_JSON_TYPE_TASK = "TASK"; + + public final static String GTASK_JSON_USER = "user"; + + public final static String MIUI_FOLDER_PREFFIX = "[MIUI_Notes]";//定义了一个常量MIUI_FOLDER_PREFFIX,值为"[MIUI_Notes]",可能用于标识MIUI笔记的文件夹前缀。 + + public final static String FOLDER_DEFAULT = "Default";//定义了一个常量FOLDER_DEFAULT,值为"Default",表示默认文件夹的名称。 + + public final static String FOLDER_CALL_NOTE = "Call_Note";//定义了一个常量FOLDER_CALL_NOTE,值为"Call_Note",表示通话记录文件夹的名称。 + + + public final static String FOLDER_META = "METADATA";//定义了一个常量FOLDER_META,值为"METADATA",表示元数据文件夹的名称。 + + public final static String META_HEAD_GTASK_ID = "meta_gid";//定义了一个常量META_HEAD_GTASK_ID,值为"meta_gid",可能用于标识元数据中的GTask ID。 + + public final static String META_HEAD_NOTE = "meta_note";//定义了一个常量META_HEAD_NOTE,值为"meta_note",可能用于标识元数据中的笔记信息。 + + public final static String META_HEAD_DATA = "meta_data";//定义了一个常量META_HEAD_DATA,值为"meta_data",可能用于标识元数据中的其他数据。 + + public final static String META_NOTE_NAME = "[META INFO] DON'T UPDATE AND DELETE";//定义了一个常量META_NOTE_NAME,值为"[META INFO] DON'T UPDATE AND DELETE",表示包含元数据的笔记的名称,提示用户不要更新或删除这个笔记。 + +} diff --git a/ResourceParser.java b/ResourceParser.java new file mode 100644 index 0000000..bd0f0b7 --- /dev/null +++ b/ResourceParser.java @@ -0,0 +1,186 @@ +/* + * 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.tool;//这行代码声明了类所在的包名,即net.micode.notes.tool。 + +import android.content.Context; +import android.preference.PreferenceManager;//这两行代码导入了Android框架中的Context和PreferenceManager类。 + +import net.micode.notes.R;//这行代码导入了net.micode.notes包下的R类。R类是一个自动生成的类,包含了项目中所有资源的引用,如布局、字符串、图片等。 +import net.micode.notes.ui.NotesPreferenceActivity;//这行代码导入了net.micode.notes.ui包下的NotesPreferenceActivity类。 + +public class ResourceParser {//这行代码定义了一个公开的类ResourceParser。 + + public static final int YELLOW = 0; + public static final int BLUE = 1; + public static final int WHITE = 2; + public static final int GREEN = 3; + public static final int RED = 4;//这几行代码定义了五个公开的静态常量,分别代表不同的颜色,并用整数0到4进行标识。 + + public static final int BG_DEFAULT_COLOR = YELLOW;//这行代码定义了一个公开的静态常量BG_DEFAULT_COLOR,并将其值设置为YELLOW,即默认背景颜色为黄色。 + + public static final int TEXT_SMALL = 0; + public static final int TEXT_MEDIUM = 1; + public static final int TEXT_LARGE = 2; + public static final int TEXT_SUPER = 3;//这几行代码定义了四个公开的静态常量,分别代表不同的文本大小。 + + public static final int BG_DEFAULT_FONT_SIZE = TEXT_MEDIUM;//这行代码定义了一个公开的静态常量BG_DEFAULT_FONT_SIZE,并将其值设置为TEXT_MEDIUM,即默认字体大小为中等 + + public static class NoteBgResources {//这行代码定义了一个公开的静态内部类NoteBgResources。 + private final static int [] BG_EDIT_RESOURCES = new int [] { + R.drawable.edit_yellow, + R.drawable.edit_blue, + R.drawable.edit_white, + R.drawable.edit_green, + R.drawable.edit_red + };//在NoteBgResources内部类中,定义了一个私有的静态整型数组BG_EDIT_RESOURCES,并初始化为包含五个图片资源ID的数组。这些资源ID对应于五种不同颜色的编辑背景图片。 + + private final static int [] BG_EDIT_TITLE_RESOURCES = new int [] { + R.drawable.edit_title_yellow, + R.drawable.edit_title_blue, + R.drawable.edit_title_white, + R.drawable.edit_title_green, + R.drawable.edit_title_red + };//在NoteBgResources内部类中,定义了另一个私有的静态整型数组BG_EDIT_TITLE_RESOURCES,并初始化为包含五个图片资源ID的数组。这些资源ID对应于五种不同颜色的编辑标题背景图片。 + + public static int getNoteBgResource(int id) { + return BG_EDIT_RESOURCES[id]; + }//在NoteBgResources内部类中,定义了一个公开的静态方法getNoteBgResource,它接受一个整数id作为参数,并返回对应id的编辑背景图片资源ID。 + + public static int getNoteTitleBgResource(int id) { + return BG_EDIT_TITLE_RESOURCES[id]; + }//在NoteBgResources内部类中,定义了另一个公开的静态方法getNoteTitleBgResource,它同样接受一个整数id作为参数,并返回对应id的编辑标题背景图片资源ID。 + } + + public static int getDefaultBgId(Context context) {//定义了一个公开的静态方法getDefaultBgId,它接受一个Context对象作为参数,并返回一个整型值。这个方法用于获取默认的背景ID。 + if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(//开始了一个条件判断,使用PreferenceManager获取默认的SharedPreferences实例,然后从中读取一个布尔值。 + NotesPreferenceActivity.PREFERENCE_SET_BG_COLOR_KEY, false)) {//完成条件判断的部分,检查是否设置了背景颜色的偏好(通过PREFERENCE_SET_BG_COLOR_KEY键),如果没有设置,则默认为false。 + return (int) (Math.random() * NoteBgResources.BG_EDIT_RESOURCES.length);//如果条件为真(即用户设置了自定义背景颜色),则返回一个随机整数,这个整数是NoteBgResources.BG_EDIT_RESOURCES数组长度的某个值 + } else {//如果条件为假(即用户没有设置自定义背景颜色),则执行else部分的代码。 + return BG_DEFAULT_COLOR;//返回一个名为BG_DEFAULT_COLOR的整型值,这个值是默认的背景颜色ID。 + } + } + + public static class NoteItemBgResources {//定义了一个公开的静态内部类NoteItemBgResources,用于封装笔记项背景资源的获取方法。 + private final static int [] BG_FIRST_RESOURCES = new int [] {//定义了一个私有的静态最终整型数组BG_FIRST_RESOURCES,包含了一系列背景资源ID,用于表示笔记项在列表中的第一个位置时的背景。 + R.drawable.list_yellow_up, + R.drawable.list_blue_up, + R.drawable.list_white_up, + R.drawable.list_green_up, + R.drawable.list_red_up + }; + + private final static int [] BG_NORMAL_RESOURCES = new int [] {//定义了一个用于表示笔记项在列表中的正常位置时的背景资源ID数组。 + R.drawable.list_yellow_middle, + R.drawable.list_blue_middle, + R.drawable.list_white_middle, + R.drawable.list_green_middle, + R.drawable.list_red_middle + }; + + private final static int [] BG_LAST_RESOURCES = new int [] {//定义了一个用于表示笔记项在列表中的最后一个位置时的背景资源ID数组。 + R.drawable.list_yellow_down, + R.drawable.list_blue_down, + R.drawable.list_white_down, + R.drawable.list_green_down, + R.drawable.list_red_down, + }; + + private final static int [] BG_SINGLE_RESOURCES = new int [] {//定义了一个用于表示单独的笔记项(不在列表中)时的背景资源ID数组。 + R.drawable.list_yellow_single, + R.drawable.list_blue_single, + R.drawable.list_white_single, + R.drawable.list_green_single, + R.drawable.list_red_single + }; + + public static int getNoteBgFirstRes(int id) {//定义了一个公开的静态方法,根据提供的ID返回BG_FIRST_RESOURCES数组中对应的背景资源ID。 + + return BG_FIRST_RESOURCES[id]; + } + + public static int getNoteBgLastRes(int id) {//定义了一个方法,用于返回BG_LAST_RESOURCES数组中对应的背景资源ID。 + return BG_LAST_RESOURCES[id]; + } + + public static int getNoteBgSingleRes(int id) {//定义了一个方法,用于返回BG_SINGLE_RESOURCES数组中对应的背景资源ID。 + return BG_SINGLE_RESOURCES[id]; + } + + public static int getNoteBgNormalRes(int id) {//定义了一个方法,用于返回BG_SINGLE_RESOURCES数组中对应的背景资源ID。 + return BG_NORMAL_RESOURCES[id]; + } + + public static int getFolderBgRes() {//这行定义了一个方法,返回用于表示文件夹的背景资源ID。 + + return R.drawable.list_folder; + } + } + + public static class WidgetBgResources {//定义了一个公开的静态内部类 WidgetBgResources。 + private final static int [] BG_2X_RESOURCES = new int [] {//定义了一个私有的静态最终整型数组 BG_2X_RESOURCES,包含了一系列小部件在2x尺寸下的背景资源ID。这些资源ID通常指向drawable资源,如图片等。 + + R.drawable.widget_2x_yellow, + R.drawable.widget_2x_blue, + R.drawable.widget_2x_white, + R.drawable.widget_2x_green, + R.drawable.widget_2x_red, + }; + + public static int getWidget2xBgResource(int id) {//定义了一个公开的静态方法 getWidget2xBgResource,它接受一个整型参数 id,用于指定想要获取的背景资源的索引。 + return BG_2X_RESOURCES[id];//返回 BG_2X_RESOURCES 数组中指定索引 id 的背景资源ID。 + } + + private final static int [] BG_4X_RESOURCES = new int [] {//定义了一个私有的静态最终整型数组 BG_4X_RESOURCES,包含了一系列小部件在4x尺寸下的背景资源ID。 + R.drawable.widget_4x_yellow, + R.drawable.widget_4x_blue, + R.drawable.widget_4x_white, + R.drawable.widget_4x_green, + R.drawable.widget_4x_red + }; + + public static int getWidget4xBgResource(int id) {//定义了一个公开的静态方法 getWidget4xBgResource,它同样接受一个整型参数 id,用于指定想要获取的背景资源的索引。 + + return BG_4X_RESOURCES[id];//返回 BG_4X_RESOURCES 数组中指定索引 id 的背景资源ID。 + } + }//WidgetBgResources 类结束。 + + public static class TextAppearanceResources {//定义了一个公开的静态内部类 TextAppearanceResources。 + private final static int [] TEXTAPPEARANCE_RESOURCES = new int [] { + //定义了一个私有的静态最终整型数组 TEXTAPPEARANCE_RESOURCES,包含了一系列文本外观资源ID。这些资源ID通常指向style资源,定义了文本的字体大小、颜色等属性。 + R.style.TextAppearanceNormal, + R.style.TextAppearanceMedium, + R.style.TextAppearanceLarge, + R.style.TextAppearanceSuper + }; + + public static int getTexAppearanceResource(int id) {//定义了一个公开的静态方法 getTexAppearanceResource 接受一个整型参数 id,用于指定想要获取的文本外观资源的索引。 + /** + * HACKME: Fix bug of store the resource id in shared preference. + * The id may larger than the length of resources, in this case, + * return the {@link ResourceParser#BG_DEFAULT_FONT_SIZE} + */ + if (id >= TEXTAPPEARANCE_RESOURCES.length) {//检查提供的索引 id 是否超出了 TEXTAPPEARANCE_RESOURCES 数组的长度。 + return BG_DEFAULT_FONT_SIZE;//如果条件为真(即索引超出了数组长度),则返回一个名为 BG_DEFAULT_FONT_SIZE 的整型值。 + } + return TEXTAPPEARANCE_RESOURCES[id];//如果条件为假(即索引在数组长度范围内),则返回 TEXTAPPEARANCE_RESOURCES 数组中指定索引 id 的文本外观资源ID + } + + public static int getResourcesSize() {//定义了一个公开的静态方法 getResourcesSize,它不接受任何参数,并返回 TEXTAPPEARANCE_RESOURCES 数组的长度。 + return TEXTAPPEARANCE_RESOURCES.length;//返回 TEXTAPPEARANCE_RESOURCES 数组的长度。 + } + } +}