我们先来看下android5.1 init.rc中
mkdir /mnt/shell/emulated 0700 shell shell
mkdir /storage/emulated 0555 root root
mkdir /storage/sdcard1 0000 system system
mkdir /storage/usbotg 0700 system system
mkdir /mnt/media_rw/usbotg 0700 media_rw media_rw
mkdir /mnt/media_rw/sdcard1 0700 media_rw media_rw
export EXTERNAL_STORAGE /storage/emulated/legacy
export PRIMARY_STORAGE /storage/sdcard0
export SECONDARY_STORAGE /storage/sdcard1
export EMULATED_STORAGE_SOURCE /mnt/shell/emulated
export EMULATED_STORAGE_TARGET /storage/emulated
# Support legacy paths
symlink /storage/emulated/legacy /sdcard
symlink /storage/emulated/legacy /mnt/sdcard
symlink /mnt/shell/emulated/0 /storage/emulated/legacy
symlink /storage/emulated/legacy /storage/sdcard0
下面这段是fuse功能,将storage/sdcard1 转到/mnt/media_rw/sdcard1 并且拥有权限
# virtual sdcard daemon running as media_rw (1023)
service sdcard /system/bin/sdcard -u 1023 -g 1023 -l /data/media /mnt/shell/emulated
class late_start
chown system system /data/etc/storage.config
# fusewrapped external sdcard daemon running as media_rw (1023)
service fuse_sdcard1 /system/bin/sdcard -u 1023 -g 1023 -w 1023 -d /mnt/media_rw/sdcard1 /storage/sdcard1
class late_start
service fuse_usbotg /system/bin/sdcard -u 1023 -g 1023 -d /mnt/media_rw/usbotg /storage/usbotg
class late_start
再来看Environment.getExternalStorageDirectory其实这个获得的内部SD卡的路径,只是Android把它理解成了外部存储。
它的路径就是storage/sdcard0,进入目录看,群组的权限是都有的。它的群组是sdcard_r。在APK中,加入相关权限会加入这个群组。也就拥有这些文件夹的读写权限了。
drwxrwx--- root sdcard_r 1980-01-01 08:06 Alarms
drwxrwx--x root sdcard_r 2015-10-20 15:40 Android
drwxrwx--- root sdcard_r 2015-12-03 10:17 Camera360
drwxrwx--- root sdcard_r 2015-11-16 17:24 DCIM
drwxrwx--- root sdcard_r 2015-10-29 13:48 Download
drwxrwx--- root sdcard_r 2015-10-19 17:08 Movies
drwxrwx--- root sdcard_r 2015-10-21 18:55 Music
drwxrwx--- root sdcard_r 1980-01-01 08:06 Notifications
drwxrwx--- root sdcard_r 2015-11-25 13:49 Pictures
drwxrwx--- root sdcard_r 1980-01-01 08:06 Podcasts
drwxrwx--- root sdcard_r 1980-01-01 08:06 Ringtones
drwxrwx--- root sdcard_r 2015-12-03 11:21 baidu
drwxrwx--- root sdcard_r 1980-01-01 08:00 elog
drwxrwx--- root sdcard_r 2015-12-03 10:51 libs
drwxrwx--- root sdcard_r 2015-12-03 11:21 soufun
drwxrwx--- root sdcard_r 2015-12-03 10:17 system
上面是Android原生的,我们公司也是这个方式。
但是我试了华为p8,就不是了。它在设置里面有一个默认存储,当你设置外部SD卡后,这个接口得到的是外部SD卡的路径。
华为这个路径是storage/sdcard1,但是当你插上usb的时候,外部存储又会unmount,导致你微信里面使用的图片都无法使用。这也是我在编写应用的时候老是异常的原因,是获取的sd卡被卸载了。
但是在设置里面选取默认储存,然后Environment.getExternalStorageDirectory返回外部存储地址还是内部存储地址是一个比较好的选择,像我们的平台如果有外部的SD卡,对于应用来说都没有借口知道其路径。只能直接使用storage/sdcard1
如果默认存储是外部sd卡的话,又想获取内部存储的路径怎么办呢?
如果是系统应用可以从storageManager中getVolumList可以获取所有的Volume,后去Volume去看它是不是Primary的,如果是就是内部存储。也可以直接使用getPrimaryVolume获取内存存储的Volume,但是一般的APK调不到这函数。
一般apk应该可以使用mount命令这种方式查看内部存储和外部存储的信息。
rootfs / rootfs ro,relatime 0 0
tmpfs /dev tmpfs rw,seclabel,nosuid,relatime,mode=755 0 0
devpts /dev/pts devpts rw,seclabel,relatime,mode=600 0 0
proc /proc proc rw,relatime 0 0
sysfs /sys sysfs rw,seclabel,relatime 0 0
selinuxfs /sys/fs/selinux selinuxfs rw,relatime 0 0
debugfs /sys/kernel/debug debugfs rw,relatime 0 0
none /acct cgroup rw,relatime,cpuacct 0 0
none /sys/fs/cgroup tmpfs rw,seclabel,relatime,mode=750,gid=1000 0 0
none /sys/fs/cgroup/memory cgroup rw,relatime,memory 0 0
tmpfs /mnt/asec tmpfs rw,seclabel,relatime,mode=755,gid=1000 0 0
tmpfs /mnt/obb tmpfs rw,seclabel,relatime,mode=755,gid=1000 0 0
none /dev/memcg cgroup rw,relatime,memory 0 0
none /dev/cpuctl cgroup rw,relatime,cpu 0 0
tmpfs /tmp tmpfs rw,seclabel,relatime 0 0
/dev/block/platform/comip-mmc.1/by-name/system /system ext4 ro,seclabel,relatime,data=ordered 0 0
/dev/block/platform/comip-mmc.1/by-name/cache /cache ext4 rw,seclabel,nosuid,nodev,noatime,data=ordered 0 0
/dev/block/platform/comip-mmc.1/by-name/userdata /data ext4 rw,seclabel,nosuid,nodev,noatime,noauto_da_alloc,data=ordered 0 0
/dev/block/platform/comip-mmc.1/by-name/amt /amt ext4 rw,seclabel,relatime,data=ordered 0 0
/dev/fuse /mnt/shell/emulated fuse rw,nosuid,nodev,noexec,relatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
/dev/fuse /storage/sdcard1 fuse rw,nosuid,nodev,noexec,relatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
/dev/fuse /storage/usbotg fuse rw,nosuid,nodev,noexec,relatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
上面就是mount命令打出来的信息,可以看到3个fuse文件系统,这个手机上没有外部SD卡,就没有外部SD卡的挂载信息了,内部的SD卡其实就是data分区的一部分。
所以我觉得在我用华为手机开发应用的时候,应该先将默认存储设层内置的,然后再去编写APK,获取的路径应该就是storage/sdcard0,就可以正常使用了。