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.
xiaomi-Notes/DataUtils.java

312 lines
21 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.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<Long> 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<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
//创建一个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要移动的笔记的IDlong srcFolderId源文件夹IDlong 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) 用于生成指向特定笔记的URIvalues 包含要更新的字段。
}
public static boolean batchMoveToFolder(ContentResolver resolver, HashSet<Long> ids,
long folderId) {//定义一个静态方法 batchMoveToFolder接受三个参数ContentResolver resolver一个包含多个笔记ID的 HashSet<Long> ids以及目标文件夹ID long folderId。返回一个布尔值表示操作是否成功。
if (ids == null) {
Log.d(TAG, "the ids is null");
return true;//如果传入的ID集合为null则记录日志并返回true
}
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
//创建一个 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等于某个值并且父IDNoteColumns.PARENT_ID不等于另一个值。
new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)},
null);//为查询条件提供具体的值。第一个值是文件夹的类型Notes.TYPE_FOLDER第二个值是垃圾文件夹的IDNotes.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<AppWidgetAttribute> getFolderNoteWidget(ContentResolver resolver, long folderId) {//定义一个静态方法getFolderNoteWidget
//它接受一个ContentResolver和一个长整型folderId作为参数返回一个HashSet<AppWidgetAttribute>。
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<AppWidgetAttribute> set = null;//初始化一个HashSet<AppWidgetAttribute>类型的变量set为null。
if (c != null) {//检查cursor是否为null。
if (c.moveToFirst()) {//如果cursor移动到第一条记录。
set = new HashSet<AppWidgetAttribute>();//初始化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;//返回格式化后的摘要。
}
}