Android监听Download目录JSON文件无响应问题排查
问题排查与解决方案
我来帮你梳理下这个问题,我之前也碰到过类似的FileObserver不触发的情况,主要有几个核心点需要调整:
1. adb push不会触发MODIFY事件
当你用adb push替换文件时,系统实际执行的不是"修改现有文件内容",而是先删除旧文件,再创建新文件(或者将临时文件移动到目标路径),所以只会触发CREATE、DELETE或MOVED_TO事件,而非你监听的MODIFY。
你需要扩展监听的事件类型,把这些可能的事件都加进去:
class JsonConfigFileObserver(private var path: String, var onModify: (JsonConfig) -> Unit) : FileObserver(path, MODIFY or CREATE or DELETE or MOVED_TO) { // 新增事件类型 override fun onEvent(event: Int, pathNullable: String?) { // 先判断文件是否存在,避免处理删除事件时出错 val targetFile = File(path) if (!targetFile.exists()) return // 只处理和文件更新相关的有效事件 if (event and (MODIFY or CREATE or MOVED_TO) != 0) { Log.d("FileObserver: ", "File Updated") onModify(jsonConfig(path)) } } }
2. 避免直接监听单个文件,改为监听父目录
直接监听单个文件有个致命问题:当文件被删除再重建时,原FileObserver绑定的是旧文件的inode,新文件的inode不同,观察者会直接失效。更好的做法是监听Download目录,然后在事件中判断是否是目标文件:
class JsonConfigFileObserver( private val targetFileName: String, private val parentDirPath: String, var onModify: (JsonConfig) -> Unit ) : FileObserver(parentDirPath, MODIFY or CREATE or DELETE or MOVED_TO) { override fun onEvent(event: Int, pathNullable: String?) { val fileName = pathNullable ?: return // 只处理目标配置文件的事件 if (fileName != targetFileName) return val targetFile = File(parentDirPath, targetFileName) if (!targetFile.exists()) return // 过滤有效更新事件 if (event and (MODIFY or CREATE or MOVED_TO) != 0) { Log.d("FileObserver: ", "Target Config File Updated") onModify(jsonConfig(targetFile.absolutePath)) } } }
然后在Activity中初始化时,改为监听父目录:
val downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) val jsonConfig = JsonConfigFileObserver( FILE_NAME_CONF, downloadDir.absolutePath ) { jsonConfig -> runActionFromConfig(jsonConfig) } jsonConfig.startWatching()
3. 确认存储权限配置
Android 10(API 29)及以上版本对外部存储有严格的访问限制,你需要确保应用拥有READ_EXTERNAL_STORAGE权限:
第一步:在AndroidManifest.xml中添加权限声明
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- 若你的应用需要修改文件,Android 11+可能需要MANAGE_EXTERNAL_STORAGE,仅读文件无需添加 -->
第二步:动态申请权限
在Activity的onCreate中添加权限申请逻辑:
private val REQUEST_STORAGE_PERMISSION = 1001 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ...其他初始化代码 if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), REQUEST_STORAGE_PERMISSION ) } }
4. 管理FileObserver的生命周期
记得在Activity销毁时停止监听,避免内存泄漏:
override fun onDestroy() { super.onDestroy() jsonConfig.stopWatching() }
额外验证:adb push路径是否正确
你当前的adb命令路径可能存在问题,建议用绝对路径推送:
adb push myConfigFile.json /storage/emulated/0/Download/
按照这些步骤调整后,你应该能正常收到文件更新的事件了。
内容的提问来源于stack exchange,提问作者Jéwôm'
相关产品推荐
相关产品推荐

