【安卓基础】Android直接通过路径来操作其他应用的私有目录,可以吗?_android 访问app私有目录-程序员宅基地

技术标签: 文件共享  文件访问权限  存储  Android  

在上篇文章【安卓基础】一文搞懂Android历代版本文件访问权限变化我们对同一个应用的的文件访问权限做了比较。
那么不同应用之间文件访问又有什么限制呢?我们准备分二到三篇文件来阐述。
这篇文章,主要来看下不同系统版本下,我们直接通过路径来访问其它应用的内部存储、外部存储私有目录,看看能不能访问以及不同系统版本的区别。

可能说得有些啰嗦,心急的同学可以直接看大红字哟。

项目地址:https://github.com/codersth/android-foundation-samples/blob/master/app/src/main/java/com/codersth/android/foundation/filesystem/InterAppFileAccessActivity.kt

1.1 api < 19

我们在api18的虚拟机上,当前应用的私有目录下放一个文件。
在这里插入图片描述
然后通过路径的方式尝试直接读取这个文件。

override fun onCreate(savedInstanceState: Bundle?) {
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_inter_app_file_access)
        // 读取当前应用私有目录的文件
        Log.d(TAG, "onCreate: ${readFile("/sdcard/Android/data/com.codersth.android.foundation/files/hello.txt")}")
        // 读取其他应用私有目录的文件(确保手机上其他应用的私有目录下有对应文件)
    }

    /**
     * 读取指定路径下的文件内容
     * @param path 待读取文件的路径,路径可能是其他应用程序的私有目录
     * @return 文件文本内容,如果文件读取失败返回null
     */
    private fun readFile(path: String): String? {
    
        File(path).takeIf {
     it.exists() }?.also {
    
            return FileUtil.readFileContent(File(path))
        }
        Log.d(TAG, "readFile: $path not exists.")
        return null
    }

可以看到,直接通过路径访问自己的私有目录是可以读取文件的。
在这里插入图片描述
接下来,我们访问本机上其他应用私有目录的文件,上传一个文件先。
在这里插入图片描述
接下来我们把上面的读取路径改成另一个应用的私有目录下的文件。

Log.d(TAG, "onCreate:其他应用的私有目录 ${readFile("/sdcard/Android/data/com.example.demo/files/hello.txt")}")

我们看到同样可以访问。
在这里插入图片描述
所以说,能不能直接访问其他应用私有目录,也是要看版本的,至少api 18上还是可以删除的,低版本应该也可以,大家不妨试下。
甚至我们可以直接把文件删除。

 // 删除其他应用私有目录的文件
Log.d(TAG, "onCreate:其他应用的私有目录 ${File("/sdcard/Android/data/com.example.demo/files/hello.txt").delete()}")

不妨再延伸下,试试操作其他应用的内部存储

// 读取其他应用内部存储的文件(确保手机上其他应用的私有目录下有对应文件)
Log.d(TAG, "onCreate:其他应用的私有目录 ${readFile("/data/data/com.example.demo/files/hello.txt")}")
// 删除其他应用内部存储的文件
Log.d(TAG, "onCreate:其他应用的私有目录 ${File("/data/data/com.example.demo/files/hello.txt").delete()}")

结果竟然成功了,就问你意不意外,惊不惊喜

在这里插入图片描述
所以我们可以总结下了:Android4.4(api19)以下完全可以通过路径直接操作其他应用的私有目录和内部存储。

19 <= api <=23

既然api19以下如此为所欲为,我们看下Android4.4是不是安全一些。
使用上述方法,以下是执行结果。
在这里插入图片描述
可以看到,针对其他应用私有目录,读取和删除是可以的;针对内部存储,读取成功,删除失败

接下来们在api=23(6.0)手机复现上述步骤,通过下面的日志可以发现,在第一步读取的时候就报权限问题了。
在这里插入图片描述
《【安卓基础】一文搞懂Android历代版本文件访问权限变化》
这篇文章中我们测试过,api > 18访问应用自身外部存储的私有目录是不需要读写权限的,那导致上面的错误是权限问题还是系统做了其它安全策略呢?
我们不妨动态给个写入权限,结果与api=19上一致。
在这里插入图片描述
总结:19 <= api <=23上,A应用可以直接通过路径读写应用B的私有目录,也可以读取应用B的内部存储,但无法删除内部存储。

