Commit 7d6614a1 authored by wanglei's avatar wanglei

Merge branch 'master' of gitlab.huolea.com:koko/file-recovery-recyclebin

parents 7b02ca2e 71854bf7
......@@ -88,11 +88,11 @@ class MediaContentObserver(val context: Context) : ContentObserver(null) {
if (src.length() > 0L) {
val recycleBinFile = File(getRecycleBinDir(), ".$name")
src.copyTo(recycleBinFile, true)
val binBean = RecycleBinBean(src.path, uri, deleteTime = 0, size = src.length(), mimeType = mimeType)
val binFile = File(recycleBinDir, ".$name.bin")
binFile.createNewFile()
binFile.writeText(Gson().toJson(binBean))
LogEx.logDebug(TAG, "RecycleBin backup")
// val binBean = RecycleBinBean(src.path, uri, deleteTime = 0, size = src.length(), mimeType = mimeType)
// val binFile = File(recycleBinDir, ".$name.bin")
// binFile.createNewFile()
// binFile.writeText(Gson().toJson(binBean))
// LogEx.logDebug(TAG, "RecycleBin backup")
}
}
}
......@@ -4,7 +4,6 @@ import android.net.Uri
data class RecycleBinBean(
val path: String = "",
val uri: Uri = Uri.EMPTY,
var deleteTime: Long = 0,
val size: Long = 0,
val mimeType: String = "",
......
......@@ -16,6 +16,7 @@ import com.base.filerecoveryrecyclebin.databinding.FragmentRecycleBinBinding
import com.base.filerecoveryrecyclebin.help.BaseFragment
import com.base.filerecoveryrecyclebin.help.PermissionHelp.checkStorePermission
import com.base.filerecoveryrecyclebin.help.PermissionHelp.requestStorePermission
import com.base.filerecoveryrecyclebin.service.BackUpUtils
import com.base.filerecoveryrecyclebin.utils.LogEx
import com.base.filerecoveryrecyclebin.view.DialogViews.showGerPermission
import com.google.gson.Gson
......@@ -78,22 +79,15 @@ class RecycleBinFragment : BaseFragment<FragmentRecycleBinBinding>() {
private fun initData() {
lifecycleScope.launch(Dispatchers.IO) {
val binList = getRecycleBinDir().listFiles()?.filter { it.name.contains(".bin") }
val beanList = arrayListOf<RecycleBinBean>()
binList?.forEach {
LogEx.logDebug(TAG, it.absolutePath)
val bean = Gson().fromJson(it.readText(), RecycleBinBean::class.java)
beanList.add(bean)
}
val deleteFile = beanList.filter { it.deleted }
// val deleteFile = beanList
val beanList = BackUpUtils.getBackUpListObj()
val deleteFile = beanList?.filter { it.deleted }
launch(Dispatchers.Main) {
binding.rv.isVisible = deleteFile.isNotEmpty()
binding.llEmpty.isVisible = deleteFile.isEmpty()
recycleBinAdapter.setData(deleteFile)
binding.rv.isVisible = deleteFile?.isNotEmpty() == true
binding.llEmpty.isVisible = deleteFile?.isEmpty() == true
if (deleteFile != null) {
recycleBinAdapter.setData(deleteFile)
}
}
}
}
......
package com.base.filerecoveryrecyclebin.service
import android.text.TextUtils
import com.base.filerecoveryrecyclebin.activity.recyclebin.RecycleBinFileEx.getRecycleBinDir
import com.base.filerecoveryrecyclebin.bean.RecycleBinBean
import com.base.filerecoveryrecyclebin.utils.AppPreferences
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.ironsource.da
import java.io.File
import java.util.stream.Collectors
object BackUpUtils {
private const val KEY = "backup_key"
fun backupFile(src: File, path: String) {
val recycleBinFile = File(getRecycleBinDir(), ".\$name")
src.copyTo(recycleBinFile, true)
val binBean = RecycleBinBean(src.path, 0, src.length(), getFileExtension(src), false)
saveData(binBean, path)
}
private fun getFileExtension(file: File): String {
val fileName = file.name
return if (fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0) {
fileName.substring(fileName.lastIndexOf(".") + 1)
} else {
""
}
}
fun saveData(binBean: RecycleBinBean, path: String) {
val hashMap = queryBackUpSp()
hashMap.put(path, binBean)
saveBackUpSp(hashMap)
}
fun queryBackUpSp(): HashMap<String, RecycleBinBean> {
val str = AppPreferences.getInstance().getString(KEY, "")
val hastMap: HashMap<String, RecycleBinBean>
if (TextUtils.isEmpty(str)) {
hastMap = HashMap()
} else {
val gson = Gson()
// 使用TypeToken来指定HashMap的类型
hastMap =
gson.fromJson(str, object : TypeToken<HashMap<String, RecycleBinBean>>() {}.type)
}
return hastMap
}
fun saveBackUpSp(hash: HashMap<String, RecycleBinBean>) {
AppPreferences.getInstance().put(KEY, Gson().toJson(hash))
}
fun getBackUpListObj(): List<RecycleBinBean>? {
val hashMap = queryBackUpSp()
if (hashMap.size > 0) {
return null
} else {
val values: MutableList<RecycleBinBean>? =
hashMap.values.stream().collect(Collectors.toList())
return values
}
}
fun queryFileExists(path: String): Boolean {
val hashMap = queryBackUpSp()
return hashMap.contains(path)
}
fun deleteFile(path: String) {
val isExists = queryFileExists(path)
if (isExists) {
val hashMap =queryBackUpSp()
val data = hashMap[path]
if (data != null) {
data?.deleted =true
data?.deleteTime =System.currentTimeMillis()
hashMap[path] = data
}
}
}
}
\ No newline at end of file
package com.base.filerecoveryrecyclebin.service;
import android.os.Environment;
import android.os.FileObserver;
import android.os.Handler;
import android.os.HandlerThread;
import android.text.TextUtils;
import android.util.Log;
import com.base.filerecoveryrecyclebin.MyApplication;
import com.base.filerecoveryrecyclebin.activity.recyclebin.RecycleBinFileEx;
import com.base.filerecoveryrecyclebin.help.FileHelp;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class FileObserverExample {
private static final String TAG = "FileObserverExample";
private HandlerThread fileHandlerThread;
private Handler fileHandler;
public static final Set<String> FILE_EXTENSIONS = new HashSet<>(Arrays.asList(
".jpg", ".jpeg", ".png", ".gif", ".bmp",
".mp4", ".avi", ".mov", ".mkv",
".mp3", ".wav", ".aac",
".pdf", ".doc", ".docx", ".xls", ".xlsx", ".txt"
));
private FileObserver fileObserver;
List<File> watchList;
public void startObserving() {
// 获取外部存储目录
List<File> dcimList = FileHelp.INSTANCE.getFileFolder(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM));
List<File> pictureList = FileHelp.INSTANCE.getFileFolder(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES));
List<File> downloadList = FileHelp.INSTANCE.getFileFolder(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS));
List<File> videoList = FileHelp.INSTANCE.getFileFolder(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES));
watchList = new ArrayList();
watchList.addAll(dcimList);
watchList.addAll(pictureList);
watchList.addAll(downloadList);
watchList.addAll(videoList);
fileHandlerThread = new HandlerThread("FileObserverThread");
fileHandlerThread.start();
fileHandler = new Handler(fileHandlerThread.getLooper());
fileObserver = new FileObserver(watchList, FileObserver.CREATE | FileObserver.DELETE) {
@Override
public void onEvent(int event, String path) {
Log.d(TAG,"onEvent "+ event+" "+path);
if(!TextUtils.isEmpty(path)){
Log.d(TAG,"path: "+path);
handleFileEvent(path, event);
}
}
};
fileObserver.startWatching(); // 启动观察
}
public void stopObserving() {
if (fileObserver != null) {
// 根据 API 版本选择不同的停止方法
fileObserver.stopWatching();
}
}
// 处理文件事件
private void handleFileEvent(String path, int event) {
Log.d(TAG,path);
// 检查文件扩展名是否在监听范围内
if (FILE_EXTENSIONS.contains(getFileExtension(path))) {
if (event == FileObserver.CREATE) {
Log.d(TAG,"CREATE");
fileHandler.post(() -> handleFileCreation(path));
} else if (event == FileObserver.DELETE) {
BackUpUtils.INSTANCE.deleteFile(path);
}
}
}
// 获取文件扩展名
private String getFileExtension( String fileName) {
if (fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0) {
return "."+fileName.substring(fileName.lastIndexOf(".") + 1);
} else {
return "";
}
}
private void handleFileCreation(String path) {
// 确保线程安全,这里我们只是打印出来,实际使用中可能需要同步机制
for (File dir : watchList) {
File src = new File(dir, path);
if (src.exists()) {
Log.d(TAG, "新创建的文件 " + path + " 属于目录: " + dir.getAbsolutePath());
BackUpUtils.INSTANCE.backupFile(src, path);
break;
}
}
}
}
\ No newline at end of file
......@@ -39,6 +39,7 @@ import kotlin.random.Random
class StayNotificationService : Service() {
private val TAG = "StayNotificationService"
private var fileObserver: FileObserverExample? = null
companion object {
const val MEDIA_OBSERVER_ACTION = "media_observer_action"
......@@ -62,17 +63,10 @@ class StayNotificationService : Service() {
@SuppressLint("ForegroundServiceType")
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val action = intent?.action
if (action == MEDIA_OBSERVER_ACTION) {
observerMediaContentObserver()
}
if (action == FILE_OBSERVER_ACTION) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startMyFileObserver()
}
if(fileObserver == null){
fileObserver = FileObserverExample()
}
fileObserver?.startObserving()
if (!isRunning) {
val notification = createPermanentNotification(applicationContext)
startForeground(1, notification)
......@@ -107,10 +101,14 @@ class StayNotificationService : Service() {
fun startMyFileObserver() {
if (myFileObserver == null) {
LogEx.logDebug(TAG, "startMyFileObserver")
val dcimList = FileHelp.getFileFolder(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM))
val pictureList = FileHelp.getFileFolder(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES))
val downloadList = FileHelp.getFileFolder(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS))
val videoList = FileHelp.getFileFolder(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES))
val dcimList =
FileHelp.getFileFolder(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM))
val pictureList =
FileHelp.getFileFolder(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES))
val downloadList =
FileHelp.getFileFolder(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS))
val videoList =
FileHelp.getFileFolder(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES))
val watchList = arrayListOf<File>()
watchList.addAll(dcimList)
......@@ -135,10 +133,8 @@ class StayNotificationService : Service() {
isRunning = false
super.onDestroy()
// 取消监听
mediaContentObserver?.let { this.contentResolver.unregisterContentObserver(it) }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
myFileObserver?.stopWatching()
}
fileObserver?.stopObserving()
}
private fun createPermanentNotification(context: Context): Notification {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment