android Q sdcard权限详解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android Q sdcard权限详解相关的知识,希望对你有一定的参考价值。
参考技术A默认情况下,如果应用以 android Q 为目标平台,则在访问外部存储设备中的文件时会进入过滤视图。应用可以使用 Context.getExternalFilesDir() 将专用于自己的文件存储在特定于自己的目录中。
1. 临时停用分区存储行为:
2. 如何实现隔离存储:
2.1 ApplicationInfo新增PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE标记
PackageParser.java:
ApplicationInfo.java:
2.2 grantRuntimePermission()重新挂载视图
apk启动时默认挂载runtime/default视图,grantRuntimePermission()时如果是READ_EXTERNAL_STORAGE或WRITE_EXTERNAL_STORAGE,则会获取挂载模式重新挂载对应视图。
PermissionManagerService.java:
获取挂载模式这块android10有修改,没有设置Legacy标志的话,总是获取default挂载模式,没有读写权限。
android 10会设置属性[persist.sys.isolated_storage]: [true],因此走到if(ENABLE_ISOLATED_STORAGE)中的getMountMode()。
正常模式下hasLegacy=false,走到if判断的DEFAULT分支;legacy模式hasLegacy=true,与之前保持一致,有write权限就走到WRITE模式分支。
2.3 Legacy Storage属性对权限的影响
安装apk时,就会根据requestLegacyExternalStorage属性来对ops state进行设置,修改OP_LEGACY_STORAGE的默认状态。
PermissionPolicyService启动时首先进行权限变化监听:
APK安装时,会根据requestLegacyExternalStorage属性来通知storage权限变化,调用关系如下:
最终调用到PermissionPolicyService的监听函数synchronizePackagePermissionsAndAppOpsForUser(),进行默认权限获取和设置。
当apk安装时,声明了requestLegacyExternalStorage="true"属性,并且声明了READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE,那么addOpIfRestricted()就会将LEGACY_STORAGE设置为allow模式。
3. sdcard路径权限说明:
/mnt/runtime/default:
/mnt/runtime/read:
/mnt/runtime/write:
/sdcard/Android/data:
4. sdcard文件存储示例:
4.1 getExternalFilesDir()随卸载而删除
4.2 媒体文件
媒体文件使用MediaStore操作,卸载后不会删除。
访问其他应用生成的照片、视频、音频,需要READ_EXTERNAL_STORAGE权限。
4.3 存储访问框架(SAF)
访问其他应用创建的文件,例如"Download"目录,必须使用存储访问框架,用户通过框架选择特定文件。
4.4 照片中的位置信息
需要ACCESS_MEDIA_LOCATION权限,才能获取元数据中的位置信息。
Unity读取Android SDcard文件
一、添加权限
权限添加 :Player settings -- Other settings -- write permission的设置 Sdcard。这个是在Unity编辑器里打包的情况。
如果导出到studio 里面的话,可自行修改Manifest文件。
二、两种方式
IO方式 加载sdcard上的图片资源
加载的 /storage/emulated/0/ProjectName/image.jpg,
image = this.GetComponentInChildren<Image>(); Debug.Log("IO加载用时: image = this.GetComponent<Image> ========== " + image); Debug.Log("IO加载: Application.dataPath " + Application.dataPath ); // Application.dataPath /data/app/com.putao.ptx.core-1/base.apk Debug.Log("IO加载: Application.persistentDataPath " + Application.persistentDataPath); // Application.persistentDataPath /storage/emulated/0/Android/data/com.putao.ptx.core/files Debug.Log("IO加载:GameObject.Find" + GameObject.Find("Canvas/Avator").GetComponent<Image>()); // /data/user/0/com.putao.paichallenge/cache/20170524_130527.jpg // path ======= "/storage/emulated/0/ProjectName/image.jpg" FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read); fileStream.Seek(0, SeekOrigin.Begin); //创建文件长度缓冲区 byte[] bytes = new byte[fileStream.Length]; //读取文件 fileStream.Read(bytes, 0, (int)fileStream.Length); //释放文件读取流 fileStream.Close(); fileStream.Dispose(); fileStream = null; //创建Texture int width = 300; int height = 372; Texture2D texture = new Texture2D(width, height); texture.LoadImage(bytes); //创建Sprite Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width,texture.height), new Vector2(0.5f, 0.5f)); image.sprite = sprite;
log上可以看出来 android上 getExternalFilesDir("") 和 Unity里面的Application.persistentDataPath是一致的
WWW方式加载本地图片
url= "file://"+ "/storage/emulated/0/ProjectName/image.jpg"
根本不是加"jar:file://..."
public void LoadByWWW(String path) { StartCoroutine(doLoadByWWW(path)); } IEnumerator doLoadByWWW(String path) { string url = "file://" + "/storage/emulated/0/PaiChallenge/image.jpg"; Debug.Log("doLoadByWWW == url ================== " + url); WWW w = new WWW(url); yield return w; if (w.isDone) { Sprite sprite = Sprite.Create(w.texture, new Rect(0, 0, w.texture.width, w.texture.height), new Vector2(0.5f, 0.5f)); GameObject.Find("Canvas/Avator").GetComponent<Image>().sprite = sprite; }
以上是关于android Q sdcard权限详解的主要内容,如果未能解决你的问题,请参考以下文章
尝试在 Android 中将文件写入 sdcard 时出现 FileNotFoundException(权限被拒绝)
权限被拒绝,同时在 Android SDcard 中写入图像文件
Android 开发中eclipse 下 DDMS 视图中 sdcard 中文件导入的处理