省流提示:采用android studio工具开发,记录一次低级的开发,避免以后忘记或者踩坑。


  • 最近有个业余项目开发到一小半,过程中需要读写 Android/data目录的文件,采用常规的文件操作总是提示权限被拒绝,无奈上网参考了很多资料,终于得到了解决。

  • 无法访问Android/data 的原因

  • 安卓11谷歌采用了文件沙盒存储模式,这就导致我的app无法直接访问android/data目录,即使我在清单文件中加了所有文件的读写权限、在程序中动态申请了所有文件的读写权限。当然如果有root权限那就另当别论了。

  • 作为开发者该如何访问Android/data

  1. 第一步当然是在清单文件中申请所有文件权限

<!--读写--><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"tools:ignore="ScopedStorage" />
  1. 在java中动态申请:MainActivity.java的onCreate()周期中:


if (Build.VERSION.SDK_INT >= 23) {//检测是否有写的权限int permission = ActivityCompat.checkSelfPermission(this,"android.permission.WRITE_EXTERNAL_STORAGE");if (permission != PackageManager.PERMISSION_GRANTED) {// 没有写的权限,去申请写的权限,会弹出对话框,这里就不展示了,可以自己写个申请权限的弹窗}
  1. 做完上面两步,接下来就是申请android/data的权限了,这里说明一下我的情况:

  1. 我的主页就一个:mainactivity,全部采用了动态替换Fragment的方法切换页面,而且需要申请特殊权限的还是fragment中的子framgent,这就需要在他们所依赖的activity中重写回调方法,并设置给fragment,然后通过这个fragment再次设置给子fragment。

  1. 在子fragment中某个按钮的点击事件中去调用SAF框架(Android Storage Access Framework),这个框架据说在4.4就引入了,可以自行百度了解。

  1. 获取Android/data的权限:子fragment中:

//在某个按钮的点击事件中:@Overridepublic void onClick(View view) {switch (view.getId()) {case R.id.xxxx://把需要授权的目录转为UriUri uri = DocumentFileUtil.pathToUri("/storage/emulated/0/Android/data");Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI,uri1);intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION| Intent.FLAG_GRANT_WRITE_URI_PERMISSION| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);//这里的第二个参数是标志的意思,用来判断是谁把结果回调过来的。requireActivity().startActivityForResult(intent, 1001);break;}
}
  1. 这时候会调出这个页面:

  1. 在点击授权后,程序会返回到MainActivity,所以要在这个活动中重写onActivityResult:

     @Overrideprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);//把onActivityResult设置fragmentFragment f = getSupportFragmentManager().findFragmentByTag("HOME_FRAGMENT");assert f != null;f.onActivityResult(requestCode, resultCode, data);switch (requestCode) {case 1001:if (resultCode == Activity.RESULT_OK) {//固定永久权限,否则当重启app时权限就没有了assert data != null;getContentResolver().takePersistableUriPermission(data.getData(),Intent.FLAG_GRANT_READ_URI_PERMISSION| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);}break;default:break;}
  1. 通过activity设置onActivityResult给framgent后,如果子fragment也需进行相关操作,则需要通过父fragment再把onActivityResult设置给子framgent。这里有一点需注意,当我们的子fragment是父fragment通过viewPager容器添加进去的时候,没有Tag也没有ID,如何精准的设置给需要的这个回调的子fragment呢?

  1. 如果适配器是继承的FragmentStatePagerAdapter,这就要用到fragment适配器的instantiateItem了。具体做法:在父fragment中寻找没有tag和id的子fragment:

  @Overridepublic void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);//实例化适配器MyFragmentAdapter fragmentAdapter = (MyFragmentAdapter) vp.getAdapter();assert fragmentAdapter != null;//通过子fragment在viewPager的position来定位。UpDataMsgFragment fragment = (UpDataMsgFragment) fragmentAdapter.instantiateItem(vp, 1);//设置fragment.onActivityResult(requestCode, resultCode, data);
}
  1. 这样一来子fragment就有了回调,然后看他何如使用:

