Android 文件存储 和 权限管理

2023-05-16

转载请标明出处: :http://blog.csdn.net/huaiyiheyuan/article/details/52473984

android SD卡主要有两种存储方式 Internal 、 External Storage

Internal

特点

  • It’s always available.
  • Files saved here are accessible by only your app.
  • When the user uninstalls your app, the system removes all your app’s files from internal storage.

内部存储不需要申请任何权限

        String fileInnerName = "/inner/img"; //目录名
                        //内置存储缓存目录
        File fileCache = new File(getActivity().getCacheDir(), fileInnerName); 
        //     /data/data/com.android.imageloaderstorage/cache/inner/img
         if (!fileCache.exists()) {
            boolean isInner = fileCache.mkdirs();
          }
         Log.i(" FileFragment ",  "  " + fileCache.getAbsolutePath());

由此可以看到 绝对路径:

Context.getCacheDir():/data/data/应用包名/cache/ fileInnerName

External Storage

外部存储也分两种 Private files (外部私有存储) 、Public files (外部公有存储)

它并非始终可用,因为用户可采用 USB 存储的形式装载外部存储,并在某些情况下会从设 备中将其删除。
它是全局可读的,因此此处保存的文件可能不受您控制地被读取。
当用户卸载您的应用时,只有在您通过 getExternalFilesDir() 将您的应用的文件保存在 目录中时,系统才会从此处删除您的应用的文件。
对于无需访问限制以及您希望与其他应用共享或允许用户使用电脑访问的文件,外部存储是最佳位置。

Private files

本属于您的应用且应在用户卸载您的应用时删除的文件。尽管这些文件在技术上可被用户和其他应用访问(因为它们在外部存储上),它们是实际上不向您的应用之外的用户提供值的文件。当用户卸载您的应用时,系统会删除应用外部专用目录中的所有文件。
例如,您的应用下载的其他资源或临时介质文件。
AndroidManifest.xml 申请权限

 <!-- 往SDCard写入数据权限 -->
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="18" />
    <!-- 在SDCard中创建与删除文件权限 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />   ?需要吗?

https://developer.android.com/guide/topics/manifest/uses-permission-element.html

(context.getExternalCacheDir())

/* Checks if external storage is available for read and write */
 String fileOutName = "/AutDir/fileOut";
                if (!isExternalStorageWritable()) {
                    return;
                }
                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
                    File fileOut = new File(getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES) + fileOutName);  //   /storage/emulated/0/Android/data/com.android.imageloaderstorage/files/Pictures/AutDir/fileOut
                    boolean flag = fileOut.mkdirs();
                    Log.i("FileFragment", fileOut.getAbsolutePath());
                }
                //缓存目录
                File fileOutCache = new File(getActivity().getExternalCacheDir() + fileOutName); //  /storage/emulated/0/Android/data/com.android.imageloaderstorage/cache/AutDir/fileOut
                Boolean isInner = fileOutCache.mkdirs();
                Log.i("FileFragment", " 路径 " + fileOutCache.getAbsolutePath());    

Public files

这里写入目录属于Dangerous Permissions,不能添加 android:maxSdkVersion="18",否则申请权限会出问题
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

如果手机是6.0以下或设置 targetSdkVersion <=22,那么用下面方法可以直接创建目录

   /**
     * 创建外部公有目录
     */
    protected void createOutPublicDir() {
     if (!isExternalStorageWritable()) {
            return;
        }
        File filePublic = new File(Environment.getExternalStorageDirectory() + fileOutPublicName);   //   /storage/emulated/0/AutPublic/outDir
        if (!filePublic.exists()) {
            filePublic.mkdirs();
        }
    }

权限处理

  上面如果 targetSdkVersion >=23,就要考虑权限问题了

权限,那么就要弄清楚 compileSdkVersion 、minSdkVersion、targetSdkVersion的区别 了。

  • compileSdkVersion :

需要强调的是修改 compileSdkVersion 不会改变运行时的行为。当你修改了 compileSdkVersion 的时候,可能会出现新的编译警告、编译错误,但新的 compileSdkVersion 不会被包含到 APK 中:它纯粹只是在编译的时候使用。(你真的应该修复这些警告,他们的出现一定是有原因的)

