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.
git.text/src/tool/DataUtils.java

381 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;
/**
* 便签数据操作工具类,封装数据库查询、更新、删除等常用操作,
* 提供与ContentProvider交互的统一接口支撑UI层的数据需求
*/
public class DataUtils {
public static final String TAG = "DataUtils";
/**
* 批量删除便签或文件夹(跳过系统根目录)
* @param resolver 内容解析器,用于操作数据库
* @param ids 待删除的便签/文件夹ID集合
* @return 操作成功返回true失败返回false
*/
public static boolean batchDeleteNotes(ContentResolver resolver, HashSet<Long> ids) {
if (ids == null) {
Log.d(TAG, "待删除的ID集合为null");
return true;
}
if (ids.size() == 0) {
Log.d(TAG, "待删除的ID集合为空");
return true;
}
// 创建批量删除操作列表
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
for (long id : ids) {
// 禁止删除系统根目录
if(id == Notes.ID_ROOT_FOLDER) {
Log.e(TAG, "不能删除系统根目录文件夹");
continue;
}
// 构建删除操作根据ID删除便签
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, "删除失败ID集合:" + 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, "待移动的ID集合为null");
return true;
}
// 创建批量更新操作列表
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
for (long id : ids) {
// 构建更新操作修改父目录ID
ContentProviderOperation.Builder builder = ContentProviderOperation
.newUpdate(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id));
builder.withValue(NoteColumns.PARENT_ID, folderId);
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, "移动失败ID集合:" + 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, "获取文件夹数量失败:" + e.toString());
} finally {
cursor.close();
}
}
}
return count;
}
/**
* 检查便签是否存在且可见(不在垃圾站中)
* @param resolver 内容解析器
* @param noteId 便签ID
* @param type 便签类型如Notes.TYPE_NOTE
* @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) {
exist = cursor.getCount() > 0; // 游标有数据则存在
cursor.close();
}
return exist;
}
/**
* 检查便签是否存在(包括垃圾站中的便签)
* @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) {
exist = cursor.getCount() > 0;
cursor.close();
}
return exist;
}
/**
* 检查便签内容数据是否存在
* @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) {
exist = cursor.getCount() > 0;
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 + "=?", // SNIPPET字段存储文件夹名称
new String[] { name }, null);
boolean exist = false;
if(cursor != null) {
exist = cursor.getCount() > 0;
cursor.close();
}
return exist;
}
/**
* 获取文件夹下所有便签关联的桌面小部件属性
* @param resolver 内容解析器
* @param folderId 文件夹ID
* @return 小部件属性集合包含widgetId和widgetType
*/
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 }, // 查询小部件ID和类型
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);
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, "获取电话号码失败 " + 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) {
Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI,
new String [] { CallNote.NOTE_ID }, // 查询关联的便签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);
} catch (IndexOutOfBoundsException e) {
Log.e(TAG, "获取通话便签ID失败 " + e.toString());
}
}
cursor.close();
}
return 0;
}
/**
* 通过便签ID获取摘要文本用于列表页展示
* @param resolver 内容解析器
* @param noteId 便签ID
* @return 摘要文本,便签不存在则抛出异常
*/
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("未找到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;
}
}