Home » Android » android – How do I let a user upload files to internal storage?

android – How do I let a user upload files to internal storage?

Posted by: admin May 14, 2020 Leave a comment

Questions:

I am writing a small app that reads files that must be regularly written to storage on the device from a source external to the device, be it USB, Bluetooth, Airdroid, etc. From what I’ve read, nothing like that can write to internal storage. I would like to manage the files in internal storage for access privacy.

My first solution is an activity that lets the user write files to external storage, and then tap a button to transfer them to internal storage. If this doesn’t happen in n minutes, the files on external storage are destroyed. But, I a have since found out that getExternalStorageDirectory is pretty useless, because devices emulate external storage on internal storage, and Android can’t know if and how this is done.

Yet I was wondering if there wasn’t some sort of built-in activity that lets users upload or download files directly from internal storage, but without free access to the whole file structure of internal storage, like they have with internal storage.

As a last resort, maybe my app can receive the files over a TCP connection and write them to internal storage itself. It’s messy, but so is trying to find an SD card. See the question Find an external SD card location.

NEW: The aim of this exercise is to find all .csv files in a directory on the SD card, let the user choose one, process it, and write an output file to the SD card. The user will enter a “Weight” value that will be used in the calculations for processing the file.

But, since Android is so unreliable at providing the location of really external storage, i.e. the SD card, I want to try and store the files in internal storage, where Android seems to be more honest and reliable about the location of that storage.

How to&Answers:

TLDR: getExternalStorageDirectory() and getExternalFilesDirs()[0] (API 19+) should return “primary” storage location, i.e, internal storage.

EDIT: if you just want to write to eMMC and don’t care about it being private, just use getFilesDir() and its guaranteed you’re writing to eMMC.


Explanation:

To avoid obscurities and for convenience, I will use the following terms

  1. PrivateStorage: App’s Private Storage in internal memory – /data/data/package name
  2. eMMC: Phone’s internal storage
  3. SD: Phone’s expandable storage (removable)

If I understood your question right, you don’t want to write to PrivateStorage which would NOT allow other apps to access that data. So the objective is to write to eMMC and to be more specific, publicly accessible eMMC and not in eMMCs app’s private space.

According to Android Docs (API 1),

Environment.getExternalStorageDirectory() returns the primary external storage directory. This directory may not currently be accessible if it has been mounted by the user on their computer, has been removed from the device, or some other problem has happened. You can determine its current state with getExternalStorageState().

And according to API 19 docs,

You can now read and write app-specific files on secondary external storage media, such as when a device provides both emulated storage and an SD card. The new method getExternalFilesDirs() works the same as the existing getExternalFilesDir() method except it returns an array of File objects.The first entry in the returned File array is considered the device’s “primary” external storage, which is the same as the File returned by existing methods such as getExternalFilesDir().

Summing up, both getExternalStorageDirectory() and getExternalFilesDirs()[0] should return “primary” storage location, which is eMMC. however in practice you can notice that what it returned might not necessarily be eMMC, for a few phones (KarbonnTitiniumS2, XoloX3000 and many other phones)

Here are some snapshots to second that sentence: This phone TitaniumS2 was running 4.2 so I couldn’t use getExternalFilesDirs()

enter image description here
enter image description here

You can also notice that, for the same reason, ES Explorer has wrongly identified /sdcard0 as internal storage (eMMC) and /sdcard1 as external storage (SD) in both old and new versions and indeed continue to tell users that sdcard0 as internal storage.

Also, an issue for finding non-primary (SD) storage, was raised.

It seems there is no API function for finding non-primary external storage devices and google has no intention of fixing the situation, leaving applications to use hacky workarounds like parsing all currently mounted filesystems. It’s pretty terrible for a current-gen OS to not properly support something as basic as accessing files on an inserted USB stick.

Answer:

Hope this help …

you are able to get the file that user wants to upload, and can read the data … then you want to write them to your Applications path …

Correct me if I’m wrong…

here is how you can try to write file to your application’s path… mine one is /data/data/com.test.internalstorage/files

try {
    File filesDir = getApplicationContext().getFilesDir();
    Log.d(TAG, "  Files -> 1 context.getFilesDir()-=> " + filesDir);
    Log.d(TAG, "  Files -> 1 context.getFilesDir().getName-=> " + filesDir.get-name());
    Log.d(TAG, "  Files -> 1 context.getFilesDir().getAbsolutePath-=> " + filesDir.getAbsolutePath());
    Log.d(TAG, "  Files -> 1 context.getFilesDir().getCanonicalPath-=> " + filesDir.getCanonicalPath());
    Log.d(TAG, "  Files -> 1 context.getFilesDir().getPath-=> " + filesDir.getPath());
    String[] lst = getApplicationContext().getFilesDir().list();
    for (int i=0; i< lst.length; i++){
        Log.d(TAG, "  Files -> 1 context.getFilesDir()list("+i+")-=> " + lst[i]);
    }
    String FILENAME = "hello_file5";
    String string = "hello world!";

    FileOutputStream fos = null;

    fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
    fos.write(string.getBytes());
    fos.close();


    Log.d(TAG, "  Files ");"
    File nw_filesDir = getApplicationContext().getFilesDir();
    Log.d(TAG, "  Files -> 2 context.getFilesDir()-=> " + nw_filesDir);
    String[] nw_lst = getApplicationContext().getFilesDir().list();
    for (int i=0; i< nw_lst.length; i++){
        Log.d(TAG, "  Files -> 2 context.getFilesDir()list("+i+")-=>  " + nw_lst[i] +
                " -> " + new File(nw_filesDir,nw_lst[i]).getParentFile());
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

output is

D/_TAG_:   Files -> 1 context.getFilesDir()-=> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 1 context.getFilesDir().getName-=> files
D/_TAG_:   Files -> 1 context.getFilesDir().getAbsolutePath-=> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 1 context.getFilesDir().getCanonicalPath-=> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 1 context.getFilesDir().getPath-=> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 1 context.getFilesDir()list(0)-=> hello_file
D/_TAG_:   Files -> 1 context.getFilesDir()list(1)-=> hello_file2
D/_TAG_:   Files -> 1 context.getFilesDir()list(2)-=> hello_file3
D/_TAG_:   Files -> 1 context.getFilesDir()list(3)-=> hello_file4
D/_TAG_:   Files 
D/_TAG_:   Files -> 2 context.getFilesDir()-=> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 2 context.getFilesDir()list(0)-=>  hello_file -> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 2 context.getFilesDir()list(1)-=>  hello_file2 -> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 2 context.getFilesDir()list(2)-=>  hello_file3 -> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 2 context.getFilesDir()list(3)-=>  hello_file4 -> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 2 context.getFilesDir()list(4)-=>  hello_file5 -> /data/data/com.test.internalstorage/files

Corrections and Suggestions are welcomed !!!