Skip to content
This repository has been archived by the owner on Apr 1, 2023. It is now read-only.

feat: On Android I can't select files on SD card - I see only Photos and Google drive #60

Closed
ieugen opened this issue Jan 4, 2023 · 7 comments · Fixed by #67
Closed
Assignees
Labels
bug/fix Something isn't working platform: android Android platform

Comments

@ieugen
Copy link

ieugen commented Jan 4, 2023

Is your feature request related to a problem? Please describe:

I would like to be able to pick files (a directory, see capawesome-team/capacitor-plugins#16 )
from my SD card .

Right now I can't see my SD card with the sample code I found on the README.

Is there a way to do that?

This is the code I use:

const pickFiles = async () => {
  const result = await FilePicker.pickFiles();
  const file = result.files[0];

  alert('Selected file is' +
      JSON.stringify(file) +
      ' ' + JSON.stringify(result));
  return result
};

I am getting this in my emulator.
Captură de ecran_2023-01-04_22-40-27

@robingenz
Copy link
Member

Unfortunately, I do not have an Android device with SD card. I guess that the permissions are missing.

Add the following permissions to your AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

(More info here)

Use the @capacitor/filesystem plugin to request the permissions at runtime:

import { Filesystem } from '@capacitor/filesystem';

const pickFiles = async () => {
  // 1. Request permissions
  await Filesystem.requestPermissions();
  // 2. Pick files
  const result = await FilePicker.pickFiles();
  const file = result.files[0];

  alert('Selected file is' +
      JSON.stringify(file) +
      ' ' + JSON.stringify(result));
  return result
};

Please let me know if this helps.

@ieugen
Copy link
Author

ieugen commented Jan 5, 2023

Hi,

I have those permissions set.
I've added this code to a branch and I tried again without success.

(Running inside emulator)

You can find the code and a repro here: https://github.com/ieugen/organice/blob/ddf41a3451784473952e894d53b4b4e17004dee2/src/components/SyncServiceSignIn/index.js#L175 .

For build instructions see https://github.com/ieugen/organice/tree/android-local-fs#native-app-on-android .

I also checked the application permissions and they are present (I got asked for them).

There is also the fact that StorageClient app for https://github.com/android/storage-samples/tree/main/StorageClient .
That app allows me to select a file from every place but does not require any permissions.
I am quite surprised by this.

Captură de ecran_2023-01-05_22-46-13
Captură de ecran_2023-01-05_22-46-31

@ieugen
Copy link
Author

ieugen commented Jan 9, 2023

ok, so I talked with a friend that does Android development and we discovered that the difference is caused by this:

This API is old for Android less then 4.3 https://developer.android.com/guide/topics/providers/document-provider#client

On Android 4.3 and lower, if you want your app to retrieve a file from another app, it must invoke an intent such as ACTION_PICK or ACTION_GET_CONTENT. The user must then select a single app from which to pick a file and the selected app must provide a user interface for the user to browse and pick from the available files.

Should be updated to ACTION_OPEN_DOCUMENT that supports Android > 4.3

On Android 4.4 (API level 19) and higher, you have the additional option of using the ACTION_OPEN_DOCUMENT intent, which displays a system-controlled picker UI controlled that allows the user to browse all files that other apps have made available. From this single UI, the user can pick a file from any of the supported apps.

And an option added to support directories: ACTION_OPEN_DOCUMENT_TREE see capawesome-team/capacitor-plugins#16

On Android 5.0 (API level 21) and higher, you can also use the ACTION_OPEN_DOCUMENT_TREE intent, which allows the user to choose a directory for a client app to access.

List of API's to access storage: https://developer.android.com/training/data-storage .

@ieugen
Copy link
Author

ieugen commented Jan 9, 2023

The Storage Access Framework API does not need extra permissions (as documented).

@robingenz
Copy link
Member

Thanks for your research. I will take a look.

@robingenz
Copy link
Member

robingenz commented Jan 9, 2023

I have had a look at it and think that Intent.ACTION_GET_CONTENT is the right choice for this plugin, because ...

Note: ACTION_OPEN_DOCUMENT is not intended to be a replacement for ACTION_GET_CONTENT. The one you should use depends on the needs of your app:

Use ACTION_GET_CONTENT if you want your app to simply read or import data. With this approach, the app imports a copy of the data, such as an image file.
Use ACTION_OPEN_DOCUMENT if you want your app to have long term, persistent access to documents owned by a document provider. An example would be a photo-editing app that lets users edit images stored in a document provider.

(Source)

However, I was able to find another fix (see #67).
On my Android device I am now able to select files from the entire file system. Unfortunately I do not have an SD card.
Please try this dev build and let me know if it fixes your issue:

npm i @capawesome/[email protected]

@robingenz robingenz added platform: android Android platform bug/fix Something isn't working needs: reply labels Jan 9, 2023
@ieugen
Copy link
Author

ieugen commented Jan 13, 2023

Thanks.
On my side we implemented our own internal plugin since it's much simpler to maintain.
The API surface is quite small for organice and we can have also file picker: 200ok-ch/organice#933

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 11, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug/fix Something isn't working platform: android Android platform
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants