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

Android Studio中蓝牙发送.txt文件无法弹出设备选择窗口报错求解

问题原因

你遇到的两个报错和蓝牙窗口不弹出的问题核心来自三个错误:

  • Fail to get file list com.example.apptest:蓝牙OPP传输进程没有权限读取你的APP私有目录下的文件,你未给目标应用授予FileProvider的临时访问权限,同时可能存在FileProvider路径配置错误。
  • getFolderSize() : Exception_1 = java.lang.NullPointerException: Attempt to get length of null array:蓝牙进程读取文件内容失败,获取文件大小的时候拿到空数组触发空指针,通常是文件未写入完成、或无权限读取文件导致。
  • 硬编码蓝牙组件类名:不同厂商的系统蓝牙应用包名、类名可能存在定制修改,硬编码com.android.bluetooth.opp.BluetoothOppLauncherActivity会导致大量机型无法匹配到对应的页面,自然弹不出选择窗口。

修复步骤

1. 配置正确的FileProvider路径

检查你res/xml目录下的FileProvider配置文件(默认命名为file_paths.xml),添加你存储文件的私有目录映射:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 对应getDir("DirFile", MODE_PRIVATE)生成的app_DirFile目录 -->
    <files-path name="shared_dir" path="../app_DirFile/" />
</paths>

同时确认AndroidManifest.xml中已经正确注册FileProvider:

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

2. 给Intent添加临时读取权限

传输文件时需要给接收Intent的应用授予Uri的临时读取权限,否则蓝牙进程无法访问你提供的文件路径。

3. 写入文件后主动flush缓冲区

数据写入FileOutputStream后会先存在内存缓冲区,需要主动flush才能确保数据落地到磁盘,避免读取到空文件。

4. 移除硬编码的蓝牙组件名,使用系统通用选择器

不要写死蓝牙的类名,使用Intent.createChooser让系统自动匹配支持分享的应用,兼容性更好。


修复后的完整代码

public void sendData(){
    String sensorName = tvSensorName.getText().toString();
    String s1 = tvS1.getText().toString();
    String s2 = tvS2.getText().toString();
    String s3 = tvS3.getText().toString();
    String s4 = tvS4.getText().toString();

    String allData = sensorName + ";" + s1 + ";" + s2 + ";" + s3 + ";" + s4 + ";";


    File ficheiro_dir = getApplicationContext().getDir("DirFile", MODE_PRIVATE);
    File ficheiro = new File(ficheiro_dir, FILE_NAME);
    FileOutputStream fos = null;

    try {
        fos = new FileOutputStream(ficheiro,true);
        fos.write(allData.getBytes(StandardCharsets.UTF_8));
        // 新增:主动flush缓冲区,确保数据写入磁盘
        fos.flush();

        Toast.makeText(this, "Saved to " + ficheiro.getPath(), Toast.LENGTH_LONG).show();
        if(ficheiro.exists())
            Toast.makeText(this, "EXIST", Toast.LENGTH_LONG).show();
        else
            Toast.makeText(this, "NOT EXIST", Toast.LENGTH_LONG).show();

        Uri uri = FileProvider.getUriForFile(
                SensorSelectedActivity.this,
                BuildConfig.APPLICATION_ID + ".provider",
                ficheiro);
        String type = "text/plain";

        Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
        sharingIntent.setType(type);
        // 新增:授予临时读取权限
        sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        // 移除硬编码的蓝牙类名,使用系统选择器
        sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
        // 弹出分享选择器
        startActivity(Intent.createChooser(sharingIntent, "发送文件到"));

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (fos != null) {
            try {
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Diogo Simao

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 15:09:01