java.lang.IllegalStateException: Not one of standard directories [duplicate] - java

Android Api 29 has big changes regarding files and folders.
I have not found a way so far to create a folder in the internal storage that is public visible.
Every folder I create can be seen by my app only.
I write an app that creates data files that shall be picked up by other apps, for instance the Total Commander to copy them to a destination.
Everything worked fine until I activated Api 29. Some of my clients DO use pixel phones and they use Android 10.
How can I create a folder and files in Android 10 that are public?
This has been deprecated:
Environment.getExternalStorageDirectory();
Environment.getExternalStoragePublicDirectory(type);
and when I use
File root = context.getExternalFilesDir(null);
The created files can only be seen by my app.
How can I achieve the behavior that was valid before Android 10?
Thanks in advance.

when I use File root = context.getExternalFilesDir(null); The created files can only be seen by my app
They can be seen by any app that uses the Storage Access Framework (e.g., ACTION_OPEN_DOCUMENT), if the user chooses the document that you place in that directory.
I write an app that creates data files that shall be picked up by other apps
Other apps have no access to external or removable storage on Android 10, except in the limited directories like getExternalFilesDir() or via non-filesystem means (ACTION_OPEN_DOCUMENT, MediaStore).
How can I create a folder and files in Android 10 that are public?
Use getExternalFilesDir() and related methods on Context. Or, use ACTION_CREATE_DOCUMENT or ACTION_OPEN_DOCUMENT_TREE and use the Storage Access Framework. In either case, the resulting documents can be used by other apps that also use the Storage Access Framework.

Starting from Android 10, you should use SAF, and let user choose the directory using ACTION_OPEN_DOCUMENT_TREE.
If you need a simple example. You can find it here
Alternatively, you could use requestLegacyExternalStorage = true in manifest when your app is not newly released. But, this is something that should not be used for future release, as this is a short-term solution provided by Google.
Note: In future releases of Android, user will not be able to pick the whole external file directory and Downloads directory, so unfortunately, keep in mind that we are not going to have access to these as well! For more information you can click here

Related

Android 11 Storage Access and Java File Library

I have an android application already available on playstore. It is a file transfer app between PC to Android using localhost. I'm using following java function within it:
To create directory/file/show list of files and many other file functions(append, byte read/write etc):
file.mkdir
directory.listFiles();
file.createNewFile()
I had also put
requestLegacyExternalStorage="true"
And it is working fine on android 10 after giving sufficient read/write external storage permission.
But the problem is that these will not work on android 11 as requestLegacyExternalStorage will not work. I have used MANAGE_EXTERNAL_STORAGE and the app works perfect but the problem is that playstore is not allowing it. (Don't know why they rejected the update)
I have also used getExternalFilesDir and it works perfect but don't like data to be in android folder and remove if app is deleted.
I have also tried to use download location and it works but the problem is getExternalStorageDirectory is deprecated:
File file = new File(Environment.getExternalStorageDirectory()+"/"+Environment.DIRECTORY_DOWNLOADS,"FileChat");
So what I wanted to ask how can I manage/use file library for android 11 to read/write/create/delete files and directory. It should not be in android folder as this will be deleted after app is deleted. Can I used public directory like downloads? If I can, what is the alternative to getExternalStorageDirectory()?
I don't need to read user data. Just want to have a directory in which app can store files. The read function is working as file is picked by user using intent.
Thanks in advance.
Top-level directory write access of shared storage is not available in Android 11, however you can use the existing File APIs to access the media and download collection folders like /Pictures, /Downloads, /DICM etc. It won't be possible to create your app's own folder as top level directory but it is possible to create a dedicated sub-directory in the default collection folders.
To keep your app running as expected on Android 10, requestLegacyExternalStorage flag will also be required since access to shared storage on Android 10 was restricted via MediaStore APIs only.
If transfer is only for your apps own files then put them in
File file = new File(Environment.getExternalStoragePublicDirectory(DIRECTORY_DOCUMENTS),"FileChat");
Or use Storage Access Framework to let the user choose and or create a directory on external storage inclusive removable micro sd card.

Is it possible to programmatically access Download folder on Android Q (SDK >= 29)?

I want to list all files .txt in the Download folder and then allow the user to pick one and read its content. My minSdkVersion is 16, but I came across this problem because my Android is Q (29).
What I tried:
Apparently Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) would solve it for SDK <= 29. However, I didn't test it because I would first like to check out a solution for Android Q.
getExternalStoragePublicDirectory says:
When an app targets Build.VERSION_CODES.Q, the path returned from this method is no longer directly accessible to apps. Apps can continue to access content stored on shared/external storage by migrating to alternatives such as Context#getExternalFilesDir(String), MediaStore, or Intent#ACTION_OPEN_DOCUMENT.
So:
getExternalFilesDir returns /storage/emulated/0/Android/data/com.mypackage/files/Download. This path is not useful, I expected it to return /storage/emulated/0/Download, which is where the downloaded files are.
I didn't manage to do something with MediaStore.Downloads. I checked the documentation and it says "In particular, if your app wants to access a file within the MediaStore.Downloads collection that your app didn't create, you must use the Storage Access Framework.". So, I assume it won't work for me.
In my concept, Intent and Storage Access Framework would need the user to navigate through directories and files using a File Manager, which is not what I want here.
In short:
Is it possible to list the .txt downloaded files programmatically in Android Q (SDK >= 29)? If so, how?
Is it possible to list the .txt downloaded files programmatically in Android Q (SDK >= 29)?
Not ones created by other apps, which would appear to be your intention.
The closest is if you use ACTION_OPEN_DOCUMENT_TREE and ask the user to open the Downloads/ tree on external storage... and you cannot do that on Android R (at least through DP1).