24 <= api <=30

由于android N对存储访问策略做了进一步限制,我们在api=24的机器上也试下,提得一得的是,不同系统版本的私有目录路径可能不同。
路径稍微改下(以测试设备为准):

Log.d(TAG, "onCreate:其他应用的私有目录 ${readFile("/sdcard/Android/data/com.example.demo/files/hello.txt")}")
        // 删除其他应用私有目录的文件
Log.d(TAG, "onCreate:其他应用的私有目录 ${File("/sdcard/Android/data/com.example.demo/files/hello.txt").delete()}")

        // 读取其他应用内部存储的文件(确保手机上其他应用的内部存储下有对应文件)
Log.d(TAG, "onCreate:其他应用的内部存储 ${readFile("/data/user/0/com.example.demo/files/hello.txt")}")
        // 删除其他应用内部存储的文件
Log.d(TAG, "onCreate:其他应用的内部存储 ${File("/data/user/0/com.example.demo/files/hello.txt").delete()}")

从下面的日志来看,android N开始对访问其它应用内部存储的读取作了限制。在这里插入图片描述
我们在api = 28上再试下,同样如此(但没有报错)。
在这里插入图片描述
最后我们在30上再看下,如果30的虚拟机上无法查看私有目录,可以在被访问的应用下执行下面代码,然后把路径贴到上面的测试代码中:

private fun saveFile() {
    
        val file1 = File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "hello.txt")
        Log.d(TAG, "saveFile: $file1 saved status: ${
      file1.createNewFile()} ${
      file1.exists()}")
    }

从运行结果来看,api=30是彻底不能操作其他应用的私有目录和内部存储了。
在这里插入图片描述
28可以,30不行,但29呢?
在这里插入图片描述
29的表现也28相同。

由此我们可以给出结论了:
总结:api 24开始,应用A无法直接通过路径访问应用B的内部存储,android 30开始,应用A无法直接通过路径访问应用B的内部存储和私有目录。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_48179608/article/details/123140003

智能推荐

ZYNQ GP总线实现PS与PL交互(一)_zynq如何完成ps和pl的交互-程序员宅基地

文章浏览阅读5.7k次,点赞4次,收藏41次。1,需要对 ZYNQ7 Processing System(PS)配置页面做更改。选中PS-PL Configuration 项,展开 AXI Non Secure Enablement--> GP Master AXI Interface,勾选 M AXI GP0 interface,相当于开启 PS 系统的 AXI GP0 的主机功能。注意下面还有一个 M AXI GP1 interface,也就是说 Zynq 最多可以有 2 个 AXI GP 主机外设。_zynq如何完成ps和pl的交互

跨平台应用开发进阶(四十六)webview方式嵌套H5应用加载慢解决方案_app内嵌h5页面webview-程序员宅基地

文章浏览阅读5k次,点赞3次,收藏15次。项目中通过方式嵌套H5应用时,出现页面加载慢的用户体验问题。尤其当应用第一次加载H5应用时,页面白屏大致有3-4s!经过分析发现,h5页面第一次加载时会下载页面静态资源(包括图片、字体库文件、css样式文件、js脚本等),后续加载时浏览器引擎在缓存机制的作用下会直接加载缓存信息,渲染较快。老生常谈,从输入URL到页面展示,发生了什么?我们可以在控制台输入​​ 来获取 (FP:文档中任意元素首次渲染时间)和 (FCP:也就是我们常说的白屏时间 )当然了,这两个值也不是固定的,比如在第一次打开页面和第二次_app内嵌h5页面webview

pascal_voc数据集下载_pascal_voc_indices.json下载-程序员宅基地

文章浏览阅读815次。Pascal VOC Dataset Mirror_pascal_voc_indices.json下载

大数据的特点(二)-程序员宅基地

文章浏览阅读337次。在前面的文章中我们给大家介绍了大数据的一个特点,那就是大数据的数据量是庞大的。当然,大数据的特点不只是这些,大数据的特点还有大类别以及具有多样性,同时大数据的处理也是十分快速的,我们在这篇文章中就给大家介绍一下大数据的这两个特点。首先我们说一下数据类别大和类型多样。其实大数据的数据来自多种数据源,数据种类和格式日渐丰富,已突破了以前所限定的结构化。数据范畴,包括了半..._】数据的多样性特点是指大数据丰富的数据来源,包含了结构化数据源和非结构化

