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

380 lines
16 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;
// 导入所需的Android和内容提供者操作的类
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;
// 导入Notes应用中的相关类
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;
// 导入Java工具类
import java.util.ArrayList;
import java.util.HashSet;
// 声明DataUtils工具类
public class DataUtils {
// 定义日志标签
public static final String TAG = "DataUtils";
/**
* 批量删除笔记
* @param resolver 内容解析器
* @param ids 要删除的笔记ID集合
* @return 操作是否成功
*/
public static boolean batchDeleteNotes(ContentResolver resolver, HashSet<Long> ids) {
// 检查ID集合是否为空
if (ids == null) {
Log.d(TAG, "the ids is null");
return true; // 如果为空则认为操作成功可能是一个设计选择但通常应返回false或抛出异常
}
// 检查ID集合是否不包含任何元素
if (ids.size() == 0) {
Log.d(TAG, "no id is in the hashset");
return true; // 同上通常应返回false
}
// 创建操作列表
ArrayList<ContentProviderOperation> operationList = new ArrayList<>();
// 遍历ID集合
for (long id : ids) {
// 检查是否为系统根文件夹ID不应删除
if(id == Notes.ID_ROOT_FOLDER) {
Log.e(TAG, "Don't delete system folder root");
continue; // 跳过系统根文件夹
}
// 创建删除操作并添加到操作列表
ContentProviderOperation.Builder builder = ContentProviderOperation
.newDelete(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id));
operationList.add(builder.build());
}
try {
// 批量执行操作
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; // 如果操作失败则返回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()));
}
return false; // 如果发生异常则返回false
}
/**
* 将笔记移动到指定文件夹
* @param resolver 内容解析器
* @param id 笔记ID
* @param srcFolderId 源文件夹ID
* @param desFolderId 目标文件夹ID
*/
public static void moveNoteToFoler(ContentResolver resolver, long id, long srcFolderId, long desFolderId) {
// 创建要更新的内容值
ContentValues values = new ContentValues();
values.put(NoteColumns.PARENT_ID, desFolderId); // 设置目标文件夹ID
values.put(NoteColumns.ORIGIN_PARENT_ID, srcFolderId); // 设置源文件夹ID可能用于记录或恢复
values.put(NoteColumns.LOCAL_MODIFIED, 1); // 标记笔记为已修改
// 执行更新操作
resolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id), values, null, null);
}
/**
* 批量将笔记移动到指定文件夹
* @param resolver 内容解析器
* @param ids 要移动的笔记ID集合
* @param folderId 目标文件夹ID
* @return 操作是否成功
*/
public static boolean batchMoveToFolder(ContentResolver resolver, HashSet<Long> ids,
long folderId) {
// 检查ID集合是否为空
if (ids == null) {
Log.d(TAG, "the ids is null");
return true; // 同上通常应返回false
}
// 创建操作列表
ArrayList<ContentProviderOperation> operationList = new ArrayList<>();
// 遍历ID集合
for (long id : ids) {
// 创建更新操作并添加到操作列表
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); // 标记笔记为已修改
operationList.add(builder.build());
}
try {
// 批量执行操作
ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList);
// 检查操作结果
if (results == null || results.length == 0 || results[0] == null) {
Log.d(TAG, "move notes failed, ids:" + ids.toString());
return false; // 如果操作失败则返回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()));
}
return false; // 如果发生异常则返回false
}
/**
* 获取用户文件夹数量(排除系统文件夹)
* @param resolver 内容解析器
* @return 用户文件夹数量
*/
public static int getUserFolderCount(ContentResolver resolver) {
// 执行查询操作,获取用户文件夹数量
Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI,
new String[] { "COUNT(*)" }, // 选择要返回的列(这里是计数)
NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?", // 查询条件:类型为文件夹且不是垃圾箱文件夹
new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)}, // 查询参数
null); // 排序(此处不需要)
int count = 0;
if(cursor != null) {
if(cursor.moveToFirst()) {
try {
count = cursor.getInt(0); // 获取计数结果
} catch (IndexOutOfBoundsException e) {
Log.e(TAG, "get folder count failed:" + e.toString()); // 如果发生索引越界异常,则记录错误
} finally {
cursor.close(); // 关闭游标
}
}
}
return count; // 返回用户文件夹数量
}
}
//判断指定类型的笔记是否在笔记数据库中可见(不在回收站中)
public static boolean visibleInNoteDatabase(ContentResolver resolver, long noteId, int type) {
// 使用ContentResolver查询指定ID的笔记过滤条件为类型匹配且父ID不等于回收站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);
boolean exist = false;
if (cursor != null) {
// 如果查询结果不为空,表示笔记存在
if (cursor.getCount() > 0) {
exist = true;
}
cursor.close(); // 关闭Cursor
}
return exist; // 返回笔记是否存在的布尔值
}
//判断指定ID的笔记是否存在于笔记数据库中
public static boolean existInNoteDatabase(ContentResolver resolver, long noteId) {
// 使用ContentResolver查询指定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(); // 关闭Cursor
}
return exist; // 返回笔记是否存在的布尔值
}
//判断指定ID的数据项是否存在于数据数据库中
public static boolean existInDataDatabase(ContentResolver resolver, long dataId) {
// 使用ContentResolver查询指定ID的数据项没有过滤条件
Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId),
null, null, null, null);
boolean exist = false;
if (cursor != null) {
// 如果查询结果不为空,表示数据项存在
if (cursor.getCount() > 0) {
exist = true;
}
cursor.close(); // 关闭Cursor
}
return exist; // 返回数据项是否存在的布尔值
}
//判断指定名称的文件夹是否存在于笔记数据库中且不在回收站中
public static boolean checkVisibleFolderName(ContentResolver resolver, String name) {
// 使用ContentResolver查询文件夹过滤条件为类型为文件夹且父ID不等于回收站ID且摘要名称匹配
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);
boolean exist = false;
if(cursor != null) {
// 如果查询结果不为空,表示文件夹存在
if(cursor.getCount() > 0) {
exist = true;
}
cursor.close(); // 关闭Cursor
}
return exist; // 返回文件夹是否存在的布尔值
}
//获取指定文件夹ID下的所有笔记小部件属性
public static HashSet<AppWidgetAttribute> getFolderNoteWidget(ContentResolver resolver, long folderId) {
// 使用ContentResolver查询指定文件夹ID下的笔记小部件信息
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);
HashSet<AppWidgetAttribute> set = null;
if (c != null) {
if (c.moveToFirst()) { // 移动到Cursor的第一行
set = new HashSet<AppWidgetAttribute>(); // 初始化HashSet
do {
try {
AppWidgetAttribute widget = new AppWidgetAttribute(); // 创建小部件属性对象
widget.widgetId = c.getInt(0); // 获取小部件ID
widget.widgetType = c.getInt(1); // 获取小部件类型
set.add(widget); // 将小部件属性添加到HashSet中
} catch (IndexOutOfBoundsException e) {
Log.e(TAG, e.toString()); // 捕获并打印索引越界异常
}
} while (c.moveToNext()); // 移动到Cursor的下一行
}
c.close(); // 关闭Cursor
}
return set; // 返回包含所有笔记小部件属性的HashSet
}
//根据笔记ID获取关联的电话号码
public static String getCallNumberByNoteId(ContentResolver resolver, long noteId) {
// 使用ContentResolver查询指定笔记ID下的电话号码数据
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);
if (cursor != null && cursor.moveToFirst()) { // 如果Cursor不为空且移动到第一行
try {
return cursor.getString(0); // 返回电话号码
} catch (IndexOutOfBoundsException e) {
Log.e(TAG, "Get call number fails " + e.toString()); // 捕获并打印索引越界异常
} finally {
cursor.close(); // 关闭Cursor
}
}
return ""; // 如果没有找到电话号码,返回空字符串
}
//根据电话号码和通话日期获取笔记ID
public static long getNoteIdByPhoneNumberAndCallDate(ContentResolver resolver, String phoneNumber, long callDate) {
// 使用ContentResolver查询指定电话号码和通话日期下的笔记ID
Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI,
new String [] { CallNote.NOTE_ID },
CallNote.CALL_DATE + "=? AND " + CallNote.MIME_TYPE + "=? AND PHONE_NUMBERS_EQUAL("
+ CallNote.PHONE_NUMBER + ",?)",
new String [] { String.valueOf(callDate), CallNote.CONTENT_ITEM_TYPE, phoneNumber },
null);
if (cursor != null) {
if (cursor.moveToFirst()) { // 如果Cursor不为空且移动到第一行
try {
return cursor.getLong(0); // 返回笔记ID
} catch (IndexOutOfBoundsException e) {
Log.e(TAG, "Get call note id fails " + e.toString()); // 捕获并打印索引越界异常
}
}
cursor.close(); // 关闭Cursor
}
return 0; // 如果没有找到笔记ID返回0
}
//定义一个静态方法用于通过笔记ID从内容提供者中获取笔记摘要
public static String getSnippetById(ContentResolver resolver, long noteId) {
// 使用ContentResolver查询特定URI下的数据
// Notes.CONTENT_NOTE_URI 是笔记内容的URI
// 查询的列只有 NoteColumns.SNIPPET即笔记摘要
// 查询条件是 NoteColumns.ID 等于传入的 noteId
// 最后一个参数为null表示不需要对结果进行排序
Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI,
new String [] { NoteColumns.SNIPPET },
NoteColumns.ID + "=?",
new String [] { String.valueOf(noteId)},
null);
// 检查返回的Cursor是否不为null
if (cursor != null) {
String snippet = ""; // 初始化摘要字符串为空
// 如果Cursor移动到第一行即存在查询结果
if (cursor.moveToFirst()) {
// 从Cursor中获取第一列的数据即SNIPPET列并赋值给snippet变量
snippet = cursor.getString(0);
}
// 关闭Cursor以释放资源
cursor.close();
// 返回查询到的摘要字符串
return snippet;
}
// 如果Cursor为null则抛出异常表示未找到指定ID的笔记
throw new IllegalArgumentException("Note is not found with id: " + noteId);
}
//定义一个静态方法,用于格式化笔记摘要字符串
public static String getFormattedSnippet(String snippet) {
// 如果传入的摘要字符串不为null
if (snippet != null) {
// 去除字符串两端的空白字符
snippet = snippet.trim();
// 查找字符串中第一次出现换行符的位置
int index = snippet.indexOf('\n');
// 如果找到了换行符
if (index != -1) {
// 将字符串截取到换行符之前的位置,即只保留第一行
snippet = snippet.substring(0, index);
}
}
// 返回格式化后的摘要字符串
return snippet;
}