2015-09-17 152 views
1

我對內部存儲沒有任何問題,但我想在外部SD卡上創建一個目錄,其版本在KitKat之前的版本爲File.mkdirs()無法在外部SD卡(棒棒糖)中創建目錄

有我的部分代碼:

//external sd card 
DocumentFile.fromFile(new File("/storage/sdcard1/")).exists(); //returns true 
DocumentFile.fromFile(new File("/storage/sdcard1/")).canRead(); //returns true 
DocumentFile.fromFile(new File("/storage/sdcard1/")).canWrite(); //returns true 
DocumentFile.fromFile(new File("/storage/sdcard1/test")).exists(); //returns false 
DocumentFile.fromFile(new File("/storage/sdcard1/")).createDirectory("test"); //returns null 

//internal storage 
DocumentFile.fromFile(new File("/storage/emulated/0/")).exists(); //returns true 
DocumentFile.fromFile(new File("/storage/emulated/0/test")).exists(); //returns false 
DocumentFile.fromFile(new File("/storage/emulated/0/")).createDirectory("test"); //it works 
DocumentFile.fromFile(new File("/storage/emulated/0/test")).exists(); //returns true 
DocumentFile.fromFile(new File("/storage/emulated/0/test")).createFile("text", "file.txt"); //it works 

//external sd card 
(new File("/storage/sdcard1/test2/subfolder")).exists(); //returns false 
(new File("/storage/sdcard1/test2/subfolder")).mkdirs(); //returns false 

//internal storage 
(new File("/storage/emulated/0/test2/subfolder")).exists(); //returns false 
(new File("/storage/emulated/0/test2/subfolder")).mkdirs(); //returns true 

在AndroidManifest.xml:

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

測試與BQ Aquaris E4,運行Android Lollipop 5.0和1GB的micro SD卡。

UPDATE:這是我拿貨量列表:

private static ArrayList<StorageInfo> listAvaliableStorage(Context context) { 
     ArrayList<StorageInfo> storagges = new ArrayList<>(); 
     StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); 
     try { 
      Class<?>[] paramClasses = {}; 
      Method getVolumeList = StorageManager.class.getMethod("getVolumeList", paramClasses); 
      getVolumeList.setAccessible(true); 
      Object[] params = {}; 
      Object[] invokes = (Object[]) getVolumeList.invoke(storageManager, params); 
      if (invokes != null) { 
       StorageInfo info; 
       for (Object obj : invokes) { 
        Method getPath = obj.getClass().getMethod("getPath"); 
        String path = (String) getPath.invoke(obj); 
        info = new StorageInfo(path); 
        File file = new File(info.getPath()); 
        if ((file.exists()) && (file.isDirectory()) 
         //&& (file.canWrite()) 
          ) { 
         info.setTotalStorage(file.getTotalSpace()); 
         info.setFreeStorage(file.getUsableSpace()); 
         Method isRemovable = obj.getClass().getMethod("isRemovable"); 
         String state; 
         try { 
          Method getVolumeState = StorageManager.class.getMethod("getVolumeState", String.class); 
          state = (String) getVolumeState.invoke(storageManager, info.getPath()); 
          info.setState(state); 
          info.setRemovable((Boolean) isRemovable.invoke(obj)); 
         } catch (Exception e) { 
          e.printStackTrace(); 
         } 

         storagges.add(info); 
        } 
       } 
      } 
     } catch (NoSuchMethodException | IllegalArgumentException | IllegalAccessException | InvocationTargetException e) { 
      e.printStackTrace(); 
     } 
     storagges.trimToSize(); 

     return storagges; 
    } 

硬編碼路徑是唯一在這個例子中

更新2: 我創建的目錄:在「測試」帶有文件瀏覽器的SD卡。當我執行此代碼:

File file = new File("/storage/sdcard1/test/", "file.txt"); 
fileOutput = new FileOutputStream(file); 

第二行拋出FileNotFoundException: /storage/sdcard1/test/file.txt: open failed: EACCES (Permission denied)

我在做什麼錯?

+0

Logcat中返回任何錯誤消息? –

+0

你也可以發佈你收到的錯誤嗎?另外,請嘗試使用Environment.getExternalStorageDirectory()。getPath()而不是直接指向。檢查此 - > http://stackoverflow.com/questions/32055815/android-mkdirs-not-working-for-me-not-external-storage – Techidiot

+0

沒有錯誤,沒有例外。 Environment.getExternalStorageDirectory.getPath()返回「/ storage/emulated/0 /」,這不是外部sdcard – cgr

回答

2

這是由於Android棒棒糖的設計。 Environment.getExternalStorageDirectory()將僅返回模擬外部存儲的路徑。 Android不會公開任何給你SD卡路徑的API。

此外,在棒棒堂中,除非通過Storage Access Framework獲取用戶權限,否則應用程序無法寫入位於sdcard自己的目錄之外的位置。

嘗試context.getExternalFilesDirs()。這給你一個你的應用程序可以寫入數據的路徑列表。其中一個將在SD卡中,並會像/ storage/sdcardname/Android/data/yourAppName/files

+0

getExternalFilesDirs()返回「/ storage/emulated/0/Android/data/packagename/files」但這不是外部sdcard。解決存儲訪問框架,在這裏一個很好的解釋http://stackoverflow.com/questions/26744842/how-to-use-the-new-sd-card-access-api-presented-for-lollipop/26765884#26765884 – cgr

+0

你確定你使用getExternalFilesDirs而不是getExternalFilesDir嗎? Dir將只返回仿真路徑。 Dirs將返回模擬路徑和SD卡路徑。 – somesh

+0

是的。 http://i.imgur.com/0cgLoeb.jpg – cgr

0

您必須明確定義位置,這裏是我爲創建文件夾和文件夾所做的簡短腳本在該文件夾中,希望這有助於

import java.io.File; 
    import android.app.Activity; 
    import android.content.Context; 
    import android.os.Bundle; 
    import android.os.Environment; 
    import android.widget.Toast; 

public class DirectoryPicker extends Activity { 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.chooser_list);//your xml layout file name 
} 
@Override 
public void onStart() { 
    super.onStart(); 
    String state = Environment.getExternalStorageState(); 
    if (Environment.MEDIA_MOUNTED.equals(state)) { // **Check that we have access to create the folder(s)** 
     File Root = Environment.getExternalStorageDirectory(); //**Get the path and hold it** 
//**Alternativly you can select a certain directory with** 
//File Root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); 
     File folder = new File(Root.getAbsolutePath() + "/main_folder_to_add/second_folder/");//**This puts everything together CORRECTLY** 
     folder.mkdirs();//**Makes the directory folders, make sure to use mkdirs not mkdir** 
     if (!folder.exists()) { 
      folder.mkdirs(); 
     } 
     Context context = getApplicationContext();//**Prove we were successful** 
     String msg = folder.toString(); 
     Toast toast = Toast.makeText(context, msg, Toast.LENGTH_LONG); 
     toast.show(); 
     return; 
    } 
} 
public void onBackPressed() { 

finish(); 
} 
} 
+0

Environment.getExternalStorageDirectory。getPath()返回「/ storage/emulated/0 /」,這不是外部sdcard – cgr

+0

正確,這就是爲什麼我沒有在我的上面的代碼中使用它,首先我得到Environment.getExternalStorageDirectory(),然後把字符串放在一起與文件夾=新文件(Root.getAbsolutePath(),而不是getPath,我在api 4.1和6上測試它,它的工作原理和使用戶可以輕鬆找到的文件夾,而我在這裏發佈的所有其他方法didn' t工作(至少對我來說) – Wraithious