因此我们强烈推荐总是使用最新的 SDK 进行编译。在现有代码上使用新的编译检查可以获得很多好处,避免新弃用的 API ,并且为使用新的 API 做好准备。

  • minSdkVersion:
    这个好理解 minSdkVersion 则是应用可以运行的最低要求。minSdkVersion 是 Google Play 商店用来判断用户设备是否可以安装某个应用的标志之一
  • targetSdkVersion :
    targetSdkVersion 是 Android 提供向前兼容的主要依据,就像后面在“外置公有目录”创建快捷方式,targetSdkVersion 22可以创建,targetSdkversion 23不能创建

权限设置代码

外置公有目录(Environment.getExternalStorageDirectory())

     // Here, thisActivity is the current activity
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                        // Should we show an explanation?
                        if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
//                            当某条权限之前已经请求过,并且用户已经拒绝了该权限时,shouldShowRequestPermissionRationale ()方法返回的是true
                        } else {
//                            ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_REQUEST_CODE);
                            requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_REQUEST_CODE);
                        }
                    }
                } else {
                    createOutPublicDir();
                }


 @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case WRITE_EXTERNAL_STORAGE_REQUEST_CODE: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // permission was granted, yay! Do the
                    // contacts-related task you need to do.
                    createOutPublicDir();
                } else {
                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                }
                return;
                // other 'case' lines to check for other
                // permissions this app might request
            }
        }
    }

如果我们在低于23的手机上运行,那么它安装试默认给定权限,targetSdkVersion 不管怎么改都没用了

A、权限这块每次都要卸载 然后运行

B、我们通常在通常在Frament 调用 requestPermissions发起权限,但是在onRequestPermissionsResult没有回调 所以要用 Frament的 requestPermissions方法

3、getExternalStorageDirectory和getExternalStoragePublicDirectory的区别

String vUrl = Environment.getExternalStorageDirectory().getPath() +
“/mv.mp4”; String vm =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).getPath()+
“/mv.mp4”;

打印出来的路径:
/storage/emulated/0/mv.mp4
/storage/emulated/0/Movies/mv.mp4
多了个Movies目录,其实使用不同的Type就有不同的目录,像 Alarms、DCIM、Download、Movies、Music、Notifications、Pictures、Podcasts、Ringtones九大目录

android:maxSdkVersion="18"原因

