8

在外部 SD 卡中写入文件时,我收到错误 EACCESS 权限被拒绝。我已经设置了权限 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 但是当我读取文件时,我可以成功读取它但无法写入文件。我用于在 SD 卡中写入文件的代码是:

String path="mnt/extsd/Test";

                try{
                    File myFile = new File(path, "Hello.txt");              //device.txt
                    myFile.createNewFile();
                    FileOutputStream fOut = new FileOutputStream(myFile);

                    OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
                    myOutWriter.append(txtData.getText());
                    myOutWriter.close();
                    fOut.close();
                    Toast.makeText(getBaseContext(),"Done writing SD "+myFile.getPath(),Toast.LENGTH_SHORT).show();
                } catch (Exception e) {
                    Toast.makeText(getBaseContext(), e.getMessage(),Toast.LENGTH_SHORT).show();
                    System.out.println("Hello"+e.getMessage());
                }
            }

外部存储卡的路径是mnt/extsd/。这就是为什么我无法使用Environment.getExternalStorageDirectory().getAbsolutePath()给我一条路径的mnt/sdcard原因,而这条路径是我平板电脑中的内部存储路径。请提出为什么会这样,我该如何解决

4

4 回答 4

17

我记得自 Honeycomb 以来,Android 获得了部分多存储支持,并且主存储(您从 Environment.getExternalStorageDirectory 获得的,通常是内部 eMMC 卡的一部分)仍受权限保护WRITE_EXTERNAL_STORAGE,但辅助存储(如真正的可移动SD卡)受新权限android.permission.WRITE_MEDIA_STORAGE保护,保护级别为signatureOrSystem,另见本文讨论。

如果是这种情况,那么普通应用程序似乎不可能在没有平台签名的情况下将任何内容写入真实的 SD 卡......

于 2012-10-12T07:05:42.667 回答
7

从 API 级别 19 开始,Google 添加了 API

  • Context.getExternalFilesDirs()
  • Context.getExternalCacheDirs()
  • Context.getObbDirs()

不允许应用程序写入辅助外部存储设备,除非在合成权限允许的特定包目录中。以这种方式限制写入可确保系统可以在卸载应用程序时清理文件。

以下是使用绝对路径在外部 SD 卡上获取应用程序特定目录的方法。

Context _context = this.getApplicationContext();

File fileList2[] = _context.getExternalFilesDirs(Environment.DIRECTORY_DOWNLOADS);

if(fileList2.length == 1) {
    Log.d(TAG, "external device is not mounted.");
    return;
} else {
    Log.d(TAG, "external device is mounted.");
    File extFile = fileList2[1];
    String absPath = extFile.getAbsolutePath(); 
    Log.d(TAG, "external device download : "+absPath);
    appPath = absPath.split("Download")[0];
    Log.d(TAG, "external device app path: "+appPath);

    File file = new File(appPath, "DemoFile.png");

    try {
        // Very simple code to copy a picture from the application's
        // resource into the external file.  Note that this code does
        // no error checking, and assumes the picture is small (does not
        // try to copy it in chunks).  Note that if external storage is
        // not currently mounted this will silently fail.
        InputStream is = getResources().openRawResource(R.drawable.ic_launcher);
        Log.d(TAG, "file bytes : "+is.available());

        OutputStream os = new FileOutputStream(file);
        byte[] data = new byte[is.available()];
        is.read(data);
        os.write(data);
        is.close();
        os.close();
    } catch (IOException e) {
        // Unable to create file, likely because external storage is
        // not currently mounted.
        Log.d("ExternalStorage", "Error writing " + file, e);
    }
}

上面的日志输出如下所示:

context.getExternalFilesDirs() : /storage/extSdCard/Android/data/com.example.remote.services/files/Download

external device is mounted.

external device download : /storage/extSdCard/Android/data/com.example.remote.services/files/Download

external device app path: /storage/extSdCard/Android/data/com.example.remote.services/files/
于 2014-03-05T14:53:17.773 回答
0

我通过删除 清单文件中的 inandroid:maxSdkVersion="18"解决了这个问题。uses-permission即使用这个:

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

代替:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
                 android:maxSdkVersion="18" />
于 2014-09-20T10:35:14.567 回答
0

检查用户是否具有外部存储权限。如果没有,则使用缓存目录来保存文件。

final boolean extStoragePermission = ContextCompat.checkSelfPermission(
               context, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                == PackageManager.PERMISSION_GRANTED;

            if (extStoragePermission &&
        Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) {
                parentFile = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
            }
            else{
                parentFile = new File(context.getCacheDir(),    Environment.DIRECTORY_PICTURES);
            }
于 2016-11-16T06:12:09.147 回答