HOWTO: Get Application Specific Directory -ASD (where one exists) without Extensions

Could you explain how this is supposed to work on a pre Android 10 device?

I compiled and installed your aia on an Android 7 device, and pressing the "false" button returned a string of a file path (which is really all the blocks do, they do not go and find a file path):

/storage/emulated/0/Android/data/appinventor.ai_bodymindpower.getASD/files

This file path does not exist, when inspecting with a File Manager (all other apps installed do show their "ASD" if they were given one). How is a user/developer meant to then use this string ? With your blocks how is the directory actually created ?

It is no problem to create the ASD on devices with API < 29 (there are numerous extensions that do that, I made 3 extensions myself that can do it). In addition, the ASD can of course also be created with the Canvas component (but then incorrectly only with WRITE permission).

Whether the ASD exists was / is not the subject of this topic, but only how to get the ASD.

We should end this discussion.
Do what @Taifun suggested. I will then post my solution in a separate topic.

You therefore have to use an extension to create this directory that doesn't exist? Crazy. And defeats the whole object of the exercise!

But this is precisely my point, my blocks do "GET" the ASD if there is one, if there isn't one they fall back to the previous position of the root of the sdcard in pre 10 versions.

:slight_smile:

@TIMAI2 You obviously don't want to understand.
In addition, you confuse the others more and more.
(although it's actually pretty simple)

Sorry for going off-topic :confused: :disappointed:

and even a little bit more... :wink:

Taifun

Of course, that was because I first wanted to output the packageName and then the ASD
(in my first approach; therefore I left it that way).

Hi Anke.
I'm trying that files remain in the same folder for all Android versions.
I think I heard you say that /storage/emulated/0 exists in all devices and Android versions.
That would be great if I could download files there from FireBase Storage.
Do you know how should I "set Web1 .ResponseFileName to" before "call Web1 .Get"?
HowToSendDownloadedFileTo_storage_emulated_0

A quick answer. Right now your approach will work. Once App Inventor starts targeting Android SDK 30 (July/August), then you will not be able to save to the sdcard location.

See this discussion:

for more details....

store your files in the ASD - Application Specific Directory, which will work for all Android versions and also later after targeting SDK 30...
this is what this thread is about...

Taifun


Trying to push the limits! Snippets, Tutorials and Extensions from Pura Vida Apps by icon24 Taifun.

If AI2 targets API 30 (Android 11) → Aug 2021, you will need to request a new permission: MANAGE_EXTERNAL_STORAGE.
WRITE_EXTERNAL_STORAGE is no longer available under Android 11.

So if the app is targeting Android 11 (targetSdkVersion = 30) and you need full access to the external storage then you have to declare the following permissions in the Manifest:

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

However, MANAGE_EXTERNAL_STORAGE, which grants general access to the external storage, must first be approved by Google and is only granted for special apps whose core use case require access to the external storage. → https://medium.com/androiddevelopers/android-11-storage-faq-78cefea52b7c

So I advise you to proceed as @Taifun suggested:

1 Like

What about applications that are distributed outside the play store?

Thanks a lot, Taifun.
I'll follow your recommendation to stick to the "ASD rule".

In my app, during the process of registering a user, the app commands the device's camera to take a selfie.
In fact, I don't mind where the selfie files are, as far as the app can retrieve them to show them to the user, and the user can't delete them.

In former Android versions, the image files stayed in the gallery, where the user could delete them. (This no longer happens in Android>=10, because now such a selfie file automatically goes to <SD (device dependent)><ASD (app dependent)>/Pictures.)

To keep the selfies safe in former Android versions, the app was using TaifunFile extension (thanks a lot) to make a copy of the selfie file in some "similar to ASD" path, and then the app uses this copy instead of using the original selfie (which might not be there if the user deleted the image from gallery).

The app also makes a second copy of the selfies on Firebase Storage.
The reason is, if the user changes to a new device, they can install the app and, at first start whithout user data, they are prompted to choose between registering (for new users), or (it they changed mobile) to retrieve from the cloud their profile data, including the selfie image file.

Its clear for me that the CopyAsync method of your extension requires to indicate the full path ("SD","RelativePath",/FileName), both for origin and destination files.
For this is helpful the ApplicationSpecificDirectory block of your extension (thanks again), because it provides the full path and, if required, you can easily split it in "SD" and "ASD", just looking for where the "/Android" piece starts on text.

What confuses me is:
How can I target ASD in Android versions >=10?
I need to do it in two circumstances:

1.- At download.
How can I target ASD at the block "set Web1 .ResponseFileName to" (before calling Web1 .Get)? .
It's hard to kow by testing, because FileManager now tells you there is nothing under /Android/data.
Should I indicate a full path to the intended destination file (or telling just the destination file name, the file will it go directly to "ASD")?
In case the file name suffice, should it start with a slash "/", several slashes, or none?

2.- When showing to the user the copy of the selfie (or the selfie downloaded from the cloud) in "ASD" with blocks such as "set Image1 .Picture", or "set ListPicker .Image".
Should I still indicate a full path to the file?
Or it's different in the new Android versions, and I should indicate a path relative to "SD", or just the file name (with or without initial "/")?

Your expert advice will be very appreciated.

Thanks Anke and Tim
Then, it looks better to stick to the ASD rule, and let Android manage the file destinations as much as possible, to avoid the need to request additional permissions.
Let's test it again in September!

Of course, the user can delete any file on his device from the external storage (also from the ASD). See e.g. here. The only files that the user cannot access without rooting the device are the assets.

I meant, before it was too simple for the mobile owner to delete by mistake any selfie from the gallery (because both photos taken by them, and photos ordered by my app stayed in the same gallery folder).
I don't think it's so easy in new Android versions.
Because photos ordered by my app will go to "SD","ASD",/Pictures. So they are no longer visible for the user from Gallery app. And also FileManager app now tells you there is nothing under "SD",/Android/data

Yes, but there are many file managers (e.g. Total Commander, ...) with which it is no problem to delete these files as well. And many users (including me) use them.

Nothing is impossible for a Power User like you :wink:

There shouldn't be any problems.