Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] - File.getExternalDir() - create app-specific folder on the shared storage of an Android device #390

Open
Eduplay1 opened this issue Jul 16, 2020 · 15 comments

Comments

@Eduplay1
Copy link

Eduplay1 commented Jul 16, 2020

As you already know, Google's recent storage policy changes and the requirement to target API level 29 by 1 Aug 2020 for new apps and 1 Nov 2020 for updates on existing apps is approaching fast.
The requestLegacyExternalStorage flag in the manifest will buy some time but it is actually just meant to allow developers to migrate to the new scoped storage model and to significantly reduce the number of apps that will be permitted to use the WRITE_EXTERNAL_STORAGE permission in order to have full access to the shared storage on a device.

Since Android 4.4 (Kitkat), apps did not have to include WRITE_EXTERNAL_STORAGE permission when the app only stored files in its own app-specific folder:
Android/data/{app-identifier}/files on the external storage.
But this is only true after the app calls the getExternalFilesDir() function on the native side, which in turn creates the folder for the app and returns the file path.
With Adobe AIR, there is no such function to call in order to create that app-specific folder, they only have File.applicationStorageDirectory but this is not on the shared storage space, but internal.
If one creates the Android/data/{app-identifier}/files folder manually, the Adobe AIR app can write to that folder without the WRITE_EXTERNAL_STORAGE permission in the manifest, but there is no way to call a function through the AIR API to create such an app-specific folder for the app, so this leaves the app only one option and that is to specify WRITE_EXTERNAL_STORAGE. This is where the problem comes in, because at some point, Google will reject your app submission if you specify WRITE_EXTERNAL_STORAGE or it will just be ignored on Android 11

My request is, that you include a new function in your File API which calls the getExternalFilesDir() natively on Android - which will create the folder for the app and return the file path. Very simple but will then eliminate the need to specify WRITE_EXTERNAL_STORAGE in the manifest.

@marchbold
Copy link
Collaborator

This is an easy one to open up via an ANE, and I believe it's already available in our Application ANE if you have access to that.

@Eduplay1
Copy link
Author

Thanks for the quick reply.
From the information I get on https://distriqt.github.io/ANE-Application/u.Device%20Information#paths
I see that getFilesDir() is supported but that will return /data/data/package-id/files
What I am looking for is access to getExternalFilesDir() which creates and returns /storage/sdcard0/Android/data/package-id/files

This is the info on the Application ANE on https://distriqt.github.io:

The functionality also includes some access to some system dependant paths, such as the getFilesDir on Android.

trace( "PATHS ==================================" );
trace( "files dir: " + Application.service.device.getFilesDir() );

Will Application.service.device.getExternalFilesDir() also work? I don't have access to the ANE to test yet

@ajwfrost
Copy link
Collaborator

@Eduplay1 this one is interesting - as we have a range of File.xxxDirectory options (applicationStorageDirectory, documentsDirectory, userDirectory etc) which are primarily there for desktop purposes. On Android from what I can see:

Given that this 'getExternalStorageDirectory()' is deprecated in SDK level 29, probably the best thing to do is to replace this with the getExternalFilesDir() call for any app that is targeting SDK 29.

@teotigraphix
Copy link

teotigraphix commented Jul 16, 2020

I brought this up on Starling forum a year ago and no body seemed to know what I was talking about. :)

So yeah, there is literally no public directories anymore after the legacy flag is enforced. All my apps use the file system and share samples with other apps and such.

https://forum.starling-framework.org/d/21307-android-q-file-system

Not much info just the fact it will break sooner than later. Pointing all past public directories to the files directory seems the only option.

Transitioning to using scoped storage and provider intents to share public files. Google does have a process for vetting apps that need to use that public directory, but you have to pass their "inspection". I will probably try to get a hold of them down the road to do this since my apps have been up for 3+ years and have no insecure actions.

@Eduplay1
Copy link
Author

@ajwfrost If I understand you correctly, you suggest that File.documentsDirectory natively calll getExternalFilesDir() on Android when API 29+ is targeted. I would suggest to rather implement it on File.usersDirectory and still have File.documentsDirectory point to the root external storage directory (for read only purposes) - As far as I can gather, Google will still allow any app full read access to the external storage, it is just write access that will be limited to app-specific folders.

@teotigraphix
Copy link

Google will still allow any app full read access to the external storage,

@Eduplay1 Do you have a quote/document on this? I have spent months researching this and if I can read only, that would be a huge time saver.

I swear they have changed this 10 times in the last 3 years. :)

@Eduplay1
Copy link
Author

@teotigraphix Yes I think many devs are still unaware of the implications the new enforcement will have for all apps on API 29+
You say pointing all past public directories to the files directory seems the only option but what concerns me more is that even if my app can point to the app-specific folder on the external storage /storage/sdcard0/Android/data/package-id/files I need that folder to be created automatically when first calling an API function to return my app-specific folder because if my app has to create that folder, then the app will require WRITE_EXTERNAL_STORAGE permission and that is going to be the problem in the near future due to harsher policy rules.
The reason I cannot use File.applicationStorageDirectory is because I need some of my other apps to be able to have read access to the first app's /storage/sdcard0/Android/data/package-id/files folder

@Eduplay1
Copy link
Author

Android 11-access files
@teotigraphix see the attachment - this is from https://developer.android.com/preview/privacy/storage

@teotigraphix
Copy link

@Eduplay1 Thanks :)

@teotigraphix
Copy link

I need that folder to be created automatically when first calling an API function to return my app-specific folder because if my app has to create that folder, then the app will require WRITE_EXTERNAL_STORAGE permission and that is going to be the problem in the near future due to harsher policy rules.

Ok, I get what you are saying now, chicken egg thing.

@marchbold
Copy link
Collaborator

@Eduplay1 Apologies we have this addition in our beta, but it's not public yet, will be released before the end of the month.

@Eduplay1
Copy link
Author

@marchbold will there be a trial version I can test out once the new release is public?

@marchbold
Copy link
Collaborator

@Eduplay1 We have just released this update. We currently don't have trial versions, however it's a very simple call:

var extPath:String = Application.service.device.getExternalFilesDir();

https://distriqt.github.io/ANE-Application/u.Device%20Information#paths

@Eduplay1
Copy link
Author

@marchbold This is good news! I will be checking it out soon. Thanks for the update sir.

@Eduplay1
Copy link
Author

Eduplay1 commented Aug 5, 2020

@Eduplay1 this one is interesting - as we have a range of File.xxxDirectory options (applicationStorageDirectory, documentsDirectory, userDirectory etc) which are primarily there for desktop purposes. On Android from what I can see:

Given that this 'getExternalStorageDirectory()' is deprecated in SDK level 29, probably the best thing to do is to replace this with the getExternalFilesDir() call for any app that is targeting SDK 29.

@ajwfrost Can you confirm when then above suggestion will be included in the SDK?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants