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_reading/src/notes/tool/DataUtils.java

395 lines
15 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 {
private static final String TAG = "DataUtils"; // 日志标签
/**
* 批量删除笔记
* @param resolver 内容解析器用于访问ContentProvider
* @param ids 要删除的笔记ID集合
* @return 删除成功返回true失败返回false
*/
public static boolean batchDeleteNotes(ContentResolver resolver, HashSet<Long> ids) {
// 参数检查如果ID集合为空直接返回成功
if (ids == null) {
Log.d(TAG, "the ids is null");
return true;
}
if (ids.size() == 0) {
Log.d(TAG, "no id is in the hashset");
return true;
}
// 创建批量操作列表
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
for (long id : ids) {
// 安全检查:不允许删除系统根文件夹
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;
}
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;
}
/**
* 将笔记移动到指定文件夹
* @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 移动成功返回true失败返回false
*/
public static boolean batchMoveToFolder(ContentResolver resolver, HashSet<Long> ids,
long folderId) {
// 参数检查
if (ids == null) {
Log.d(TAG, "the ids is null");
return true;
}
// 创建批量操作列表
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
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, "delete notes failed, ids:" + ids.toString());
return 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;
}
/**
* 获取用户文件夹数量(排除系统文件夹)
* @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;
}
/**
* 检查指定类型和ID的笔记是否在数据库中可见不在垃圾箱中
* @param resolver 内容解析器
* @param noteId 笔记ID
* @param type 笔记类型
* @return 如果存在且可见返回true否则返回false
*/
public static boolean visibleInNoteDatabase(ContentResolver resolver, long noteId, int type) {
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();
}
return exist;
}
/**
* 检查指定ID的笔记是否存在于数据库中
* @param resolver 内容解析器
* @param noteId 笔记ID
* @return 如果存在返回true否则返回false
*/
public static boolean existInNoteDatabase(ContentResolver resolver, long noteId) {
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;
}
/**
* 检查指定ID的数据项是否存在于数据表中
* @param resolver 内容解析器
* @param dataId 数据项ID
* @return 如果存在返回true否则返回false
*/
public static boolean existInDataDatabase(ContentResolver resolver, long dataId) {
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();
}
return exist;
}
/**
* 检查指定名称的文件夹是否已存在(可见文件夹,不在垃圾箱中)
* @param resolver 内容解析器
* @param name 文件夹名称
* @return 如果存在返回true否则返回false
*/
public static boolean checkVisibleFolderName(ContentResolver resolver, String 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);
boolean exist = false;
if(cursor != null) {
if(cursor.getCount() > 0) {
exist = true;
}
cursor.close();
}
return exist;
}
/**
* 获取文件夹中所有笔记关联的小部件属性
* @param resolver 内容解析器
* @param folderId 文件夹ID
* @return 小部件属性集合如果没有返回null
*/
public static HashSet<AppWidgetAttribute> getFolderNoteWidget(ContentResolver resolver, long folderId) {
// 查询文件夹中所有笔记的小部件信息
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()) {
set = new HashSet<AppWidgetAttribute>();
do {
try {
// 创建小部件属性对象并添加到集合
AppWidgetAttribute widget = new AppWidgetAttribute();
widget.widgetId = c.getInt(0); // 小部件ID
widget.widgetType = c.getInt(1); // 小部件类型
set.add(widget);
} catch (IndexOutOfBoundsException e) {
Log.e(TAG, e.toString());
}
} while (c.moveToNext());
}
c.close();
}
return set;
}
/**
* 根据笔记ID获取对应的电话号码用于通话记录笔记
* @param resolver 内容解析器
* @param noteId 笔记ID
* @return 电话号码,如果不存在返回空字符串
*/
public static String getCallNumberByNoteId(ContentResolver resolver, long 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);
if (cursor != null && cursor.moveToFirst()) {
try {
return cursor.getString(0); // 返回电话号码
} catch (IndexOutOfBoundsException e) {
Log.e(TAG, "Get call number fails " + e.toString());
} finally {
cursor.close(); // 确保游标被关闭
}
}
return ""; // 没有找到返回空字符串
}
/**
* 根据电话号码和通话日期获取对应的笔记ID
* @param resolver 内容解析器
* @param phoneNumber 电话号码
* @param callDate 通话日期
* @return 笔记ID如果不存在返回0
*/
public static long getNoteIdByPhoneNumberAndCallDate(ContentResolver resolver, String phoneNumber, long callDate) {
// 使用自定义的PHONE_NUMBERS_EQUAL函数比较电话号码
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()) {
try {
return cursor.getLong(0); // 返回笔记ID
} catch (IndexOutOfBoundsException e) {
Log.e(TAG, "Get call note id fails " + e.toString());
}
}
cursor.close();
}
return 0; // 没有找到返回0
}
/**
* 根据笔记ID获取内容摘要
* @param resolver 内容解析器
* @param noteId 笔记ID
* @return 笔记内容摘要
* @throws IllegalArgumentException 如果笔记不存在抛出异常
*/
public static String getSnippetById(ContentResolver resolver, long noteId) {
Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI,
new String [] { NoteColumns.SNIPPET },
NoteColumns.ID + "=?",
new String [] { String.valueOf(noteId)},
null);
if (cursor != null) {
String snippet = "";
if (cursor.moveToFirst()) {
snippet = cursor.getString(0); // 获取内容摘要
}
cursor.close();
return snippet;
}
throw new IllegalArgumentException("Note is not found with id: " + noteId);
}
/**
* 格式化内容摘要(去除首尾空格,只保留第一行)
* @param snippet 原始内容摘要
* @return 格式化后的内容摘要
*/
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;
}
}