通常再訪問sd卡前都要獲取sd卡的路徑,以防止不一樣的廠商有不一樣的路徑配置。Android提供了Environment類來獲取系統當前sd卡路徑。java
Log.d(TAG, Environment.getExternalStorageDirectory().getAbsolutePath());
以手上的三星手機爲例,打印出來的結果是node
533 09-20 14:29:47.850 D 32105 32105 sdtest : /storage/emulated/0
adb shell連上手機確認下路徑linux
1 root@degasveltechn:/proc/32105 # cat mounts 2 cat mounts 3 ... 4 /dev/block/platform/soc.2/by-name/USER /data ext4 rw,seclabel,nosuid,nodev,noatime,discard,journal_checksum,journal_asyn 5 c_commit,noauto_da_alloc,data=ordered 0 0 6 ... 7 /data/media /storage/emulated/0 sdcardfs rw,nosuid,nodev,relatime,uid=1023,gid=1023,derive=legacy,reserved=20MB 0 0
/storage/emulated/0 目錄是以sdcardfs方式掛載到目錄/data/media,/data目錄是系統目錄,因而可知android
Environment.getExternalStorageDirectory()
獲取到的是機身內部SD卡的地址,並非真正外部SD卡的地址。android系統是區份內部SD卡和外部SD卡兩種,通常內部SD卡是內部ROM存儲空間的一部分切割出來的,邏輯的意義大於物理。shell
當咱們想用以下方法訪問SD卡的時候ui
1 File sd = new File(Environment.getExternalStorageDirectory(), "text.txt"); 2 try { 3 sd.createNewFile(); 4 } catch (IOException e) { 5 e.printStackTrace(); 6 }
會發現再createNewFile()的時候程序拋出了一個IO異常,系統調用open的時候被返回EACCES文件訪問權限錯誤了。spa
1036 09-20 14:46:28.850 W 32368 32368 System.err: java.io.IOException: open failed: EACCES (Permission denied) 1037 09-20 14:46:28.850 W 32368 32368 System.err: at java.io.File.createNewFile(File.java:946)
1053 09-20 14:46:28.850 W 32368 32368 System.err: Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied
由於咱們沒有在AndroidManifest.xml裏面加入權限使用的聲明code
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Android對於SD卡目錄的訪問權限限制並非直接經過控制linux內核文件權限rwx標誌位來限制應用訪問,而是間接經過package management service控制一個文件orm
/data/system/packages.list
來實現,咱們先看下未加入uses-permission聲明的時候,該文件的內容是什麼xml
cat /data/system/packages.list | grep sdtest com.example.sdtest 10155 1 /data/data/com.example.sdtest default none
當前擁有的組權限是none,再增長了user-permission聲明以後,再看文件內容變成了
cat /data/system/packages.list | grep sdtest com.example.sdtest 10155 1 /data/data/com.example.sdtest default 1028,1015
新增了1028和1015組權限。
而1028正好是sdcard_r,於是就間接擁有了SD卡的訪問權限。