Torch安装+Densecap实验_sh scripts/download_model.sh-程序员宅基地

文章浏览阅读2k次。Torch安装+Densecap实验本博客用于记录学习过程,欢迎交流。Densecap引入密集的字幕任务,不仅能够定位局部显著的图像,而且能用自然语言来描述该区域。密集字幕任务概括和统一了两个任务,一个是只需要单个单词描述的目标检测任务,另一个是对整个图像的一个预测区域的字幕标注任务。为了同时解决定位和描述任务,提出了一个统一高效的直传处理图像架构,全卷积定位网络(FCLN)架构,无需外部区域的建议_sh scripts/download_model.sh

Java实现动态折线图(多条折线)_idea java折线-程序员宅基地

文章浏览阅读4.7k次,点赞3次,收藏20次。Java实现动态折线图导包过程IDEA中:File——>Project Structure——>Project Settings——>modules——>Dependencies——>+点完加号之后找到jfreechart的jar包所在位置,建议将其放在项目的lib文件夹下。使用实例public class Chart extends JPanel{ private ChartPanel chartPanel; private TimeSeries_idea java折线

随便推点

android之表格布局_andriod 表格-程序员宅基地

文章浏览阅读2.2k次。表格布局1、表格布局就是往里面加行组成,tableraw2、在tableraw加内容实现列3、子容器中设置属性weight来瓜分tableraw4、图片属性是tableview_andriod 表格

【LATEX】如何并排并列插入图片_texstudio中怎么并排插入图片-程序员宅基地

文章浏览阅读4k次。有一个任务就是如何将四张pdf(当然也可以是其他格式的)合并为一个文件,并且是两行两列排列。在网上找了半天的资料,很多代码跑不通,最后修改了一些内容,终于成功了~ps:里面很多宏包并没有用到,因为我是直接从以前写实验报告的tex文件里复制过来的,只是新增加了\usepackage{subfigure}\usepackage{graphicx}这些宏包基本上能满足所有的需求啦~\documentclass{zjureport}%自己创建的一个文件\usepackage{times}\usepa_texstudio中怎么并排插入图片

Kotlin学习笔记(九)协程简单概念与简单使用_kotlin 协程 join-程序员宅基地

文章浏览阅读864次。1. 协程,就是任务调度框架,可以在一个线程里调度,也可以在一个线程池里调度。2. Kotlin的协程和RxJava一样的功能。至少协程有的,RxJava都有。3.协程和线程的相同点是,都一个“程”字,也就是说,都是要被执行的代码流。4.Kotlin协程的优点是,以“阻塞式的代码”实现“非阻塞式的代码”。都说比RxJava简单一些。........._kotlin 协程 join

I.MX6 eMMC分区挂载-程序员宅基地

文章浏览阅读244次。/********************************************************************* * I.MX6 eMMC分区挂载 * 说明: * 如果想要修改分区的挂载情况,可以修改fstab.freescale文件。 * * ..._imx6 分区挂载

【opencv-python】霍夫圆检测_霍夫圆圆心检测python-程序员宅基地

文章浏览阅读6.7k次,点赞10次,收藏55次。霍夫变换检测直线的原理是利用累加器找到最大的(ρ,θ)(ρ,θ)(ρ,θ)数对,如文章所述。圆形的数学表达式为(x−xcenter)2+(y−ycenter)2=r2(x-x_{center})^2+(y-y_{center})^2=r^2(x−xcenter​)2+(y−ycenter​)2=r2,其中(xcenter,ycenter)(x_{center},y_{center})(xcenter​,ycenter​)为圆心坐标,rrr为圆的直径。因此可知一个圆需要xcenter,ycenter,rx_{_霍夫圆圆心检测python

码仔精选,Android面试题-程序员宅基地

文章浏览阅读171次。码个蛋(codeegg) 第 822次推文码妞看世界1.Java创建对象的几种方式使用new关键字使用Class类的newInstance方法使用Constructor类的newIn..._码个蛋 《每日一道面试题》 第一期

推荐文章

热门文章

相关标签