首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

android监听文件和目录的创建删除移动等事件

  • 25-04-18 23:46
  • 3603
  • 6902
juejin.cn

android.os下的FileObserver类是一个用于监听文件访问、创建、修改、删除、移动等操作的监听器,基于linux的inotify。 FileObserver 是个抽象类,必须继承它才能使用。每个FileObserver对象监听一个单独的文件或者文件夹,如果监视的是一个文件夹,那么文件夹下所有的文件和级联子目录的改变都会触发监听的事件。 所能监听的事件类型如下: ACCESS,即文件被访问 MODIFY,文件被 修改 ATTRIB,文件属性被修改,如 chmod、chown、touch 等 CLOSE_WRITE,可写文件被 close CLOSE_NOWRITE,不可写文件被 close OPEN,文件被 open MOVED_FROM,文件被移走,如 mv MOVED_TO,文件被移来,如 mv、cp CREATE,创建新文件 DELETE,文件被删除,如 rm DELETE_SELF,自删除,即一个可执行文件在执行时删除自己 MOVE_SELF,自移动,即一个可执行文件在执行时移动自己 CLOSE,文件被关闭,等同于(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) ALL_EVENTS,包括上面的所有事件 这些都是FileObserver的静态共有属性。 下面举个例子说明一下其用法。 比如,我要监听sd卡的目录创建事件,新建一个类SDCardListener继承FileObserver:

scala
代码解读
复制代码
import android.os.FileObserver; import android.util.Log; /** * sd卡上的目录创建监听器 * @author chroya * */ public class SDCardListener extends FileObserver { public SDCardListener(String path) { /* * 这种构造方法是默认监听所有事件的,如果使用super(String,int)这种构造方法, * 则int参数是要监听的事件类型. */ super(path); } @Override public void onEvent(int event, String path) { switch(event) { case FileObserver.ALL_EVENTS: Log.d("all", "path:"+ path); break; case FileObserver.CREATE: Log.d("Create", "path:"+ path); break; } } }

onEvent是回调,系统监听到事件后会触发此事件,参数event就是上面所说的事件类型,根据类型,我们可以做相应的处理,参数path就是触发事件的目录。

然后使用它:

scss
代码解读
复制代码
SDCardListener listener = new SDCardListener("/sdcard"); //开始监听 listener.startWatching(); /* * 在这里做一些操作,比如创建目录什么的 */ //最后停止监听 listener.stopWatching();

 如果要在onEvent中做较多操作,最好用线程去做 ,以免因为阻塞接收不到后面的事件。 最后补充一点,比较重要 : FileObserver对象必须保持一个引用,确保不被垃圾收集器回收掉,否则就不会触发事件了。

让我们实现 FileObserver + 前台服务 的结合,确保在后台持续监听,即使应用被杀掉也能保持运行!下面分成几部分来讲解:

🚦一、前台服务基本结构

在 Android 中,前台服务需要:

  • 创建 Service 来管理 FileObserver。
  • 创建通知,确保服务在前台运行,避免系统回收。
  • 启动服务时,绑定 FileObserver。

🏗️二、创建前台服务

1. FileMonitorService.java

java
代码解读
复制代码
java复制编辑import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.Service; import android.content.Intent; import android.os.Build; import android.os.FileObserver; import android.os.IBinder; import android.util.Log; public class FileMonitorService extends Service { private static final String TAG = "FileMonitorService"; private static final String CHANNEL_ID = "FileMonitorChannel"; private SDCardListener fileObserver; private String directoryPath = "/sdcard"; // 替换为你要监听的目录 @Override public void onCreate() { super.onCreate(); createNotificationChannel(); startForeground(1, createNotification()); startFileObserver(); Log.d(TAG, "Service started and observer initialized."); } private void startFileObserver() { fileObserver = new SDCardListener(directoryPath); fileObserver.startWatching(); Log.d(TAG, "Started watching: " + directoryPath); } private void stopFileObserver() { if (fileObserver != null) { fileObserver.stopWatching(); Log.d(TAG, "Stopped watching: " + directoryPath); } } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; // 确保服务在被系统杀掉时重启 } @Override public void onDestroy() { super.onDestroy(); stopFileObserver(); Log.d(TAG, "Service destroyed and observer stopped."); } @Override public IBinder onBind(Intent intent) { return null; } private void createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel( CHANNEL_ID, "File Monitor Service", NotificationManager.IMPORTANCE_LOW); NotificationManager manager = getSystemService(NotificationManager.class); if (manager != null) { manager.createNotificationChannel(channel); } } } private Notification createNotification() { Notification.Builder builder = new Notification.Builder(this) .setContentTitle("File Monitoring Active") .setContentText("Watching directory: " + directoryPath) .setSmallIcon(android.R.drawable.ic_menu_info_details); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { builder.setChannelId(CHANNEL_ID); } return builder.build(); } }

2. SDCardListener.java

java
代码解读
复制代码
java复制编辑import android.os.FileObserver; import android.util.Log; public class SDCardListener extends FileObserver { private static final String TAG = "SDCardListener"; public SDCardListener(String path) { super(path, FileObserver.ALL_EVENTS); } @Override public void onEvent(int event, String path) { switch (event) { case FileObserver.CREATE: Log.d(TAG, "File created: " + path); break; case FileObserver.DELETE: Log.d(TAG, "File deleted: " + path); break; case FileObserver.MODIFY: Log.d(TAG, "File modified: " + path); break; case FileObserver.MOVED_FROM: Log.d(TAG, "File moved from: " + path); break; case FileObserver.MOVED_TO: Log.d(TAG, "File moved to: " + path); break; default: Log.d(TAG, "Event " + event + " on: " + path); break; } } }

3. AndroidManifest.xml 中声明服务和权限

ini
代码解读
复制代码
xml复制编辑name="android.permission.FOREGROUND_SERVICE" /> name="android.permission.WRITE_EXTERNAL_STORAGE" /> name="android.permission.READ_EXTERNAL_STORAGE" /> android:name=".FileMonitorService" android:foregroundServiceType="dataSync" />

4. 启动/停止服务

你可以在 MainActivity 里启动/停止前台服务:

scala
代码解读
复制代码
java复制编辑import android.content.Intent; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 启动服务 Intent intent = new Intent(this, FileMonitorService.class); startForegroundService(intent); } @Override protected void onDestroy() { super.onDestroy(); // 停止服务 Intent intent = new Intent(this, FileMonitorService.class); stopService(intent); } }

🎯五、运行效果

  1. 启动 App 后,通知栏显示“File Monitoring Active”,服务进入前台。
  2. 任何对 /sdcard 目录的操作(如文件创建、删除、修改、移动等),都会触发 SDCardListener,输出日志。
  3. App 被杀掉后,服务依然存活,持续监听。即使系统回收,也会自动重启(START_STICKY)。

⚡六、优化建议

  • 递归监听子目录:
    FileObserver 不能自动递归监听所有子目录。如果需要递归监听,创建多个 FileObserver 对象,每个对象监听一个子目录。
  • 电量优化:
    FileObserver 是 native 的 inotify 实现,功耗较低,但频繁操作大目录时,建议加上事件合并、去抖动逻辑。
  • 异常处理:
    防止监听路径被删除、SD 卡拔出、权限丢失等意外情况引起的崩溃。
注:本文转载自juejin.cn的小叶不焦虑的文章"https://juejin.cn/post/7481205186818523173"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

140
Android
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top