SD 卡写入是否被阻止?

Has SD card writing been blocked?

我正在尝试在我的应用程序中提供一项功能,即用户可以将我的应用程序中使用的媒体或存储文件移动到 SD 卡。

我正在尝试使用下面描述的代码 link

http://www.java-samples.com/showtutorial.php?tutorialid=1523

但是我得到了权限异常。当我搜索获得该权限时,我发现我必须对设备进行 root 操作。我不想对我的设备进行 root,因为这是非法的,不是吗?是否有任何 android 设备型号从一开始就从制造商那里获得了根基?

之前我也曾在应用程序设置中看到一个 "Move To SD Card" 选项,但我再也看不到该选项了。我还看到我设备中安装的大多数文件浏览器应用程序都无法在 SD 卡上创建文件夹,

请分享一些关于实现此功能的最佳推荐方法的信息。我们支持 android 4.4 到 8.0

如果您还没有这样做,您需要通过将以下行添加到您的清单来为您的应用授予写入 SD 卡的正确权限:

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

Getting runtime permissions

您应该使用以下方式检查用户是否已授予外部存储权限:

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
 }

还要确保您的 activity 实现了 OnRequestPermissionResult

整个权限如下所示:

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;
    }
}

权限结果回调:

@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 卡目录是 /sdcard 但您不应该对其进行硬编码。相反,调用 Environment.getExternalStorageDirectory() 获取目录:

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 

    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();
    }

}
}

除此之外

共享存储可能并不总是可用,因为可移动媒体可能会被用户弹出。

是的,写入 SD 卡在现代 Android 版本中被阻止。

大部分情况下你已经读取了整个sd卡的权限。

仅写入一个应用程序特定目录,如果幸运的话,在 getExternalFilesDirs() 返回的第二项中可用。

如果要写入整个 SD 卡,请使用存储访问框架。

例如Intent.ACTION_OPEN_DOCUMENT_TREE.