2016-08-20 167 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 = =,我會切斷這個功能。) –