Android 10下Nearby Connections API无法访问接收文件的问题
别担心,Android 10上用Nearby Connections API实现接收文件并上传完全是可行的,你遇到的问题主要是Scoped Storage(分区存储)限制导致的,咱们一步步来解决:
问题根源分析
Android 10引入的Scoped Storage限制了APP对公共目录(比如Downloads)的直接路径访问,Nearby Connections接收的文件存在Downloads/Nearby下,这时候用asJavaFile()获取File对象会返回null——因为File需要依赖文件路径,但你的APP没有权限直接访问这个公共目录的路径。不过Nearby已经通过ParcelFileDescriptor给了你访问该文件的临时权限,这才是正确的操作入口。
正确的文件读取与上传方案
你不需要通过MediaStore或者文件路径来访问文件,直接利用ParcelFileDescriptor提供的权限操作输入流即可,下面是具体实现:
1. 读取文件流(适用于上传或Bitmap处理)
使用try-with-resources语法自动管理资源,避免权限或资源泄漏问题:
// 获取ParcelFileDescriptor try (ParcelFileDescriptor pfd = filePayload.asFile().asParcelFileDescriptor()) { if (pfd == null) { // 处理异常情况 return; } // 读取文件输入流 try (FileInputStream inputStream = new FileInputStream(pfd.getFileDescriptor())) { // 如果你需要转成Bitmap: Bitmap bitmap = BitmapFactory.decodeStream(inputStream); // 后续Bitmap操作... // 如果你要直接上传到REST API,推荐直接用流上传,不需要转Bitmap uploadFileToApi(inputStream); } } catch (IOException e) { e.printStackTrace(); }
2. 直接上传到REST API(高效方案)
直接用文件流上传比转成Bitmap再上传更高效,以OkHttp为例:
private void uploadFileToApi(InputStream inputStream) throws IOException { OkHttpClient client = new OkHttpClient(); // 大文件推荐用流式写入,避免一次性读入内存 RequestBody requestBody = new RequestBody() { @Override public MediaType contentType() { return MediaType.parse("image/jpeg"); // 根据实际文件类型调整 } @Override public void writeTo(BufferedSink sink) throws IOException { sink.writeAll(Okio.source(inputStream)); } }; Request request = new Request.Builder() .url("你的REST API上传地址") .post(requestBody) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { // 处理上传失败逻辑 } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { // 上传成功逻辑 } else { // 处理错误响应 } } }); }
额外注意事项
- 不要试图通过MediaStore访问这些文件:Nearby保存的文件没有被MediaStore索引,且无扩展名,所以即使扫描也无法被识别,完全没必要走这条路。
- 依赖版本:你用的
com.google.android.gms:play-services-nearby:17.0.0是兼容Android 10的,但可以考虑升级到最新稳定版(比如20.x系列),获取更多bug修复和优化。 - 权限有效期:
ParcelFileDescriptor的权限是临时的,要确保在接收文件的回调生命周期内完成读取/上传操作,不要保存这个对象到后续使用。
这样就能顺利实现接收文件并上传的功能了。
内容的提问来源于stack exchange,提问作者Christian Jensen
相关产品推荐
相关产品推荐

