Android数据存储之文件存储

原创 2016年08月31日 16:53:55

内部存储和外部存储的概念

所有Android设备都有两个存储:”内部”和”外部”存储。早期Android设备的内部存储指的是内置的不可移除的内存,外部存储指的是sd card,也就是可移除存储。后来一些设备将内置存储划分为”内部”和”外部”分区,所以即便没有sd card这样的可移除存储,也始终有两个存储空间,并且无论外部存储是否可移除,API行为均一致。

内外部存储的实际路径

那么现在我们可以把存储分为三类:内部存储、不可移除的外部存储(内置内存划分的)、可移除外部存储(sd card)。
而外部存储保存的文件又分为两类:公有文件,私有文件。

内部存储目录:由 Context.getFilesDir() 获得,路径为 /data/data/com.example.capturephotodemo/files

内部存储缓存目录:由 Context.getCacheDir() 获得,路径为 /data/data/com.example.capturephotodemo/cache

外部存储私有文件存储目录:Context.getExternalFilesDir(String type)获得,传入 null 就是获取根目录 /storage/emulated/0/Android/data/com.example.capturephotodemo/files。如果传入 Environment.DIRECTORY_PICTURES,路径为 /storage/emulated/0/Android/data/com.example.capturephotodemo/files/Pictures

外部存储私公有文件目录(这里是由Environment获取,不是Context):Environment.getExternalStorageDirectory()获取是公有文件存储的根目录 /storage/emulated/0。Environment.getExternalStoragePublicDirectory(String type) 如果传入Environment.DIRECTORY_PICTURES,目录为/storage/emulated/0/Pictures

内外部存储区别

内部存储:始终可用,默认情况下只有当前应用可访问,用户卸载应用时,内部存储文件全部删除
外部存储:分为可移除和不可移除的,全局可读,不过当用户卸载应用时,只有私有文件(Context.getExternalFilesDir(String type),如下载的音频)会被删除,公有文件(Environment.getExternalStorageDirectory()或Environment.getExternalStoragePublicDirectory(String type),如拍照)不会被删除。

权限

写权限包含默认包含读的权限,不过一般为了版本兼容,必要时候还是加上读权限

    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="18" /> 

保存文件到内部存储

先看下效果,点击Button后,会在ImageView中加载Internal Storage中的保存的图片,然后会把这个图片发送出去。
这里写图片描述

先创建图片

