Android Dev: Accessing external SD card directly o

2019-07-15 05:38发布

问题:

I'm learning Android development so am relatively new to some of the technical Android concepts, but I do have a strong developer background.

I am writing an app that I want to be able to directly access files on the user's SD card. The test device is a Samsung Galaxy Tab 4.

Samsung appears to use a custom method of mounting the SD card, placing it at /storage/extSdCard rather than the more traditional /sdcard.

In my app, I used the method Environment.getExternalStoragePublicDirectory method to request the path for storage, and was given a path which points to the internal storage rather than the SD card. (/storage/sdcard0/...)

When I try to directly access the SD card storage (/storage/extSdCard/...), I get the error open failed: EACCES (Permission denied).

This device - and potentially any user's device - has very limited storage available on the internal memory. (This device has only 8GB of storage internally, most of which is taken up by apps.) Additionally, I want a potential app user to be able to put files onto their MicroSD card directly and not have to use an Android file transfer tool to load content into the app...

Any way I can access the external SD card directly from an app running on a Samsung device?

Test code:

public void doTest()
{
    FileWriter fw;

    File f = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), "test.txt");
    Log.i("file","Trying to write a file at: "+f.getPath());
    try {
        fw = new FileWriter(f);
        fw.write("You got a file.");
        fw.flush();
        fw.close();
        Log.i("file", "Successfully wrote the file.");
    }
    catch (IOException e)
    {
        Log.i("file_error", "Could not write the file.");
        Log.i("file_error",e.getMessage());
    }

    f = new File("/storage/extSdCard/Documents", "test.txt");
    Log.i("file","Trying to write a file at: "+f.getPath());
    try {
        fw = new FileWriter(f);
        fw.write("You got a file.");
        fw.flush();
        fw.close();
        Log.i("file", "Successfully wrote the file.");
    }
    catch (IOException e)
    {
        Log.i("file_error", "Could not write the file.");
        Log.i("file_error",e.getMessage());
    }
}

回答1:

I am writing an app that I want to be able to directly access files on the user's SD card.

That is not possible on Android 4.4+, as most of the direct access to removable storage has been curtailed. Exceptions include pre-installed apps and apps that run on rooted devices and use superuser privileges.

Samsung appears to use a custom method of mounting the SD card, placing it at /storage/extSdCard rather than the more traditional /sdcard.

/sdcard has not been used for removable media since Android 2.x, on most devices.

In my app, I used the method Environment.getExternalStoragePublicDirectory method to request the path for storage, and was given a path which points to the internal storage rather than the SD card. (/storage/sdcard0/...)

No, getExternalStoragePublicDirectory() points to external storage. External storage is not removable storage. Internal storage is something else entirely.

Any way I can access the external SD card directly from an app running on a Samsung device?

You are welcome to use the getExternalFilesDirs(), getExternalCacheDirs(), and getExternalMediaDirs() methods on Context. Note the plural method names. If those methods return 2+ entries, the second and subsequent ones are locations on removable storage that you can read from and write to, no permissions required. However, you cannot access all of removable storage this way, just a location specific for your app.

You are also welcome to use the Storage Access Framework, allowing the user to pick where the content goes, including placing it on removable storage. However, you are no longer working with files and paths, but with content and Uri values.

The N Developer Preview offers another option for "Scoped Directory Access", which supports removable storage. However, this is still part of a developer preview at the present time (March 2016).