4

I am following this guide with the goal of transferring an image file which on the receiver side should be uploaded via a REST API.

Android 10 blocks access to public folders like the 'Downloads' folder in which all received files from Nearby Connections API are stored in, in a 'Nearby' folder.

File payloadFile = filePayload.asFile().asJavaFile();

I have a Payload object, and as the guide suggests the code above should get the file. Unfortunately the above code returns null when targeting api 29 and running on an Android 10 device. Works fine on earlier Android versions.

I can get the ParcelFileDescriptor by doing File payloadFile = filePayload.asFile().asParcelFileDescriptor(); but not sure how to access the file then?

Via the ParcelFileDescriptor I have tried reading the file in the following ways but I always get some kind of permission or bad access exception:

BitmapFactory.decodeStream(FileInputStream(payloadFileDescriptor.fileDescriptor)) or BitmapFactory.decodeFileDescriptor(payloadFileDescriptor.fileDescriptor)

The file is stored correctly in the Downloads folder as I can see and open it via a file browser app.

Also tried accessing via a content resolver (MediaStore.Downloads.EXTERNAL_CONTENT_URI and MediaStore.Images.EXTERNAL_CONTENT_URI) but no luck.

A note here is that the files are save with no extension, so maybe that's why Mediastore can't find anything?

I use "com.google.android.gms:play-services-nearby:17.0.0".

As mentioned I really want to receive a file and upload it. Is this totally impossible with Nearby Connections API on Android 10?

  • How do you know the file is in the Download folder? – blackapps Jan 30 '20 at 13:16
  • `I am following this guide.` ?? To do what? Please tell what you want. – blackapps Jan 30 '20 at 13:16
  • `I can get the ParcelFileDescriptor ` Well show your code. How should we know what you are doing? – blackapps Jan 30 '20 at 13:17
  • `My goal is ending up with a readable File object.` That is not possible under Android Q. But it is possible to get a nice content scheme uri for the file. Querying the MediaStore should give you one. – blackapps Jan 30 '20 at 13:21
  • Quote: `// Get the received file (which will be in the Downloads folder) File payloadFile = filePayload.asFile().asJavaFile(); `Indeed that is what the doc tells. But stil... think that under Android Q this will not work.. – blackapps Jan 30 '20 at 13:26
  • Quote: `filePayload = Payload.fromFile(pfd); DOes that not work for you. Then you have the content of the file. ` – blackapps Jan 30 '20 at 13:28
  • If you prefer to read the content of the file using an input stream then change `ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(uri, "r"); ` to `InputStream is = getContentResolver().openInputStream(uri);` and then read from the stream. If you want to use the parcel file descripter you should be able to find code for it. – blackapps Jan 30 '20 at 13:30
  • Thanks for your feedback. I have update the description to be more clear. – Christian Jensen Jan 30 '20 at 19:19
  • You are not reacting to my suggestionl to use an input stream. Why not? It is the solution for your problem. – blackapps Jan 30 '20 at 21:10
  • I'm not sure how I would use that, as your suggestion seems to be relevant on the sending side, and not the receiving side. I tried making your suggestion when sending the file, but as expected it made no difference when receiving the file and trying to read it. When receving the file I only have a Payload and I can do either `filePayload.asFile().asJavaFile()`or `filePayload.asFile().asParcelFileDescriptor()`. I have no `uri`. – Christian Jensen Jan 31 '20 at 07:45
  • On the recreiving side. And you have an uri which you use in openFileDesctiptor(). Use it! – blackapps Jan 31 '20 at 09:57
  • I have no uri available and I only use openFileDescriptor() when sending - as seen in the guide: https://developers.google.com/nearby/connections/android/exchange-data#file – Christian Jensen Jan 31 '20 at 10:50
  • I'm not talking about sending. And your post is about accessing the received file. So where are you talking about? I'm talking about receiving. – blackapps Jan 31 '20 at 12:15
  • I have no uri available when receiving so I can't use openFileDescriptor() when receiving. – Christian Jensen Jan 31 '20 at 12:45
  • Ok. I was confused -probably because you posted so little code-. You have no uri. The only thing you know is that the file is put in the Download foleder. But then i dont understand why you cannot find it using the MediaStore or using ACTION_OPEN_DOCUMENT (to let the user choose the file). – blackapps Jan 31 '20 at 13:31
  • `The file is stored correctly in the Downloads folder as I can see and open it via a file browser app.` Which file browser app? As apps have no acces to the Downloads folder anymore in the classic way. – blackapps Jan 31 '20 at 13:32
  • Please post your code where you query the MediaStore for the file. – blackapps Jan 31 '20 at 13:34
  • `requireActivity().applicationContext.contentResolver.query( MediaStore.Downloads.EXTERNAL_CONTENT_URI, arrayOf(MediaStore.Downloads.DISPLAY_NAME), null, null, null ).use { cursor -> while (cursor.moveToNext()) { //Never enters here :( } }` So I guess my app is not the owner of the files since I cannot see them? This should work without user interaction so ACTION_OPEN_DOCUMENT is not an option. – Christian Jensen Jan 31 '20 at 20:22
  • tons of comments and not even one usefull answer :-( I have at the moment the same problem because of scoped storage in 10 and 11 . The description from google is really bad and buggy and also it seems that google is not interested anymore to update this. Next problem is that filePayload.asFile().asUri(); is not working because asUri() to get the Uri does not exists. So there is no chance to get the uri of the received file – Frank Nov 25 '20 at 16:38
  • I'm facing the same issue now. Did anybody find solution for it? – Prodigy May 13 '21 at 19:46

1 Answers1

1

Nearby connections 18.0.0 has been released. You can now do this -

if (VERSION.SDK_INT >= VERSION_CODES.Q) {
        // Because of https://developer.android.com/preview/privacy/scoped-storage, we are not
        // allowed to access filepaths from another process directly. Instead, we must open the
        // uri using our ContentResolver.
        Uri uri = filePayload.asFile().asUri();
        try {
          // Copy the file to a new location.
          InputStream in = context.getContentResolver().openInputStream(uri);
          copyStream(in, new FileOutputStream(new File(context.getCacheDir(), filename)));
        } catch (IOException e) {
          // Log the error.
        } finally {
          // Delete the original file.
          context.getContentResolver().delete(uri, null, null);
}
Prerak Mann
  • 661
  • 7
  • 15