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数据存储(二)——使用文件和目录

文件的操作,都由Context(上下文)对象来衍生
  • dearday
  • dearday
  • 2013年08月14日 18:23
  • 1853

Android中数据存储方式一:文件形式

总结在Android中,一共有数据存储的5种方式。今天做一个笔记的整理。关于以文件形式如何来保存数据。 1.在activity_main.xml设计好布局     xmlns:tools="http...

初学Android,数据存储之读写SD卡文件(四十三)

读写SD卡上的文件有几个步骤1.调用Environment的getExternalStorageState() 方法判断手机上是否插入了SD卡,并且应用程序具有读写权限  如使用如下代码       ...
  • lee576
  • lee576
  • 2012年09月07日 13:56
  • 5040

初学Android,数据存储之SD卡文件浏览器(四十四)

用上一篇的知识,做一个SD卡的文件浏览器定义ListView的显示,Line.xml
  • lee576
  • lee576
  • 2012年09月07日 16:13
  • 2044

【Android】pull解析xml文件+将数据存储为xml格式,并保存在内存里

在解析中,常用到的还有一种解析就是pull去解析xml格式的文件。事实上android内部也是这样做的。今天这个demo是来自传智播客,可能技术已经被翻新了。 但是基础原理还是那样,希望基础学习者,能...

android(7)_数据存储与访问1_文件

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

android基础---使用文件进行数据存储

Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可以使用Context...

Android 数据存储详解(SharedPreferences, 文件, Sqlite, ContentProvider)

文章大部分内容来自 < < Android开发全程实录 > >, 希望大家能看看原书 SharedPreferences sharepreferences是Android中最轻量级的数据存储. 原...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android数据存储之文件存储
举报原因:
原因补充:

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