So I am aware that there is SD Card access API which allows us to write files via DocumentProvider and DocumentFiles. I have made it work on removable SD Cards. I was always confused about External and Internal Storage. I always thought External Storage is Always SD card but today I came to know that it is not so.
So I have three question .
Question1 , how to know if Files are stored in external emulated storage or sdcard ?
One solution maybe by searching for instances of "sdcard0" or "emulated" in the file path.
Will this solution always work? I mean on all phones?
Question 2 what to Use for writing files on emulated storage(non removable external storage) normal files or DocumentFile?
Question 3 If solution of Q2 is Document File then why doesn't this work ?
private static String[] getExtSdCardPaths() {
List paths = new ArrayList<>();
for (File file : GlobalSongList.GetInstance().getApplicationContext().getExternalFilesDirs("external")) {
if (file != null && !file.equals(GlobalSongList.GetInstance().getApplicationContext().getExternalFilesDir("external"))) {
int index = file.getAbsolutePath().lastIndexOf("/Android/data");
if (index < 0) {
Log.w("StorageAccessAPI", "Unexpected external file dir: " + file.getAbsolutePath());
}
else {
String path = file.getAbsolutePath().substring(0, index);
try {
path = new File(path).getCanonicalPath();
}
catch (IOException e) {
// Keep non-canonical path.
}
paths.add(path);
}
}
}
return paths.toArray(new String[paths.size()]);
}
So I am aware that there is SD Card access API which allows us to write files via DocumentProvider and DocumentFiles.
You are referring to the Storage Access Framework. This allows you to read and write streams, not files, where the streams are backed by document providers. The user chooses what document provider to use, which in turn determines where the stream's content is stored. That could be local (e.g., external storage, removable storage) or remote (Google Drive, Dropbox, Samba file server, Web server, FTP server, SFTP server, etc.).
how to know if Files are stored in external emulated storage or sdcard ?
If you are using the Storage Access Framework, you do not know where the stream's content is stored.
what to Use for writing files on emulated storage(non removable external storage) normal files or DocumentFile?
If you explicitly want to use external storage, use external storage.
Using the Storage Access Framework allows the user to choose where the stream's content is stored, which may or may not be external storage.
why doesn't this work ?
I have no idea what you expect that to do. I expect it to return a series of useless strings.
Related
I have created an android app that gets input from user through EditText and writes them to name.txt file in phone's internal storage. Is it possible to open the text file in phone's file manager? I tried to get the file path using getFilesDir().getAbsolutePath()+"/"+FILE_NAME. But couldn't locate the file in file manager.
You need to use External storage if you want another app like File Manager to access the file. Internal storage is only readable by your app.
In the comments you ask a valid question - "What if the phone doesnt have external storage...?". That is not really a concern today. See https://developer.android.com/training/data-storage/files:
Many devices now divide the permanent storage space into separate
"internal" and "external" partitions. So even without a removable
storage medium, these two storage spaces always exist...
==========
So change your above code to this:
getExternalFilesDir().getAbsolutePath()+"/"+FILE_NAME
getExternalFilesDir is a method from the android.content.Context class. So this call will work from your activity class which is a Context.
=============
Further supporting the choice of external storage is the following, also from https://developer.android.com/training/data-storage/files.
Internal storage is best when you want to be sure that neither the
user nor other apps can access your files.
External storage is the best place for files that don't require access
restrictions and for files that you want to share with other apps or
allow the user to access with a computer.
there is private storage for each app that can be accessed from the app itself and then public storage /sdcard/... that other app can access too (it needs to get Storage Permission from system)
this method will save a content in a file in private storage of app
public void saveFile(String fileName, String content) {
try {
FileOutputStream fOut = context.openFileOutput(fileName, Context.MODE_PRIVATE);
fOut.write((content).getBytes());
fOut.flush();
fOut.close();
} catch (Exception e) {
e.printStackTrace();
}
}
I have some paths on sd card on Android 7, which are unwritable using instant access requiring, so I have to use StorageVolume.createAccessIntent and therefore use DocumentFile later instead of File. But the problem is that I need to use File, because db lib(realm), that I'm using, simply uses File object to store data. So the point is that I have to createDirectory and this directory(it's path) has to have writing access. How to do this using DocumentFile.createDirectory() or something like that?
So the point is that I have to createDirectory and this directory(it's path) has to have writing access
That is not supported.
The only direct filesystem access that you have to removable storage is via getExternalFilesDirs(), getExternalCacheDirs(), and getExternalMediaDirs() (all methods on Context). If these return 2+ items, the second and subsequent ones are locations on removable storage that are unique to your app and which you can read/write using classic File objects.
Otherwise, keep your Realm database on external storage, then copy it to removable storage at some appropriate point (e.g., user-initiated "export" or "backup" operation).
A simple question. By default android doesn't allow 3rd party apps to write to removable sd card.
But in Android 5.0 I can request for permission to write to removable sdcard and write any file in that directory.
So how to do that? I need an output stream to write to the file.
I can request for permission to write to external sdcard and write any file in that directory.
Not really.
On Android 4.4+, you can use getExternalFilesDirs(), getExternalCacheDirs(), and getExternalMediaDirs(). If those return 2+ items, the second and subsequent ones will be locations on removable storage.
On Android 5.0+, you can use ACTION_OPEN_DOCUMENT_TREE, to ask the user to grant you access to a document tree. That could be the root of removable storage... or anything else the user wants to use. This gives you a Uri back, which you can use with DocumentFile and the rest of the Storage Access Framework. It does not give you filesystem access (e.g., via File).
On Android 7.0+, you can use StorageManager and StorageVolume to ask for access to a removable storage volume. Once again, though, you get a Uri back to use with DocumentFile, ContentResolver, etc -- you do not get filesystem access.
As described in the documentation, internal storage files are private to application.
But, is there any way just to access list of for ex. cache directory files of another app?
Context context = createPackageContext(packageNameOfAnotherApp, 0);
File directory = context.getCacheDir();
directory.listFiles(); // this will return null, as do list()
No, for security reasons obviously.
You can only access data of other apps it they have written it to a publicly readable directory, or using a ContentProvider.
Unless device is rooted and your application has elevated privileges you cannot access private data of other applications directly.
I want to store data on external storage and Environment.getExternalStorageDirectory() returns /storage/emulated/0/
path and and when i store data on that directory it store data on storage/sdcard0/... and on /storage/emulated/0/
I need to store a great numbers of images on external storage
How could i implement that?How could i get path on external storage?
How could I get path on external storage?
/storage/emulated/0/ and storage/sdcard0/ is basically the same, this is just an alias. On devices like the Nexus 5 and any other device that doesn't have a physical SD card, "external storage" means the device built-in storage which emulates an SD card. Environment.getExternalStorageDirectory() will point to this location so you are good to go using this method.
From the docs:
Note: don't be confused by the word "external" here. This directory
can better be thought as media/shared storage. It is a filesystem that
can hold a relatively large amount of data and that is shared across
all applications (does not enforce permissions). Traditionally this is
an SD card, but it may also be implemented as built-in storage in a
device that is distinct from the protected internal storage and can be
mounted as a filesystem on a computer.
First of all find of path of external storage
String path = Environment.getExternalStorageDirectory().toString() + directoryName;
then you can write whatever content you want to the file as follows:
File file = new File(path, fileName);
BufferedWriter br;
try {
br = new BufferedWriter(new FileWriter(file));
br.write(content);
br.close();
} catch (IOException e) {
e.printStackTrace();
}