Android存储小结

转自:http://www.liaohuqiu.net/cn/posts/storage-in-android/

android系统自身自带有存储,另外也可以通过sd卡来扩充存储空间。前者好比pc中的硬盘,后者好移动硬盘。 前者空间较小,后者空间大,但后者不一定可用。 开发应用,处理本地数据存取时,可能会遇到这些问题:

  1. 需要判断sd卡是否可用: 占用过多机身内部存储,容易招致用户反感,优先将数据存放于sd卡;
  2. 应用数据存放路径,同其他应用应该保持一致,应用卸载时,清除数据:
    • 标新立异在sd卡根目录建一个目录,招致用户反感
    • 用户卸载应用后,残留目录或者数据在用户机器上,招致用户反感
  3. 需要判断两者的可用空间: sd卡存在时,可用空间反而小于机身内部存储,这时应该选用机身存储;
  4. 数据安全性,本应用数据不愿意被其他应用读写;
  5. 图片缓存等,不应该被扫描加入到用户相册等媒体库中去。
  1. 从API 19 / Andorid 4.4 / KITKAT开始,不再需要显式声明这两个权限,除非要读写其他应用的应用数据($appDataDir)

  2. 判断sd卡可用:
    /**
     * Check if the primary "external" storage device is available.
     *
     * @return
     */
    public static boolean hasSDCardMounted() {
        String state = Environment.getExternalStorageState();
        if (state != null && state.equals(Environment.MEDIA_MOUNTED)) {
            return true;
        } else {
            return false;
        }
    }
    

存储的用量情况

  • 根据系统用户不同,所能占用的存储空间大小也有不同

