android 应用存储路径和目录小结

    一直对android系统各种的存储路径理的不是很清晰,只知道有手机内部存储和外部存储(一般为sd卡存储),今天把获取存储路径的API使用和区别详细看了一遍,在这里做个小结。

    从android 1.0系统开始,往sd卡的写入操作需要在清单文件添加WRITE_EXTERNAL_STORAGE权限。

    从android 4.1系统开始,读取sd的操作需要在清单文件添加WRITE_EXTERNAL_STORAGE权限。

    从android 4.4系统开始,应用可以管理在它外部存储上的特定包名目录,且不需要添加读写权限。外部存储上有一个Android文件夹,在其data目录下一组文件夹,分别是各个应用的包名。context.getExternalCacheDir()和context.getExternalFilesDir(String type)两个方法分别可以获取对应包名下的cache和files文件目录,getExternalFilesDir方法中需传入一个文件夹类型,当type为Environment.DIRECTORY_DCIM,则会在files目录下创建一个DCIM文件夹,传入其他参数会生成对应的文件夹。

    举个栗子,对包名为com.jaya.storagedemo的应用,getExternalCacheDir获取到的存储目录:/storage/emulated/0/Android/data/com.jaya.storagedemo/cache,getExternalFilesDir(Environment.DIRECTORY_DCIM)获取到的目录:/storage/emulated/0/Android/data/com.jaya.storagedemo/files/DCIM。

    当我们在开发中想在本地缓存文件时,可以保存在sd卡上的Android/data/包名/,这样的好处一是可以充分利用sd卡的存储空间,只要不超过sd卡存储大小即可,另外当我们卸载应用时Android/data下包名对应的文件夹会被系统删除。当然如果是重要的私密文件还是保存在手机内部存储中更为安全。

    获取存储路径的方法主要在Environment和Context两个类中,我们可以如下

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        Log.i("wenqiao", "Environment.getDataDirectory():" + Environment.getDataDirectory().getAbsolutePath());
        Log.i("wenqiao", "Environment.getExternalStorageDirectory():" + Environment.getExternalStorageDirectory().getAbsolutePath());
        Log.i("wenqiao", "Environment.getRootDirectory():" + Environment.getRootDirectory().getAbsolutePath());
        Log.i("wenqiao", "Environment.getDownloadCacheDirectory():" + Environment.getDownloadCacheDirectory().getAbsolutePath());
        /**
         * 这个方法接收一个参数,表明目录所放的文件的类型,传入的参数是Environment类中的DIRECTORY_XXX静态变量,比如DIRECTORY_DCIM等.
         * 注意:传入的类型参数不能是null,返回的目录路径有可能不存在,所以必须在使用之前确认一下,比如使用File.mkdirs创建该路径。
         */
        File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_ALARMS);
        if( !path.exists() ){
        	path.mkdirs();
        }
        /* /storage/emulated/0/Alarms */
        Log.i("wenqiao", "Environment.getExternalStoragePublicDirectory():" + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_ALARMS));
        
        /**
         * contextWrapper
         */
        Log.i("wenqiao", "getCacheDir():" + this.getCacheDir().getAbsolutePath());
        Log.i("wenqiao", "getFilesDir():" + this.getFilesDir().getAbsolutePath());
        Log.i("wenqiao", "getExternalCacheDir():" + this.getExternalCacheDir().getAbsolutePath());
        Log.i("wenqiao", "getExternalFilesDir():" + this.getExternalFilesDir(Environment.DIRECTORY_DCIM).getAbsolutePath());
        Log.i("wenqiao", "getPackageResourcePath():" + this.getPackageResourcePath());
        Log.i("wenqiao", "getDir():" + this.getDir("myfile", Context.MODE_PRIVATE));
        
    }

}

    在华为荣耀6上测试结果:

02-15 15:28:24.154: I/wenqiao(12821): Environment.getDataDirectory():/data
02-15 15:28:24.157: I/wenqiao(12821): Environment.getExternalStorageDirectory():/storage/emulated/0
02-15 15:28:24.157: I/wenqiao(12821): Environment.getRootDirectory():/system
02-15 15:28:24.157: I/wenqiao(12821): Environment.getDownloadCacheDirectory():/cache
02-15 15:28:24.168: I/wenqiao(12821): Environment.getExternalStoragePublicDirectory():/storage/emulated/0/Alarms
02-15 15:28:24.168: I/wenqiao(12821): getCacheDir():/data/user/0/com.jaya.storagedemo/cache
02-15 15:28:24.170: I/wenqiao(12821): getFilesDir():/data/user/0/com.jaya.storagedemo/files
02-15 15:28:24.172: I/wenqiao(12821): getExternalCacheDir():/storage/emulated/0/Android/data/com.jaya.storagedemo/cache
02-15 15:28:24.175: I/wenqiao(12821): getExternalFilesDir():/storage/emulated/0/Android/data/com.jaya.storagedemo/files/DCIM
02-15 15:28:24.175: I/wenqiao(12821): getPackageResourcePath():/data/app/com.jaya.storagedemo-2/base.apk
02-15 15:28:24.175: I/wenqiao(12821): getDir():/data/user/0/com.jaya.storagedemo/app_myfile

    其中,/data/user/0目录其实就是/data/data目录,可以看出,getCacheDir和getFilesDir获取的是手机内部存储中应用包名下的cache和files文件夹,getDir则获取应用包名的文件夹,其中传入的是要获取的文件夹名。

    此外,context还可以通过openFileInput(name)和openFileOutput(name, mode)获取FileInputStream和FileOutputStream,分别对应的是/data/user/0/包名/files/下的文件输入流和输出流。name是文件名,mode指定打开文件的模式,有以下几种:

    Context.MODE_PRIVATE                                         默认模式,表示文件只能被自身应用访问,如果向文件中写入数据,会覆盖之前数据

    Context.MODE_MODE_APPEND                          文件写入时,文件不存在则创建文件,存在则在已有的内容上追加

    Context.MODE_MODE_WORLD_READABLE   表示文件可以被其他应用读取

    Context.MODE_WORLD_WRITEABLE                表示文件可以被其他文件写入

当调用openFileOutput时,如果文件不存在,系统会创建文件。


   

    原文作者:疯狂的蚂蚁123
    原文地址: https://blog.csdn.net/wenqiaoqqq/article/details/55193264
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