2016-08-20 149 views
1

无法在Android v6.0.1中将文件写入外部SDCard。 测试上的设备:红米手机注3android 6.0无法写入外部SD卡

我使用已经有写权限:

@TargetApi(21) 
public void requestDocumentPermission() { 
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); 
    startActivityForResult(intent, SDCardBrowser.REQUEST_DOCUMENTS); 
} 

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    if (requestCode == REQUEST_DOCUMENTS && resultCode == RESULT_OK) { // given permission 
     Uri uri = data.getData(); 
     takeUriPermission(data.getFlags(), uri); 
     SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit(); 
     editor.putString(Constants.PREFS_DEFAULT_URI, uri.toString()).apply(); 
     doCopy(selectedNodes, toNode); 
    } 
    super.onActivityResult(requestCode, resultCode, data); 
} 

这里是我下面的复制方法,它运行正常,但我没有发现目标字典目标文件。谁遇到过这个问题?帮助我PLZ。

@TargetApi(23) 
public static void copyFileV23(File srcFile, File destFile) { 
    FileInputStream in = null; 
    OutputStream out = null; 
    Context context = XXXApplication.getInstance().getApplicationContext(); 
    ContentResolver resolver = context.getContentResolver(); 
    String strUri = PreferenceManager.getDefaultSharedPreferences(context).getString(Constants.PREFS_DEFAULT_URI, null); 
    if (null == strUri) { 
     return; 
    } 
    DocumentFile rootDocument = DocumentFile.fromTreeUri(context, Uri.parse(strUri)); 

    try { 
     in = new FileInputStream(srcFile); 
     DocumentFile target = find(destFile.getAbsolutePath(), rootDocument, getMimeType(srcFile)); 
     out = resolver.openOutputStream(target.getUri()); 

     if (null != out) { 
      byte[] buf = new byte[4096]; 
      int len; 
      while ((len = in.read(buf)) != -1) { 
       out.write(buf, 0, len); 
      } 
     } 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     try { 
      in.close(); 
      out.close(); 
     } catch (IOException ignore) { 
     } 
    } 
} 

private static DocumentFile find(String absolutePath, DocumentFile root, String mime) { 
    if (null == root || null == absolutePath) { 
     return null; 
    } 
    String[] paths = absolutePath.split("\\/"); 
    for (int i = 0; i < paths.length; i++) { 
     if (paths[i].equals("")) 
      continue; 

     DocumentFile documentFile = root.findFile(paths[i]); 

     if (null == documentFile) { 
      if (i < paths.length - 1) { 
       documentFile = root.createDirectory(paths[i]); 
      } else { 
       documentFile = root.createFile(mime, paths[i]); 
      } 
     } 
     root = documentFile; 
    } 
    return root; 
} 

编辑-1 查找溶液,find()方法不正确。它应该如下所示:

private static DocumentFile findFileInExternal(String absolutePath, DocumentFile root, String mime) { 
    if (null == root || null == absolutePath) { 
     return null; 
    } 

    String externalPath = ExternalStorage.getStoragePath(true); 
    if (null == externalPath) { 
     return null; 
    } 
    absolutePath = absolutePath.substring(externalPath.length()); 

    String[] paths = absolutePath.split("\\/"); 
    for (int i = 0; i < paths.length; i++) { 
     if (paths[i].equals("")) 
      continue; 

     DocumentFile documentFile = root.findFile(paths[i]); 

     if (null == documentFile) { 
      if (i < paths.length - 1) { 
       documentFile = root.createDirectory(paths[i]); 
      } else { 
       documentFile = root.createFile(mime, paths[i]); 
      } 
     } 

     root = documentFile; 
    } 

    return root; 
} 
+0

如果你的'find'方法是不工作的,你应该在你的问题中包含该方法。 – ianhanniballake

+0

@ianhanniballake也许你没有看到它的兄弟,向下滚动代码区域,你会看到'find()'方法发布:-) –

+0

检查你的应用程序信息 - > Permission for double sure if you have it or not。 –

回答

0

find()方法是错误的。在我做split操作之前,我应该删除外部SD卡路径。或者它会两次添加外部SD卡路径。这里是下面的正确find()方法:

private static DocumentFile find(String absolutePath, DocumentFile root, String mime) { 
    if (null == root || null == absolutePath) { 
     return null; 
    } 

    String externalPath = ExternalStorage.getStoragePath(true); 
    if (null == externalPath) { 
     return null; 
    } 
    absolutePath = absolutePath.substring(externalPath.length()); 

    String[] paths = absolutePath.split("\\/"); 
    for (int i = 0; i < paths.length; i++) { 
     if (paths[i].equals("")) 
      continue; 

     DocumentFile documentFile = root.findFile(paths[i]); 

     if (null == documentFile) { 
      if (i < paths.length - 1) { 
       documentFile = root.createDirectory(paths[i]); 
      } else { 
       documentFile = root.createFile(mime, paths[i]); 
      } 
     } 

     root = documentFile; 
    } 

    return root; 
} 
0

看一看getExternalFilesDirs()。它会告诉你两个你可以写文件的路径。第二个是可移动的微型SD卡。

应用程序只能写入卡上应用程序特定的目录。

谷歌允许它。但是现在你必须看看你的制造商是否实现了它。

这种限制的有趣之处在于,您不需要这些目录的通常写入和读取权限。

+0

但我需要写入文件2外部sdcard,我已经测试过'file.mkdir'不能在外部路径上通过'getExternalFilesDirs()'成功创建字典。 –

+0

那么你现在知道制造商正在限制这一点。你确定你用过... FilesDirs()?而不是... FilesDir()?你有两条路吗?你只谈论一条路径。 – greenapps

+0

是的,但这是我的PM的请求:-)我必须这样做,所以我发现'DocumentFile'并使用这种方式可以确实写入。 (如果我是boss = =,我会切断这个功能。) –