【问题标题】:Cannot write file to external SDcard on android 6.0无法在 android 6.0 上将文件写入外部 SD 卡
【发布时间】:2017-03-20 02:31:05
【问题描述】:

我的设备是Android 6.0.1操作系统,但是无法将文件写入外置SD卡,从日志看,没有权限,但是我有申请成功的权限,而且AndroidManifest.xml中的权限文件;

我使用“adb shell dumpsys package packagename”命令,读写权限都返回true; 然后我查看了设置->应用->我的应用->权限,已经授予读写权限;

我必须使用外部 SD 卡

有没有人遇到过这个问题,我觉得这很奇怪

private void requestPermiss() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission_group.STORAGE) != PackageManager.PERMISSION_GRANTED) {
        if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
            Toast.makeText(this, "We need to read file from sdcard", Toast.LENGTH_SHORT).show();
            ActivityCompat.requestPermissions(this, new String[]{
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
            }, 0);
        }

    }
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(requestCode == 0){
        if(grantResults[0] == PackageManager.PERMISSION_GRANTED
                && grantResults[1] == PackageManager.PERMISSION_GRANTED){
            writeFile();
        }
    }
}

private void writeFile(){
    new Thread(new Runnable() {
        @Override
        public void run() {
            String sdDir = getPath_For23(MainActivity.this, 0);
            File file = new File(sdDir + "/test.txt");
            if(!file.exists()){
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }).start();
}

private static String getPath_For23(Context context, int flag) {
    try {
        StorageManager sManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
        Class class_StorageManager = StorageManager.class;
        Method method_getVolumes = class_StorageManager.getMethod("getVolumes");

        Class<?> class_VolumeInfo = Class.forName("android.os.storage.VolumeInfo");
        Method method_getPath = class_VolumeInfo.getMethod("getPath");
        Method method_getDisk = class_VolumeInfo.getMethod("getDisk");

        Class<?> class_DiskInfo = Class.forName("android.os.storage.DiskInfo");
        Method method_isSd = class_DiskInfo.getMethod("isSd");
        Method method_isUsb = class_DiskInfo.getMethod("isUsb");

        List<Object> volumes = (List<Object>) method_getVolumes.invoke(sManager);
        for (Object volumeInfo : volumes) {
            File file = (File) method_getPath.invoke(volumeInfo);
            if (file != null) {
                Object diskInfo = method_getDisk.invoke(volumeInfo);
                if (diskInfo != null) {
                    boolean isSd = (boolean) method_isSd.invoke(diskInfo);
                    boolean isUsb = (boolean) method_isUsb.invoke(diskInfo);
                    switch (flag){
                        case 0:
                            if (isSd) {
                                return  file.getAbsolutePath();
                            }
                            break;
                        case 1:
                            if (isUsb) {
                                return file.getAbsolutePath();
                            }
                            break;
                    }
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
 }

错误日志:

W/System.err: java.io.IOException: open failed: EACCES (Permission 拒绝)

W/System.err:在 java.io.File.createNewFile(File.java:939)

W/System.err:在 com.example.user.test60.MainActivity$1.run(MainActivity.java:70)

W/System.err: at java.lang.Thread.run(Thread.java:818)

W/System.err:原因:android.system.ErrnoException:打开失败: EACCES(权限被拒绝)

W/System.err:在 libcore.io.Posix.open(本机方法)

W/System.err:在 libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)

W/System.err:在 java.io.File.createNewFile(File.java:932)

W/System.err: ... 2 更多

【问题讨论】:

  • 尝试 Environment.getExternalStorageDirectory();获取路径..
  • 它将返回 /storage/emulated/0,这个内部 sdcard 路径,而不是外部 sdcard
  • 好的,您确定设置了正确的权限吗?您只检查 READ... 以显示权限集 stackoverflow.com/questions/21091022/… 您真的需要 sdcard 吗? Google 推荐使用内部存储(更快、更安全,您可以信赖...)
  • 我已经检查了 WRITE.... ,并使用了 dumpsys 包 packagename,它返回 grant=true 读写权限。
  • 很奇怪。在主线 70 中引发了异常。这是您调用新文件的地方,不是吗?

标签: android permissions android-external-storage


【解决方案1】:

试试这个

String imgLocation = Environment.getExternalStorageDirectory().toString() + "/FolderName/", fileName;
                FileOutputStream fOut = null;
                Date date = new Date();
                File dir = new File(imgLocation);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                fileName = "img" + date.getTime() + ".jpg";
                file = new File(dir, fileName);
                try {
                    Bitmap imageBitmap = bm;
                    FileOutputStream out = new FileOutputStream(file);
                    imageBitmap.compress(Bitmap.CompressFormat.JPEG, 85, out);
                    out.flush();
                    out.close();
                   } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

【讨论】:

  • 否,Environment.getExternalStorageDirectory() 将返回 /storage/emulated/0,指向内部 sdcard,而不是外部 sdcard,我想将文件写入外部 sdcard
  • 嗯..我认为它适用于两者..谢谢提醒。
【解决方案2】:

注意,getExternalFilesDirectory() != getExternalFilesDirs()

我很确定 getExternalFilesDirs(String) 会完成这项工作。检查https://developer.android.com/reference/android/os/Environment.html

他们说:

在具有多个共享/外部存储目录的设备中,这 目录代表用户将交互的主存储 和。可以访问二级存储 通过getExternalFilesDirs(String),getExternalCacheDirs(), 和 getExternalMediaDirs()

【讨论】:

  • 是的,这些方法确实可以返回到外部SD卡目录,但是只能到应用程序目录,但是如果我的文件在SD卡根目录下,这个方法是无法访问的
【解决方案3】:

现代 Android 版本(如 6.0)上的 SD 卡是只读的。

您的应用程序可以写入的唯一位置是其上的应用程序特定目录。

查看getExternalFilesDirs()为该路径返回的第二项。

【讨论】:

  • 我试过了,是内部sdcrad,只能获取指定类型的目录
  • +Victor,使用 getExternalFilesDirS() 而不是 getExternalFilesDir()...第一个返回一个数组..请检查索引 1 处的值,应该是 SD 卡
【解决方案4】:

尝试将此添加到您的清单文件中:

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

这将获得所需的权限。

【讨论】:

  • 已添加
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多