处理的是 WRITE_EXTERNAL_STORAGE getExternalFilesDir(String) and getExternalCacheDir()

  • 如果要申请 内置目录读写在api>=19是不需要声明权限的,但是为了兼容
    为了兼容android版本 ,通常minSdkVersion 14,那么就要声明WRITE_EXTERNAL_STORAGE 权限了
    然而声明之后我们在设置里是不是会看到这(借的图)
    [外链图片转存失败(img-Lyvi1FAk-1568797653293)(http://unclechen.github.io/content/images/app-perm-before.png)]
    如果持有6.0手机的用户把 存储空间 给关了,而我刚好没适配6.0就以 targetSdkVersion 22打包,那么应用就没办法使用内置存储空间了,应用基本跑不了
  • 加上android:maxSdkVersion="18"
    这里写图片描述
    就没这个按钮关了
  • 但是有个问题,如果要使用外置存储目录(Environment.getExternalStorageDirectory()) android:maxSdkVersion="18"就不能加了,否则没法使用了,授权框也不会弹出来
    参考:https://developer.android.com/reference/android/Manifest.permission.html#WRITE_EXTERNAL_STORAGE

特别注意 mkdir(),mkdirs(),createNewFile()的区别

  • createNewFile:新建文件(非目录)
    
  • mkdir:新建目录
    
  • mkdirs:新建目录,与mkdir的区别是:比如   mkdirs(“D:/test/test2”) 如果test  ,   不存在会创建,然后创建test2,如果是  mkdir(“D:/test/test2”) ,如果 
                test不存在,会失败。
    
  • android io输入文件
new File(param1,param2); param1 File,param2  String类型
 
 String dir = StorageUtils.getCacheDirectory(this);
 String apkDIR = "apkdir.apk";
File apkFile = new File(dir, apkDIR);

参考:

https://developer.android.com/training/permissions/requesting.html
https://developer.android.com/guide/topics/permissions/requesting.html
https://developer.android.com/training/basics/data-storage/files.html?hl=zh-cn

http://www.jianshu.com/p/2de0113b3164
http://unclechen.github.io/2016/03/05/Android6.0%E8%BF%90%E8%A1%8C%E6%97%B6%E6%9D%83%E9%99%90%E7%AE%80%E4%BB%8B/
http://chinagdg.org/2016/01/picking-your-compilesdkversion-minsdkversion-targetsdkversion/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 文件存储 和 权限管理 的相关文章

  • 计算Android设备的PPI

    如何计算 Android 设备的 PPI 最特别的是 Android 平板电脑 请注意 我想计算设备的 PPI 而不是 DPI 就像一二三一样简单 让我们来计算一下PPI to Nexus 5 例如 float LCD Diagonal 4
  • 如何获取之前的碎片?

    为了在我的应用程序中重用某些片段 我需要知道哪个片段是返回堆栈上的第二个片段 为了做到这一点 我正在使用getFragmentManager getFragments 显示以下错误 但有效 FragmentManager getFragme
  • Android webview 滚动不起作用

    我正在尝试在网络视图中向下滚动到页面底部 我正在使用谷歌在其教程中提供的网络视图示例 我正在使用这行代码来尝试滚动 但它不起作用 mWebView pageDown true 关于如何使其以编程方式滚动有什么建议吗 谢谢 public cl
  • 使用 google Directions API 的地图视图绘制方向 - 解码折线

    我正在尝试使用 Google 方向 API 在我的地图视图上显示方向 但我在从 JSON 响应获取数据时遇到困难 我可以获得 级别 和 点 字符串 但无法弄清楚如何将它们解码为地图上的点 任何帮助将非常感激 我有一个类可以为您解码它们 添加
  • Manifest Merger工具:替换失败

    我正在使用一个使用自己的 android theme 的库 因此在构建时收到以下错误 错误 55 9 任务 contacit processDebugManifest 执行失败 清单合并失败 AndroidManifest xml 中的属性
  • 自定义选择器活动:SecurityException UID n 无权 content:// uri

    我正在构建一个选择器应用程序来替换本机 Android 共享对话框 它工作正常 除非我尝试通过长按图像 gt 共享图像从 Chrome 共享图像 我发现 Google 没有捕获异常 它崩溃了 所以我可以通过 Logcat 查看它 在 Goo
  • 如何使用Android opencv使图像的白色部分透明

    我无法链接超过 2 个网址 因此我将我的照片发布到此博客 请在这里查看我的问题 http blog naver com mail1001 220650041897 http blog naver com mail1001 220650041
  • 安卓定位不准确

    我正在尝试获取当前用户的位置 我试图重构我的代码以获得更好的结果 但我只是不断得到关于准确度的荒谬位置 它在 900 600 米之间 如何才能得到更好的结果 使其精度达到50m以内 这是我的代码 package com agam mapsl
  • Android 如何更改 OnTouchListener 上的按钮背景

    你好 我在 xml 中有一个按钮 我正在使用OnTouchListener在我的活动中获得button按下并释放 但问题是 当我按下按钮时背景颜色没有改变 当我延长可能的活动时OnClickListener背景正在改变 任何人都可以告诉我的
  • 播放 SoundCloud 曲目

    我可以在 Android 应用程序中播放 SoundCloud 中的曲目吗 我正在尝试这段代码 但它不起作用 String res https api soundcloud com tracks 84973999 stream client
  • Android在排序列表时忽略大小写

    我有一个名为路径的列表 我目前正在使用以下代码对字符串进行排序 java util Collections sort path 这工作正常 它对我的 列表进行排序 但是它以不同的方式处理第一个字母的情况 即它用大写字母对列表进行排序 然后用
  • Android 自定义布局 - onDraw() 永远不会被调用

    public class MainActivity extends Activity Override public void onCreate Bundle savedInstanceState super onCreate savedI
  • Android Library项目使用gradle在命令行编译时无法导入另一个库项目的R类

    我的 android 项目有这样的结构 ProjectDir settings gradle MyApp depends on LibraryA and LibraryB gt build gradle gt All the other a
  • AudioTrack、SoundPool 或 MediaPlayer,我应该使用哪个?

    如果我需要能够 播放多个音频文件 具有不同的持续时间 例如 5 到 30 秒 独立设置右 左声道的音量 应用声音效果 如混响 失真 那么 我应该使用哪个 API 另外 我在 AudioTrack API 上找不到太多文档 有谁知道在哪里可以
  • Android onChange 事件未在 android 5 (Lollipop) 上的 chrome 历史记录的 contentObserver 中触发

    我注意到我的 chrome 历史记录和书签的 contentObservers 在 android lolipop 上不再触发 该代码在旧版本的 android 上完美运行 无论 chrome 版本如何 但在 Lollipop 上它不再运行
  • 使用 PhoneGap 使 Android 应用程序易于访问(对于残障人士)

    有人有过使用 PhoneGap 使 Android 应用程序可访问的经验吗 至少我们需要使我们的应用程序符合第 508 条规定 我尝试实现一些标准的辅助功能 文本框标签 向 div 添加标题属性等 但是 当在 Android 中使用 Tal
  • 在游戏视图下添加 admob

    我一直试图将 admob 放在我的游戏视图下 这是我的代码 public class HoodStarGame extends AndroidApplication Override public void onCreate Bundle
  • 在 Android 中调整可绘制对象的大小

    我正在为进度对话框设置一个可绘制对象 pbarDialog 但我的问题是我想每次调整可绘制的大小 但不知道如何调整 这是一些代码 Handler progressHandler new Handler public void handleM
  • 如何在 Viewpager 中禁用预加载下一页? [复制]

    这个问题在这里已经有答案了 如何在 Viewpager 中禁用页面预加载 I tried viewPager setOffscreenPageLimit 0 但它不起作用 用这个viewPager setOffscreenPageLimit
  • Android应用程序可以像旧的普通java小程序一样嵌入到网页中吗?

    我对 android 平台一无所知 也无法在互联网上找到这个基本问题的答案 更新 好的 我本身无法嵌入 Android 应用程序 但是我可以在 Android Webbrowser 中嵌入 Java 的东西吗 不可以 您无法将 Androi

随机推荐

  • 学C++有多难,你知道吗?

    都2020年了 xff0c 还要学C 43 43 吗 xff1f C 43 43 好多理工科大学里面都有 xff0c 它的学习难度比其他编程语言比如Python Javascript 和Java等等难 那为什么呢 xff1f C 43 43
  • 搞懂Java高级特性--注解

    1 注解是什么 xff1f Java注解 xff08 Annotation xff09 又称Java标注 xff0c 是JDK5 0引入的一种注释机制 xff0c 注解是元数据的一种形式 xff0c 提供有关于程序但不属于程序本身的数据 x
  • 为什么都说代码改变世界?是因为这五位程序员创造了未来!

    致敬那些为软件开发奠定坚实基础的计算机科学先驱 从 1 和 0 开始 xff0c 编程经历了很长一段路 xff0c 才达到了现在的抽象状态 过去的程序员用伟大的发明 xff0c 为现代程序员轻松地完成工作奠定了坚实的基础 如果我们研究某个软
  • 编译提示缺少libjli.so,jar command not found,javadoc错误等

    这周一周忙于Ubuntu server环境下的Android编译环境的搭建 xff0c 由于刚开始真正使用Linux xff0c xff08 以前虽然用过Ubuntu xff0c 但是就当win用了 就这样还没坚持下来 xff0c 现在工作
  • 银河麒麟系统4.0.2离线安装MySQL教程

    银河麒麟系统4 0 2离线安装MySQL教程 xff08 Ubuntu离线安装MySQL教程 xff09 https www jianshu com p 478dc7c9b9e0 这个教程很详细 xff0c 我不再多说 xff0c 而且亲测
  • 实现线程同步的几种方式

    在多线程中线程的执行顺序是依靠哪个线程先获得到CUP的执行权谁就先执行 xff0c 虽然说可以通过线程的优先权进行设置 xff0c 但是他只是获取CUP执行权的概率高点 xff0c 但是也不一定必须先执行 在这种情况下如何保证线程按照一定的
  • STC开天斧虚拟示波器使用

    开天斧外观图 xff0c 颜值非常可以 1 在keil中添加STC8H8K64U的型号和头文件 xff0c 添加功能在STC IPS软件里 首先点击Keil仿真设置 xff0c 然后选择单片机型号STC8H8K64U xff0c 然后点击添
  • android AlertDialog 弹窗自定义布局 点击外部不关闭弹窗

    AlertDialog span class token punctuation span Builder builder span class token operator 61 span span class token keyword
  • delete释放new[] 以及 delete[]释放new 的问题

    在同花顺 的笔试过程中遇到这么一个类似问题 A ptr 61 new A 10 for int i 61 0 i lt n i 43 43 delete amp ptr i 由此衍生出两个问题 new 申请的空间用delete释放会发生什么
  • C#中的readonly与const区别

    xfeff xfeff const 的概念就是一个包含不能修改的值的变量 常数表达式是在编译时可被完全计算的表达式 因此不能从一个变量中提取的值来初始化常量 如果 const int a 61 b 43 1 b是一个变量 xff0c 显然不
  • 改变无线连接、有线连接的优先级

    有线和无线连的是同一个网络 xff0c 当笔记本打开时 xff0c 总是优先使用无线连接 xff0c 如何转变优先级为有线连接呢 xff1f 1 打开网络和共享中心 2 更改适配器设置 xff0c 打开网络连接窗口 3 单击此窗口的高级菜单
  • 杂感一

    从2014年7月工作至今已有快2年了 xff0c csdn的博客从毕业后就很少上了 工作中有很多收获 技术上 也在不断积累和成长中 不管做什么事情 xff0c 要坚持下去 xff0c 方得初心 xff0c 把坚持养成习惯 xff0c 学习如
  • Kotlin实战---Retrofit网络模型

    没有Kotlin基础的小伙伴先进这里 Koltin基础文章 1 Java和Kotlin互相调用之间的注意事项 1 解决关键字冲突 span class token keyword public span span class token k
  • MFC隐藏主窗口的方法

    隐藏基于对话框的MFC应用程序窗口的方法 推荐这个方法 xff0c 非常好用 很多人可能会将窗口创建出来 然后用一个 ShowWindow SW HIDE 的方法去隐藏窗口 当然这是可以做到隐藏的功能 但是有一点不足的地方就是窗口在隐藏之前
  • JSP 通过Servlet将excel数据导入SQL

    1 gt 在网上下载jxl jar 这个JAR包用于Java操作excel 下载后 xff0c 将这个包复制到工程Webroot下的WEB INF下的lib中 xff0c 或是在工程中导入jxl jar包 2 gt 准备excel文件 如图
  • 1=5,2=15,3=215,4=2145,那么5=?

    如题 xff0c 1 61 5 xff0c 2 61 15 xff0c 3 61 215 xff0c 4 61 2145 xff0c 那么5 61 xff1f 答案 xff1a 5 61 1 哎 xff0c 这个题出的 xff0c 没反应过
  • 村子里有50个人,每人有一条狗,在这50条狗中有病狗(这种病不传染),于是人们要找出病狗。

    xff29 xff22 xff2d 公司向来以高素质人才作为企业持续竞争力的保证 进入 xff29 xff22 xff2d 公司是差不多每个 xff29 xff34 人的梦想 下面这条 xff29 xff22 xff2d 公司的面试题 xf
  • 删除单向链表中的某一个节点

    已知一个单向链表的表头head xff0c 写出一个删除某一个节点的算法 xff0c 要求先找到此节点 xff0c 然后删除 include lt iostream gt using namespace std typedef struct
  • 多段图的最短路径问题-----动态规划法

    对多段图 xff0c 求最短路径 xff0c 如图 xff1a 对其使用动态规划法 xff1a 阶段 xff1a 将图中的顶点划分5个阶段 xff0c k 状态 xff1a 每个阶段有几种供选择的点s 决策 xff1a 当前状态应在前一个状
  • Android 文件存储 和 权限管理

    转载请标明出处 xff1a xff1a http blog csdn net huaiyiheyuan article details 52473984 android SD卡主要有两种存储方式 Internal External Stor