通常再访问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卡的访问权限。