how to grant full Write/Read files access on specifics folder in android Q

I noticed that my program on Android Q can not create any folder or save and open a file.
I've read Google's documentation but I did not find the answer or at least I did not understand Because there is a very small sample code, and as I figured out, every time you create a file, you need to open a special window
Someone can tell me how can I get a full access for special folder in sdcard?
I do not want to open a different window every time and confirm it
Long term, you have no means of forcing the user to give you access to a test/ directory on external storage.
You have three main options.
You can use getExternalFilesDir(), getExternalCacheDir(), or getExternalMediaDir(). These are methods on Context, and they each return a File pointing to a directory on external storage for which you have full read-write filesystem access. From the user's standpoint, these will be under Android/data/.../, where ... is your application ID.
Or, you can use ACTION_OPEN_DOCUMENT_TREE and the Storage Access Framework. Using startActivityForResult() with an ACTION_OPEN_DOCUMENT_TREE Intent will give you a Uri that points to a document tree, which may be on external storage, removable storage, or in the cloud. You can call takePersistableUriPermission() on a ContentResolver to get long-term access to that tree, and you can use DocumentFile.fromTreeUri() to work with that tree. However, this is not filesystem access — it is a bit closer to working with a Web server.
Or, you can add android:requestLegacyExternalStorage="true" to your <application> element in the manifest. This will give you legacy filesystem behavior on Android Q devices. This is scheduled to be removed for Android R, so this is not a suitable long-term solution.
I blogged about the Android Q storage changes a lot this year; here is my last(?) post on it.

Android access file system nexus 7

Background
I am developing an android application that will only be used on Nexus 7 tablets (my team is also providing and has access to the hardware).
Problem
The app needs to be flexible to allow content to be added (by non-tech savvy users) to the app and accessed without an internet connection.
Our Idea
Android devices have a file system. We want to design a file system layout such that the people adding content to the application can drag and drop into the correct folder.
e.g.
AppName
Images
Videos
If the user adds a video to the videos folder of the device under our app, it will show up in the app.
We understand that this could easily go wrong (accidentally delete a folder, etc.) but this is out best attempt to solve this without having to update the app ourselves whenever new content comes up (and remember, no internet connection!).
The Question
Is it possible to access the android file system contents and insert them into an app as described in the "Our Idea" section? If so, how?
Yes. This is possible if you don't bother about content security. You can copy the content to any of the file system path in sdcard and your app can look for the folder and read the files .
Example , you can create a folder in sdcard as
sdcard/appname/media/
and create a layout to access the files in the device, and when user selects the files provide option to copy it to your sdcard/appname path.
Check this link
http://developer.android.com/training/basics/data-storage/files.html
Note : the sdcard path can be accessed if you connect to any external system ( PC).

Difference between getExternalFilesDir and getExternalStorageDirectory()

I understand that ExternalFiles is to be used on API 8 and up and getExternalStorageDirectory is for 7 and down. However I am a little confused between the use. For example I wanted to check that a folder that exists and previously you would use something like:
File ChildFolder = new File(Environment.getExternalStorageDirectory() + "/ParentFolder/Child");
However every example I see says to use getExternalFilesDir (null), File.ext. Since I am above API 8 I want to use this method but how do I just check for a folder? I will check for a files existence at another point but for now just want to see if the folders exist??
getExternalFilesDir()
It returns the path to files folder inside Android/data/data/your_package/ on your SD card. It is used to store any required files for your app (e.g. images downloaded from web or cache files). Once the app is uninstalled, any data stored in this folder is gone too.
getExternalStorageDirectory()
It returns the root path to your SD card (e.g mnt/sdcard/). If you save data on this path and uninstall the app, that data won't be lost.
First of all, we need to understand what is difference between Internal Storage, External Storage (aka primary external storage), and Secondary External Storage?
Internal Storage: is storage that is not accessible by the user, except via installed apps (or by rooting their device). Example: data/data/app_packageName
Primary External Storage: In built shared storage which is "accessible by the user by plugging in a USB cable and mounting it as a drive on a host computer". Example: When we say Nexus 5 32 GB.
Secondary External Storage: Removable storage. Example: SD Card.
getExternalFilesDir (String type)
It returns the path to files folder inside Android/data/data/your_package/ on primary external storage. Which is inbuilt storage.
Environment.getExternalStorageDirectory()
It will return the path of the secondary external storage directory
! IMPORTANT UPDATE ! for whoever comes across this question.
As this is a somewhat old question just wanted to provide some additional information. Since KitKat even apps that have WRITE_EXTERNAL_STORAGE permission are only allowed to write to Android/data/data/your_package/ on external storage, a.k.a getExternalFilesDir()
If you will try to write to getExternalStorageDirectory() + "/somefolder/anotherfolder/" you will get a SecurityException on most devices
!! IMPORTANT !!
Environment.getExternalStorageDirectory() is deprecated and Context#getExternalFilesDir(String), MediaStore, or Intent#ACTION_OPEN_DOCUMENT, should be used instead.
This method was deprecated in API level 29.
To improve user privacy, direct access to shared/external storage devices is deprecated. When an app targets Build.VERSION_CODES.Q, the path returned from this method is no longer directly accessible to apps. Apps can continue to access content stored on shared/external storage by migrating to alternatives such as Context#getExternalFilesDir(String), MediaStore, or Intent#ACTION_OPEN_DOCUMENT.
https://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory()
Also beginning from Android.M developers need to ask for permissions at run time.
See more details in documentation here and this question
Environment.getExternalStorageDirectory() deprecated in API level 29 java

Categories