问题
I am trying to provide a functionality in my app that the media or storage files used in my application can be moved to SD card by the user.
I am trying to use the code as described in below link
http://www.java-samples.com/showtutorial.php?tutorialid=1523
But I get a permission exception. When I searched for getting that permission, I see that I have to root the device. I don't want to root my device, as it is illegal, no? Is there any android device model that comes rooted from the beginning itself from the manufacturer?
Earlier also I used to see a "Move To SD Card" option in the app settings, but I don't see that option any more. I also saw that most of the file browser applications installed in my device are unable to create a folder on the SD card,
Please share some light on what's the best recommended way to implement this feature. We are supporting android 4.4 to 8.0
回答1:
Yes writing to the sd card is blocked in modern Android versions.
Mostly you have read acces to the whole sd card.
Writing only to one app specific directory which if you are lucky is available in the second item returned by getExternalFilesDirs()
.
If you want to write to the whole sd card then use the Storage Access Framework.
For instance Intent.ACTION_OPEN_DOCUMENT_TREE.
回答2:
If you haven't done so already, you will need to give your app the correct permission to write to the SD Card by adding the line below to your Manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Getting runtime permissions
You should be checking if the user has granted permission of external storage by using:
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.v(TAG,"Permission is granted");
//File write logic here
return true;
}
If not, you need to ask the user to grant your app a permission:
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
Of course these are for marshmallow devices only so you need to check if your app is running on Marshmallow:
if (Build.VERSION.SDK_INT >= 23) {
//do your check here
}
Be also sure that your activity implements OnRequestPermissionResult
The entire permission looks like this:
public boolean isStoragePermissionGranted() {
if (Build.VERSION.SDK_INT >= 23) {
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
Log.v(TAG,"Permission is granted");
return true;
} else {
Log.v(TAG,"Permission is revoked");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
return false;
}
}
else { //permission is automatically granted on sdk<23 upon installation
Log.v(TAG,"Permission is granted");
return true;
}
}
Permission result callback:
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(grantResults[0]== PackageManager.PERMISSION_GRANTED){
Log.v(TAG,"Permission: "+permissions[0]+ "was "+grantResults[0]);
//resume tasks needing this permission
}
}
Also
SD Card directory is /sdcard but you shouldn't be hard coding it. Instead, make a call to Environment.getExternalStorageDirectory() to get the directory:
File sdDir = Environment.getExternalStorageDirectory();
Code to write into external storage
Source
/** Method to check whether external media available and writable. This is adapted from
http://developer.android.com/guide/topics/data/data-storage.html#filesExternal */
private void checkExternalMedia(){
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// Can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// Can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// Can't read or write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
}
/** Method to write ascii text characters to file on SD card. Note that you must add a
WRITE_EXTERNAL_STORAGE permission to the manifest file or this method will throw
a FileNotFound Exception because you won't have write permission. */
private void writeToSDFile(){
// Find the root of the external storage.
// See http://developer.android.com/guide/topics/data/data- storage.html#filesExternal
File root = android.os.Environment.getExternalStorageDirectory();
// See http://stackoverflow.com/questions/3551821/android-write-to-sd-card-folder
File dir = new File (root.getAbsolutePath() + "/download");
dir.mkdirs();
File file = new File(dir, "myData.txt");
try {
FileOutputStream f = new FileOutputStream(file);
PrintWriter pw = new PrintWriter(f);
pw.println("Hi , How are you");
pw.println("Hello");
pw.flush();
pw.close();
f.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.i(TAG, "******* File not found. Did you" +
" add a WRITE_EXTERNAL_STORAGE permission to the manifest?");
} catch (IOException e) {
e.printStackTrace();
}
}
/** Method to read in a text file placed in the res/raw directory of the application. The
method reads in all lines of the file sequentially. */
private void readRaw(){
InputStream is = this.getResources().openRawResource(R.raw.textfile);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr, 8192); // 2nd arg is buffer size
// More efficient (less readable) implementation of above is the composite expression
/*BufferedReader br = new BufferedReader(new InputStreamReader(
this.getResources().openRawResource(R.raw.textfile)), 8192);*/
try {
String test;
while (true){
test = br.readLine();
// readLine() returns null if no more lines in the file
if(test == null) break;
}
isr.close();
is.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
In addition to that
Shared storage may not always be available, since removable media can be ejected by the user.
- Media state can be checked using getExternalStorageState(File).
- There is no security enforced with these files.
来源:https://stackoverflow.com/questions/49790057/has-sd-card-writing-been-blocked