How can I let users access the internal storage directory of my app? How can I let users access the internal storage directory of my app? android android

How can I let users access the internal storage directory of my app?


I took a closer look at the result of getFilesDir() vs getExternalFilesDir() and found that getFilesDir() returns /data/data/[packagename]/files while getExternalFilesDir() returns /Android/data/[packagename]/files. I thought the app files I was browsing in /Android/data were the internal storage directories, but now I see that those are actually the external storage directories.

If the internal storage directories are indeed never available to regular users, I wish the documentation said that instead of saying they are not available "by default." To me at least, saying "by default" implies that the default behavior can be changed.

Anyway, I tested and confirmed that if I delete my app, files saved to the getExternalFilesDir() are deleted automatically. So that meets my need for a storage location that is clearly connected with the app (uses an app-specific directory name and is deleted with the app) but is accessible to users for occasional manual file management.

Here's a comparison that might be helpful to someone else reading this:

  • getFilesDir() - creates an app-specific directory; hidden from users; deleted with the app
  • getExternalFilesDir() - creates an app-specific directory; accessible to users; deleted with the app
  • getExternalStoragePublicDirectory() - uses a shared directory (e.g., Music); accessible to users; remains when the app is deleted


I think you are getting confused by the developers documentation, I can't blame you, it's not the best documentation I've ever read. Anyway, Android provides two ways of saving files to the file system:

  1. Using the Internal Storage
  2. Using the External Storage

The Internal Storage is ALWAYS available and is ONLY accessible to your app, no other app in the system can access the files your app saved to this partition.

Now, I think what you need is the External Storage because it is "world-readable" and can be accessed by anyone and any any apps. The downside is that it may not be available since the user could mount it on a USB device - which can be removed by the user at anytime.

You shouldn't use neither MODE_WORLD_WRITEABLE nor MODE_WORLD_READABLE as per the documentation states, because it is very dangerous. Furthermore, these constants have been deprecated since API Level 17

Recommendation

If you need to make your files public, then save them to the External Storage. You will need to declare a permission in your manifest file to avoid your app from crashing everytime it access the External Storage...

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

because the External Storage might not be available you will need to determine the state of it before you perform any operation, otherwise your app will crash...

public enum StorageState{  NOT_AVAILABLE, WRITEABLE, READ_ONLY}public StorageState getExternalStorageState() {    StorageState result = StorageState.NOT_AVAILABLE;    String state = Environment.getExternalStorageState();    if (Environment.MEDIA_MOUNTED.equals(state)) {        return StorageState.WRITEABLE;    }    else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {        return StorageState.READ_ONLY;    }    return result;}

There is more information on the documentation and things that you should be aware of. For example, you can give your app ownership of these files so that when your app is uninstalled the system can automatically delete these files. For more info please refer to the documentation on the Android Developers Site


add this to manifest

then add this in your activity:

private static final String RequieredPermission = Manifest.permission.READ_EXTERNAL_STORAGE;

then call HandlePermission() where your require to check for permission, usually in Oncreate method of an activity. These functions are then required:

@Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        Log.d("amir", "onRequestPermissionsResult: called");        switch (requestCode) {            case REQUEST_PERMISSION_READING_STATE:                if (grantResults.length > 0                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {                    Toast.makeText(MainActivity.this, "Permission Granted!", Toast.LENGTH_SHORT).show();                } else {                    Toast.makeText(MainActivity.this, "Permission Denied!", Toast.LENGTH_SHORT).show();                }        }    }    private void HandlePermission() {        int permissionCheck = ContextCompat.checkSelfPermission(                this, RequieredPermission);        if (permissionCheck != PackageManager.PERMISSION_GRANTED) {            if (ActivityCompat.shouldShowRequestPermissionRationale(this,                    RequieredPermission)) {                showExplanationaboutPermission("Permission Needed", "Rationale", RequieredPermission, REQUEST_PERMISSION_READING_STATE);            } else {                requestPermission(RequieredPermission, REQUEST_PERMISSION_READING_STATE);            }        } else {            Toast.makeText(MainActivity.this, "Permission (already) Granted!", Toast.LENGTH_SHORT).show();        }    }    private void showExplanationaboutPermission(String title,                                                String message,                                                final String permission,                                                final int permissionRequestCode) {        AlertDialog.Builder builder = new AlertDialog.Builder(this);        builder.setTitle(title)                .setMessage(message)                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {                    public void onClick(DialogInterface dialog, int id) {                        requestPermission(permission, permissionRequestCode);                    }                });        builder.create().show();    }    private void requestPermission(String permissionName, int permissionRequestCode) {        ActivityCompat.requestPermissions(this,                new String[]{permissionName}, permissionRequestCode);    }