/* * 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.model; import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; import android.util.Log; import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.tool.DataUtils; import java.util.HashSet; /** * 最近删除管理器,负责管理最近删除的便签和文件夹 * 采用单例模式设计,提供获取最近删除项、恢复项、永久删除项、清空回收站等功能 */ public class RecentlyDeletedManager { // 默认保留天数,超过此天数的已删除项将被自动清理 public static final int DEFAULT_RETENTION_DAYS = 30; // 清理任务间隔(每天) public static final long CLEANUP_INTERVAL = 24 * 60 * 60 * 1000; private Context mContext; private ContentResolver mContentResolver; // 单例实例 private static RecentlyDeletedManager sInstance; // 日志标签 private static final String TAG = "RecentlyDeletedManager"; /** * 私有构造方法,防止外部实例化 * @param context 上下文对象 */ private RecentlyDeletedManager(Context context) { mContext = context.getApplicationContext(); mContentResolver = mContext.getContentResolver(); } /** * 获取单例实例 * @param context 上下文对象 * @return 最近删除管理器实例 */ public static synchronized RecentlyDeletedManager getInstance(Context context) { if (sInstance == null) { sInstance = new RecentlyDeletedManager(context); } return sInstance; } /** * 获取最近删除的项列表 * @return 最近删除项的游标,按删除时间倒序排列 */ public Cursor getRecentlyDeletedItems() { // 查询条件:已删除(DELETED_DATE > 0)且位于回收站文件夹 String selection = NoteColumns.DELETED_DATE + " > 0 AND " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER; // 按删除时间倒序排序 String sortOrder = NoteColumns.DELETED_DATE + " DESC"; try { return mContentResolver.query( Notes.CONTENT_NOTE_URI, null, // 查询所有列 selection, null, sortOrder ); } catch (Exception e) { Log.e(TAG, "Failed to get recently deleted items", e); return null; } } /** * 恢复指定项 * @param itemIds 要恢复的项ID数组 * @return 成功恢复的项数量 */ public int restoreItems(long[] itemIds) { if (itemIds == null || itemIds.length == 0) { return 0; } int restoredCount = 0; for (long itemId : itemIds) { try { // 获取原父文件夹ID String[] projection = {NoteColumns.ORIGIN_PARENT_ID}; String selection = NoteColumns.ID + "=" + itemId; Cursor cursor = mContentResolver.query( Notes.CONTENT_NOTE_URI, projection, selection, null, null ); if (cursor != null && cursor.moveToFirst()) { long originParentId = cursor.getLong(0); cursor.close(); // 如果原父文件夹不存在或已被删除,使用根文件夹 long targetParentId = originParentId != Notes.ID_TRASH_FOLER ? originParentId : Notes.ID_ROOT_FOLDER; // 使用现有的batchMoveToFolder方法来恢复项目 HashSet ids = new HashSet(); ids.add(itemId); if (DataUtils.batchMoveToFolder(mContentResolver, ids, targetParentId)) { restoredCount++; } } else if (cursor != null) { cursor.close(); } } catch (Exception e) { Log.e(TAG, "Failed to restore item: " + itemId, e); } } return restoredCount; } /** * 永久删除指定项 * @param itemIds 要永久删除的项ID数组 * @return 成功永久删除的项数量 */ public int permanentlyDeleteItems(long[] itemIds) { if (itemIds == null || itemIds.length == 0) { return 0; } int deletedCount = 0; for (long itemId : itemIds) { try { int rowsAffected = mContentResolver.delete( Notes.CONTENT_NOTE_URI, NoteColumns.ID + "=" + itemId, null ); if (rowsAffected > 0) { deletedCount++; } } catch (Exception e) { Log.e(TAG, "Failed to permanently delete item: " + itemId, e); } } return deletedCount; } /** * 清空回收站 * @return 成功清空的项数量 */ public int emptyTrash() { try { // 删除所有已删除且位于回收站的项 String selection = NoteColumns.DELETED_DATE + " > 0 AND " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER; return mContentResolver.delete( Notes.CONTENT_NOTE_URI, selection, null ); } catch (Exception e) { Log.e(TAG, "Failed to empty trash", e); return 0; } } /** * 清理超过保留天数的项 * @param retentionDays 保留天数 * @return 成功清理的项数量 */ public int cleanupOldItems(int retentionDays) { if (retentionDays < 0) { retentionDays = DEFAULT_RETENTION_DAYS; } try { // 计算清理阈值:当前时间减去保留天数(毫秒) long cleanupThreshold = System.currentTimeMillis() - (retentionDays * 24 * 60 * 60 * 1000); // 删除条件:已删除且删除时间小于清理阈值 String selection = NoteColumns.DELETED_DATE + " > 0 AND " + NoteColumns.DELETED_DATE + " < " + cleanupThreshold; return mContentResolver.delete( Notes.CONTENT_NOTE_URI, selection, null ); } catch (Exception e) { Log.e(TAG, "Failed to cleanup old items", e); return 0; } } /** * 启动自动清理任务 * 注意:此方法在当前实现中仅作为占位符,实际自动清理逻辑由TrashCleanupWorker实现 */ public void startAutoCleanup() { // 自动清理任务由TrashCleanupWorker处理,此处预留接口 Log.d(TAG, "Auto cleanup task is managed by TrashCleanupWorker"); } }