private void createInternalFile() {
    //在内部存储创建 images/ 目录
    File imagesDir = new File(getFilesDir(), shareDir);
    //在images/目录下创建文件
    internalFile = new File(imagesDir, "launcher.png");
    //打开文件的输出流
    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream(internalFile);
        //获取bitmap对象
        Bitmap launcherIcon = BitmapFactory.decodeResource(getResources(), R.mipmap.star);
        //把bitmap对象压缩到输出流中
        boolean isCompressed = launcherIcon.compress(Bitmap.CompressFormat.PNG, 100, fos);
        if (!isCompressed) {
            Log.e("david", "Failed to compress");
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } finally {
        if (fos != null) {
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

发送并加载

public void shareInternalFile(View view) {
    createInternalFile();

    //把文件以uri形式分享出去
    Uri uri = FileProvider.getUriForFile(this, AUTHORITY, internalFile);
    Intent shareIntent = new Intent(Intent.ACTION_SEND);
    shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
    shareIntent.setType("image/png");
    startActivity(Intent.createChooser(shareIntent,"Send Image"));

    //加载内部存储的文件,显示到ImageView中
    Bitmap bitmap = BitmapFactory.decodeFile(internalFile.getAbsolutePath());
    mImageView.setImageBitmap(bitmap);
}

既然内部存储只有本应用可以访问,那么接收图片的应用为何有权限访问这个图片。因为这里用了FileProvider,它赋予了Uri的临时权限

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.ckt.savingfile.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths"/>
</provider>

实际情况中,可能我要发送多张图片

ArrayList<Uri> imageUris = new ArrayList<Uri>();
imageUris.add(imageUri1); // Add your image URIs here
imageUris.add(imageUri2);

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris);
shareIntent.setType("image/*");
startActivity(Intent.createChooser(shareIntent, "Share images to.."));

保存文件到外部存储

因为外部存储可能不存在,所以总是要先检查存在性。

/**
 * 检查外部存储是否挂载
 */
private boolean isExternalStorageAvailable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}

然后写入文件

private void createExternalFile() {
    if (isExternalStorageAvailable()) {
        //创建外部存储的私有文件目录
        File picDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        //在私有文件目录下创建文件
        externalFile = new File(picDir, "panda.jpg");
        //打开文件的输出流
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(externalFile);
            //获取bitmap对象
            Bitmap launcherIcon = BitmapFactory.decodeResource(getResources(), R.mipmap.panda);
            //把bitmap对象压缩到输出流中
            boolean isCompressed = launcherIcon.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            if (!isCompressed) {
                Log.e("david", "Failed to compress");
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

最后发送出去

    public void shareInternalFile(View view) {
        createExternalFile();
        Uri uri = Uri.fromFile(externalFile);
        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.putExtra(Intent.EXTRA_STREAM, uri);
        intent.setType("image/*");
        startActivity(intent);
    }

这里我并没有通过FileProvier生成Uri,因为外部存储的文件其它应用都是可以访问的,所以我们只需要知道这个文件的路径就行,这里我们用一个Uri告知其它应用这个文件的路径。
最后我还是上一个图,让大家看到效果,并用图的最后,我们会看到内部私有文件到底存放在哪里

这里写图片描述

删除文件

当用户卸载app时候,系统会删除以下各项:
1. 内部存储中的所以文件
2. 用getExternalFilesDir()保存的外部存储的文件
但是,我们还是要自己定期删除用 getCacheDir() 创建的缓存文件。

删除文件最直接的方法就是 myFile.delete(),如果文件保存在内部存储中,可以用Context.deleteFile(fileName)

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

android数据存储与访问之使用普通文件

很多时候我们的软件需要对处理后的数据进行存储或再次访问。Android为数据存储提供了如下几种方式: 文件 SharedPreferences(参数) SQLite数据库 内容提供者(Cont...

Android(二)数据存储和访问 之文件 1

今日重点内容是Adnroid的数据存储和访问。Android的数据存储有五种:文件SharedPreferences、SQLite数据库、内容提供者(Content provider)、网络。Andr...
  • ictch
  • ictch
  • 2011-01-10 21:06
  • 449

从零开始学android<数据存储(1)SharedPreferences属性文件.三十五.>

在android中有五种保存数据的方法,分别是 Shared Preferences Store private primitive data in key-value pairs. 对应属性的键值对...

Android App开发基础篇—数据存储(SP和文件)

Android中的数据存储技术     前言:Android中提供了多种数据存储技术来保存永久性应用数据,以便开发者能够根据需求选择合适的数据存储方案。例如:数据是应用的私有数据,还是可供其他应用(和...

Android—文件进行数据存储(四中操作模式)

简介:     Android进行文件存储主要有四种操作模式     1》Context.MODE_PRIVATE:默认模式,私有模式只能被本身应用进行访问,其它应用不能进行访问,本身应用访问文件,如...

Android中使用SharedPreferences进行数据存储及文件操作模式

因为SharedPreferences背后是使用xml文件保存数据,getSharedPreferences(name,mode)方法的第一个参数用于指定该文件的名称,名称不用带后缀,后缀会由Andr...

Android之使用文件进行数据存储

首先给大家介绍使用文件如何对数据进行存储,Activity提供了openFileOutput()方法可以用于把数据输出到文件中,具体的实现过程与在J2SE环境中保存数据到文件中是一样的。 ...
  • w_l_j
  • w_l_j
  • 2012-05-22 15:35
  • 679
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)