//回调事件,可以得到上个活动或fragment返回的结果@Overridepublic void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);//判断文件是否存在 DocumentFileswitch (requestCode) {case 6666:if (resultCode == Activity.RESULT_OK) {//persist uri//固定永久权限assert data != null;requireActivity().getContentResolver().takePersistableUriPermission(data.getData(),Intent.FLAG_GRANT_READ_URI_PERMISSION| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);Log.i("回调事件:", "Access persist uri permission to Android/data");}}
}
  1. 此时子fragment就有了回调结果,可以通过Document来操作andriod/data的文件了

  1. 注意:用户可以随时取消你的data访问权限,所以避免闪退,还需要在用到Document的地方寄一个判断有无相关目录的权限。

 public boolean isHaveAndroidDataGrant(Context context) {boolean b = true;for (UriPermission persistedUriPermission : context.getContentResolver().getPersistedUriPermissions()) {b = persistedUriPermission.getUri().toString().equals("content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fdata");//这里的content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fdata不渴随意更改里面的%3Ahe %2F字符,可按此格式自行拼接需要的目录。}return  b;}

总结:先在清单文件申请权限,然后在程序中动态申请,其次在需要授权的activity(或fragment)中启用SFA框架,最后在回调回来的activity中重写onActivityResult,如果是多层嵌套的fragment,则通过tag或id或position找到对应的fragment,一层一层的传递过去。

安卓学习笔记:安卓11访问/读写 Android/data 目录相关推荐

  1. 2020年安卓学习笔记目录

    文章目录 一.讲课笔记 二.安卓案例 三.安卓实训项目 四.学生安卓学习博客 五.安卓课后作业 (一)界面设计练习 1.制作登录界面 2.制作部队管理界面 3.制作灭火救援界面 4.制作交付界面 5. ...

  2. 安卓学习笔记3——登录界面UI

    安卓学习笔记3--登录界面UI 一.登录界面UI 1.根据需求写UI 2.主活动 3.主活动调用的读写文件的工具类 4.效果展示 二.总结与改进 不足: 1.密码分割采用字符串:当密码和用户名包含该字 ...

  3. 安卓学习笔记07:事件处理、窗口跳转与传递数据

    文章目录 零.学习目标 一.三个基本控件 1.标签控件(TextView) 2.编辑框控件(EditText) 3.按钮控件(Button) 二.安卓事件处理机制 (一)安卓事件处理概述 (二)安卓事 ...

  4. 很low的安卓学习笔记(一、实用技巧)

    很low的安卓学习笔记(一.实用技巧) 一.学习了几天的实用技巧小总结: 1.规范的定义内容的格式: 2.一些快捷键 3.将xxx.xml布局改为Activity中可以调用的View视图 4.当左下角 ...

  5. 安卓学习笔记之骚扰拦截

    安卓学习笔记之骚扰拦截 1.监听电话状态 2.检测来电号码是否匹配拦截条件 3.若匹配,则挂断电话 实例代码: 获取TelephonyManager 对象,并监听来电状态 TelephonyManag ...

  6. Java编程思想学习笔记-第11章

    <?xml version="1.0" encoding="utf-8"?> Java编程思想学习笔记-第11章 Java编程思想学习笔记-第11章 ...

  7. Jenkins持续集成学习笔记(2020.11.22)

    Jenkins持续集成学习笔记(2020.11.22) 前言: (官网) 以前很久学习过Jenkins持续集成进行快速部署项目进行测试, 最近换工作了, 发现新公司有用到, 现在来复习一下 官网介绍: ...

  8. python学习笔记之编写readConfig读写配置文件

    python学习笔记之编写readConfig读写配置文件_weixin_34055910的博客-CSDN博客

  9. Linux第二周学习笔记(11)

    Linux第二周学习笔记(11) 2.17 隐藏权限lsattr_chattr chattr命令:是设置吟唱隐藏权限的命令,更改Linux文件系统上的文件属性. 参数说明: A:表示文件或目录的ati ...

最新文章

  1. 树莓派教程之树莓派系统镜像刷入和远程登陆(1)
  2. 团队软件开发第一次冲刺(二)
  3. 把所有的谎言献给你β
  4. [转]软件保护之注册算法篇
  5. android 指定资源id,Android 通过名称获取资源ID
  6. Windows Workflow HOL学习笔记(十二):创建状态基工作流
  7. bzoj 3611: [Heoi2014]大工程(虚树+树形DP)
  8. [USACO14OPEN]Fair Photography【前缀和】
  9. asp.net后台操作javascript:confirm返回值
  10. (转)国外优秀区块链创业公司梳理
  11. HTC G14解锁S-OFF、刷机、获取ROOT权限
  12. 如何下载专利(国内)
  13. 只需四天,从零开始选购笔记本电脑【转】【荐】
  14. 计算机金额函数,Excel数字转大写金额方法 一个隐藏函数搞定
  15. 修改smartbi的JVM调优
  16. 电子线路设计技巧5:CDRH系列贴片电感
  17. Macbook怎么录屏?macbook怎么屏幕录制
  18. 《云计算与大数据》课程报告
  19. BlockingQueue的用法
  20. 20189200余超 2018-2019-2 移动平台应用开发实践作项目代码分析

热门文章

  1. Python爬虫实例:爬取微信公众号图片(表情包)
  2. 作业帮一课FE技术分享记录
  3. 常见测试用例的设计方法
  4. QTP自动化测试技术——经典面试题
  5. iOS-触发home键和电源键
  6. Lifecycle 使用及原理解析 一文搞懂
  7. 【Ubuntu】16.04服务器:驱动更新+cuda11+cudnn
  8. 笔记本电脑死机原因大全
  9. java 蓝牙打印_Android蓝牙打印(app源码)
  10. Location属性和方法