You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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'

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:59:34