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

Android 11下免MANAGE_STORAGE_ACCESS权限无交互读取卸载留存纯文本文件方案

Android 11 无交互读取BLE配对信息文件解决方案

核心背景说明

Android 11 引入的分区存储机制中,通过MediaStore创建的非媒体类自定义文件,在应用卸载后确实会丢失直接访问权限,你要求的无用户交互、不申请MANAGE_EXTERNAL_STORAGE权限的前提下,有两种可行实现方案:

方案1:直接读取系统蓝牙配对记录(最优解)

你提到系统蓝牙管理器本身会留存已配对设备记录,完全可以跳过自定义文件持久化逻辑,直接通过系统蓝牙接口读取设备Mac地址,不需要任何存储权限,也完全不受应用卸载影响:

  • 仅需要常规蓝牙权限,适配起来没有兼容问题
  • 代码示例:
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter.isEnabled()) {
    Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
    for (BluetoothDevice device : bondedDevices) {
        String macAddress = device.getAddress();
        // 结合设备名、服务UUID等特征筛选你需要的BLE设备即可
    }
}

方案2:保留自定义文件逻辑的适配方法

如果业务必须保留自定义文本文件存储配对信息的逻辑,可以按以下规则实现:

  • 写入文件阶段:将文本文件存入公共下载目录Environment.DIRECTORY_DOWNLOADS,文件名添加应用专属前缀(比如com_xxx_ble_bonded_list.txt),写入操作不需要额外存储权限
  • 读取文件阶段:应用重装后不需要申请存储权限,直接通过MediaStore查询公共下载目录下匹配你专属文件名的文件即可读取内容,Android 10及以上版本原生支持该操作,无需用户交互
  • 代码示例:
val projection = arrayOf(MediaStore.Files.FileColumns._ID, MediaStore.Files.FileColumns.DISPLAY_NAME)
val selection = "${MediaStore.Files.FileColumns.DISPLAY_NAME} = ?"
val selectionArgs = arrayOf("com_xxx_ble_bonded_list.txt")
val contentUri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL)

contentResolver.query(contentUri, projection, selection, selectionArgs, null)?.use { cursor ->
    if (cursor.moveToFirst()) {
        val fileId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID))
        val targetUri = ContentUris.withAppendedId(contentUri, fileId)
        contentResolver.openInputStream(targetUri)?.use { inputStream ->
            // 直接读取输入流中的文本内容即可
        }
    }
}

注意事项

不要尝试用内部存储、SharedPreferences存储配对信息,应用卸载后这些数据会被系统自动清除,无法满足持久化需求。

内容的提问来源于stack exchange,提问作者Varsha Kulkarni

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 17:45:01