基本操作

  1. 使用外部存储,需要的权限,在AndoridManifest.xml中:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    
    
    • 在API level 9及其以上时,File对象的getFreeSpace()方法获取系统root用户可用空间;

      getUsableSpace()取非root用户可用空间

    • 当有多个存储可用时获取磁盘用量,根据当前系统情况选用合适的存储。
    • 根据系统存储用量,合理设定app所用的空间大小;运行时,也可做动态调整。
    • 在API level 9及其以上的系统,可直接调用File对象的相关方法,以下需自行计算:
      @TargetApi(VERSION_CODES.GINGERBREAD)
      public static long getUsableSpace(File path) {
          if (path == null) {
              return -1;
          }
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
              return path.getUsableSpace();
          } else {
              if (!path.exists()) {
                  return 0;
              } else {
                  final StatFs stats = new StatFs(path.getPath());
                  return (long) stats.getBlockSize() * (long) stats.getAvailableBlocks();
              }
          }
      }
      

    路径的规律

    一般地,通过Context 和 Environment相关的方法获取文件存取的路径。

    通过这两个类可获取各种路径,如图:

        ($rootDir)
    +- /data                -> Environment.getDataDirectory()
    |   |
    |   |   ($appDataDir)
    |   +- data/com.srain.cube.sample
    |       |
    |       |   ($filesDir)
    |       +- files            -> Context.getFilesDir() / Context.getFileStreamPath("")
    |       |       |
    |       |       +- file1    -> Context.getFileStreamPath("file1")
    |       |   ($cacheDir)
    |       +- cache            -> Context.getCacheDir()
    |       |
    |       +- app_$name        ->(Context.getDir(String name, int mode)
    |
    |   ($rootDir)
    +- /storage/sdcard0     -> Environment.getExternalStorageDirectory()
        |                       / Environment.getExternalStoragePublicDirectory("")
        |
        +- dir1             -> Environment.getExternalStoragePublicDirectory("dir1")
        |
        |   ($appDataDir)
        +- Andorid/data/com.srain.cube.sample
            |
            |   ($filesDir)
            +- files        -> Context.getExternalFilesDir("")
            |   |
    |   +- file1    -> Context.getExternalFilesDir("file1")
            |   +- Music    -> Context.getExternalFilesDir(Environment.Music);
            |   +- Picture  -> ... Environment.Picture
            |   +- ...
            |
            |   ($cacheDir)
            +- cache        -> Context.getExternalCacheDir()
            |
            +- ???
    

    各个路径的特性

    下面介绍这些路径的特性以及使用中需要注意的细节:

    1. 根目录($rootDir):

      • 内部存储路径: /data, 通过Environment.getDataDirectory() 获取
      • 外部存储路径: /storage/sdcard0 (也有类似 /mnt/ 这样的),通过Environment.getExternalStorageDirectory()获取
          • 示例:

            Environment.getDataDirectory():
                    /data
            
            Environment.getExternalStorageDirectory():
                    /storage/sdcard0
            

        1. 应用数据目录($appDataDir)
          • 内部储存: $appDataDir = $rootDir/data/$packageName,
          • 外部存储: $appDataDir = $rootDir/Andorid/data/$packageName

          在这些目录下的数据,在app卸载之后,会被系统删除,我们应将应用的数据放于这两个目录中。


        2. 外部存储中,公开的数据目录。 这些目录将不会随着应用的删除而被系统删除,请斟酌使用:
          Environment.getExternalStorageDirectory():
              /storage/sdcard0
          
          // 同 $rootDir
          Environment.getExternalStoragePublicDirectory(""):
              /storage/sdcard0
          
          Environment.getExternalStoragePublicDirectory("folder1"):
              /storage/sdcard0/folder1
          
          

          应用数据目录下的目录

          一般的在$appDataDir下,会有两个目录

          1. 数据缓存:$cacheDir = $appDataDir/cache:

            • 内部存储:Context.getCacheDir(), 机身内存不足时,文件会被删除
            • 外部存储:Context.getExternalCacheDir()

              外部存储没有实时监控,当空间不足时,文件不会实时被删除,可能返回空对象

              示例:

              Context.getCacheDir():
                      /data/data/com.srain.cube.sample/cache
              
              Context.getExternalCacheDir():
                      /storage/sdcard0/Android/data/com.srain.cube.sample/cache
              
          2. 文件目录 $filesDir = $appDataDir/files:
            • 内部存储:通过Context.getFilesDir() 获取

              Context.getFileStreamPath(String name)返回以name为文件名的文件对象,name为空,则返回$filesDir 本身

              示例:

              Context.getFilesDir():
                      /data/data/com.srain.cube.sample/files
              

          1. 相关代码:

            https://github.com/liaohuqiu/cube-sdk/blob/master/core/src/com/srain/cube/file/FileUtil.java

     
时间: 2024-08-15 11:27:09

Android存储小结的相关文章

Android存储子系统

这篇文章主要是分析Android存储向关联的一些模块,这个分析主要从大的工作流程和代码模块分析,没有对于没有分析到地方后续遇到后在详细分析.主要从以下几个模块分析 系统分区的挂载.外部分区挂载.Vold守候进程分.MountService的业务分析.Sdcard的详细分析.MTP模式分析和设备存储空间的监控机制. 系统分区挂载 Android是基于linux内核的系统,遵从linux的文件系统的挂载方式.在Android中在init进程负责挂载常用的system,data,cache等分区.In

Android 存储学习之在外部存储中读写文件

上节学习了如何在手机内部存储中读写文件,本节学习如何在手机的外部存储中读写文件.那就是如何在Sdcard中读写文件. 那我们还是用以前登录界面的例子举例说明,(登录界面请看上节Android 存储学习之在内部存储中读写文件) 先我们显示写的代码: 当点击确定并且自动登录的钩是选中的,则就会在sdcard文件夹写创建一个info.txt文件 public void login(View v) { String name = ed_nam.getText().toString(); String p

Android 存储学习之使用SharedPreference保存文件

上两节我们都是使用文本文件保存用户的信息,这明显是存在漏洞的.同时对文件中的内容不好管理.今天我们学习用SharedPreference保存.sharedPreference是专门保存一些比较零散的数据的. 我们还是用上节的例子分析,将用户的信息使用SharedPreference来保存. 注意:如果不知道是什么例子,请看Android 存储学习之在内部存储中读写文件 当点击确定按钮后,就会保存用户的信息: public void login(View v) { String name = ed

Android 存储(本地存储 SD卡存储 SharedPreference SQLite ContentProvider)

本文出自:http://blog.csdn.net/dt235201314/article/details/73176149 源码下载欢迎Star(updating):https://github.com/JinBoy23520/CoderToDeveloperByTCLer 一丶慨述 本周的学习内容是Android存储,要求:数据库Sqlite相关操作,常用的文件存取方式,以及实用场景学习,主要学习Sqlite,SD卡文件操作,SharedPreference 二丶效果演示:         

android fota小结

fota在make中有个关键的目标target-files-package,该目标生成一个用于做升级包的zip文件.升级包中的内容是定义好的文件列表. 同时有一个主要的脚本./build/tools/releasetools/ota_from_target_files,这个脚本可以根据不同的参数生成完整的升级包和差分升级包. 完整的升级包是采用覆盖的形式升级,差分升级则是采用patch的方式升级. 在update-binary中会有升级的函数定义,在update-script中会调用不同的函数进

Android存储的实现

在Android开发中,少不了对数据文件进行存取,需要掌握的Android存储功能技术如下: SharedPreferences:即用户偏好,可以通过这个类,存取一些简单的用户设置信息: 外部存储:即面向外部SD卡存取数据,可为数据做持久化保存: 内部存储:即面向移动设备内部自带存储区域的存取(并不是手机的CPU内存),同样可为数据做持久化保存,由于移动设备可能并未安装SD卡而且SD卡可能被随时取出,所以使用内部存储相对外部存储更加安全,但内部存储空间有限,远小于外部存储. SQLite数据库:

一篇文章搞懂android存储目录结构

前言 前两天因为开发一个app更新的功能,我将从服务器下载的apk文件放在了内部存储目录(测试手机为小米,路径为:data/user/0/packagename/files)下面,然后安装的时候一直安装不了,提示解析包出错.后来查询发现,安装apk是调用了PackageInstaller,没有相关权限,这个无法获取内部路径,所以会安装不了.借机也复习了一遍Android下面存储相关的知识点,特来总结一番. 存储分类 对于Android存储目录,我总结成一张思维导图,如果有需要原图的,请在我的公众

Android 存储目录

Android 存储目录总结:https://www.jianshu.com/p/9528329d4787 Android内.外存储 易混淆点剖析(/mnt/sdcard./storage/sdcard0./storage/emulated/0等区别): https://blog.csdn.net/ITermeng/article/details/79423035 原文地址:https://www.cnblogs.com/pomodoro/p/12660460.html

Android数据存储小结

巧妇难为无米之催,数据是一个程序的血肉,可是Android的数据存在哪里呢?Android提供了四种方法对数据进行存储:SQLite/ContentProvider/File/SharedPreferences 因为对数据的基本操作就是增删改查,那就从这四个方面对这四种方式进行总结: 一.SQLite 用到的类:SQLiteOpenHelper/SQLiteDatabase/Cursor SQLit支持:NULL/INTEGER/REAL/TEXT/BLOB getReadableDatabas