Android4.4(API级别19)引入了存储访问框架(SAF).SAF其中的部分功能就是通过其获取对外置sd卡的读写权限,从而操作外置sd卡.原文介绍连接,这里不对其进行复制粘贴,本帖直接讲述如何通过documentFile在获得SAF的后,在外置SD卡中读写数据.
Android 4.4提供了复杂的权限获取步骤,在android7.0时进行了简化.
StorageManager sm = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
List<StorageVolume> volume = sm.getStorageVolumes();
int size = volume.size();
Log.i(TAG, "size: " + size);
for (int i = 1; i < size; i++) {
StorageVolume storageVolume = volume.get(i);
Intent intent = storageVolume.createAccessIntent(null);
startActivityForResult(intent, REQUEST_REQUEST_CODE);
}
上面的代码volume会返回内部存储和外部SD卡(我们所需要操作的卡,包括华为的NM卡),
使用 StorageManager
类获取适当的 StorageVolume
实例。然后,通过调用该实例的 StorageVolume.createAccessIntent()
方法创建一个 intent。使用此 intent 访问外部存储目录。要获取所有可用卷的列表,包括可移动介质卷,请使用 StorageManager.getStorageVolumes()
。
如果您有关于特定文件的信息,请使用 StorageManager.getStorageVolume(File)
获取包含该文件的 StorageVolume
。调用此 StorageVolume
上的 createAccessIntent()
以访问文件的外部存储目录。
在次要卷(例如外部 SD 卡)上,调用 createAccessIntent()
以请求访问整个卷而不是特定目录时将传入“null”。如果您向主要卷传入“null”,或者如果您传入无效的目录名,createAccessIntent()
将返回“null”。 createAccessIntent()也可以传入多种媒体类型,包括电影,图片,文档,音乐等.
Parameters | |
directoryName | String : must be one of Environment.DIRECTORY_MUSIC , Environment.DIRECTORY_PODCASTS , Environment.DIRECTORY_RINGTONES , Environment.DIRECTORY_ALARMS , Environment.DIRECTORY_NOTIFICATIONS , Environment.DIRECTORY_PICTURES , Environment.DIRECTORY_MOVIES , Environment.DIRECTORY_DOWNLOADS , Environment.DIRECTORY_DCIM , or Environment.DIRECTORY_DOCUMENTS , or null to request access to the entire volume. |
权限处理
权限的请求在Fragment或者Activity中发起,在onActivityResult中intent.getDate()获得权限uri参数.当然过程中会弹出一个询问框,当用户同意后我们才能得到权限uri,有了这个uri我们就可以操作外置SD卡了.为了不重复的要求用户给予访问权限,在用户授予访问权限后,调用 getContentResolver()
,在返回 ContentResolver
后,使用目录访问 URI 调用 takePersistableUriPermission()
。系统将保留此 URI,后续的访问请求将返回 RESULT_OK
,且不会向用户显示确认 UI。
uri = resultData.getData();
final int takeFlags = resultData.getFlags()
& (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Check for the freshest data.
getContentResolver().takePersistableUriPermission(uri, takeFlags);
我们也可以将获得的uri保存起来,方便再次使用.
PreferenceManager.getDefaultSharedPreferences(this).edit().putString(PREF_DEFAULT_URI, uri.toString()).commit();
最后一点,获取外置SD卡的路径在各个机型上可能还不同,我的测试机是华为mate8(SD卡),mate20pro(NM卡).
下一篇在获得uri的情况下如何读写文件