精华内容
下载资源
问答
  • Android系统数据存储分为内部存储和外部存储,内部存储是手机系统自带的存储,一般空间都不大,外部存储一般是SD卡的存储,空间一般都比较大。一般我们会把存储内容放在外部存储空间里。在使用过程需要注意事项: 先...
  • 外部存储 sharedpreferences:link. 本文主要介绍外部存储的相关知识。 存储路径:/storage/emulated/0 ———————————————————————————————————————— 1、向SD卡写数据 步骤:...
  • 上面不难看出,在manifest>中直接添加的读取和写入的权限 安卓6.0以上的版本怎么办,就需要动态申请权限了 下面添加了一个显示跳转与隐式跳转的两种方式,是activity组件的知识,不必在意在此处 ...
  • 创建与删除本地文件,对手机的外部存储进行操作
  • File存储(内部存储) 一旦程序在设备安装后,data/data/包名/ 即为内部存储空间,对外保密。 Context提供了2个方法来打开输入、输出流 FileInputStream openFileInput(String name) FileOutputStream ...
  • 今天小编就为大家分享一篇解决android6.0以上不能读取外部存储权限的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 一般的Android App能读取的存储空间主要有三种: app自己的私有目录,也就是/data/data/《app 目录》。 读写这个目录不需要单独的权限。每个app只能读写自己的目录,而不能读写其他app的目录。 Android通过Seandroid...
  • 不一样的手机,外部存储在手机中的位置可能是不一样的,有些手机是在 storage 文件夹下,有些手机是在 mnt 文件夹下,我们通常用来表示外部存储的话,都会找一个叫做 sdcard 的文件夹,在 mnt 下

    一、前言

    Android 本地数据存储之 SharePreferences 存储 中,我们已经讲了 Sp 是如何保存数据的,并且也提供了一个 Sp 的工具类,今天我们来讲解一下 Android 中本地存储数据的另外一种方式——文件存储,文件存储又分为外部存储和内部存储。

    二、外部存储

    2.1、概述

    不一样的手机,外部存储在手机中的位置可能是不一样的,有些手机是在 storage 文件夹下,有些手机是在 mnt 文件夹下,我们通常用来表示外部存储的话,都会找一个叫做 sdcard 的文件夹,在 mnt 下面我们可以直接找到这个文件夹,但是在 storage 下面会首先看到 emulated 的文件夹,然后 emulated 下面还有一个叫做 0 的文件夹,这个 0 的文件夹才是真实的外部存储的目录,通常这个目录是无法打开的,因为在这一类型的设备中间会形成一个映射,而这个映射文件夹的名字就叫做 sdcard,所以这种情况下我们就会直接去找这个 sdcard 文件夹。

    2.2、获取外部存储位置(SDK 29 之前)

    在 Android SDK 29 之前,想要查看外部存储的真实目录只需要调用 Environment.getExternalStorageDirectory() 就可以了,但是在 Android SDK 29 之后,这个方法就被废弃了,如下所示,在 SDK 为29 的情况下,getExternalStorageDirectory() 这个方法显示的就是被废弃了。

    2.3、获取外部存储私有目录(SDK 29)

    之所以 getExternalStorageDirectory() 这个方法被废弃的原因就是,保存在这个目录下的数据即时应用被卸载了,这些数据依然会存在外部存储里面,而这些数据是很有可能成为垃圾数据的,这样对用户是非常不友好的,所以呢谷歌提供了 getExternalFilesDir()getExternalCacheDir() 这两个方法来获取外部存储的私有目录,前一个存放需要长时间保存的数据,后一个就存一些临时数据,它们位于 SDCard/Android/data/包名/files(cache) 下面。我们用一个简单的例子来演示一下。

    2.4、外部存储实例演示

    这个例子也很简单,就是往这个目录下存一些数据再读出来,具体效果如下所示:

    完整代码如下所示:

    public class ExternalActivity extends AppCompatActivity {
    
        private EditText infoEdt;
        private TextView txt;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_external);
    
            infoEdt = findViewById(R.id.info_edt);
            txt = findViewById(R.id.textView);
        }
    
        public void operate(View v) {
            String path = getExternalFilesDir(null).getAbsolutePath() + "/test.txt";
            Log.e("ExternalActivityTag", path);
            switch (v.getId()) {
                case R.id.save_btn:
                    File file =  getExternalFilesDir(null);
                    try {
                        if (!file.exists()) {
                            file.createNewFile();
                        }
                        FileOutputStream fos = new FileOutputStream(path, true);
                        String str = infoEdt.getText().toString();
                        fos.write(str.getBytes());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    break;
                case R.id.read_btn:
                    try {
                        FileInputStream fis = new FileInputStream(path);
                        byte[] b = new byte[1024];
                        int len = fis.read(b);
                        String str2 = new String(b, 0, len);
                        txt.setText(str2);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
            }
        }
    }
    

    打印出来的具体位置如下所示(结合概述所讲内容可以知道这个目录我们可以在映射目录 sdcard 下面找到):

    2.5、注意

    利用 getExternalFilesDir()getExternalCacheDir() 这两个方法来获取外部存储的私有目录是不需要任何权限的,但是如果用 Environment.getExternalStorageDirectory() 是需要外部存储的读写权限的,而且在 Android 6.0 之后,只在清单文件中声明是不够的,还需要运行时申请,即动态权限。

    三、内部存储

    3.1、概述

    首先,内部存储不是内存。在 Android studio 中,内部存储可以通过 Device File Explorer 找到,文件夹叫做 data,如果你想将文件存储于内部存储中,那么文件默认只能被你的应用访问到,且一个应用所创建的所有文件都在和应用包名相同的目录下。也就是说应用创建于内部存储的文件,与这个应用是关联起来的。当一个应用卸载之后,内部存储中的这些文件也被删除。

    3.2、获取内部存储位置

    我们可以通过 getFileDir()getCacheDir() 这两个方法来获取内部存储的目录,它们位于 data/data/包名/files(cache) 下面,我们同样用外部存储的实例来演示一下,只是把数据存到内部存储中,因为实例效果是完全一样的,就不演示了,直接看代码(具体代码写法上跟外部存储有点不一样):

    public class InternalActivity extends AppCompatActivity {
    
        private EditText edt;
        private TextView txt;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_internal);
    
            edt = findViewById(R.id.editText);
            txt = findViewById(R.id.textView);
        }
    
        public void operate(View v) {
            File file = new File(getFilesDir(), "getFilesDir.txt");
            switch (v.getId()) {
                case R.id.save_btn:
                    try {
                        if (!file.exists()) {
                            file.createNewFile();
                        }
                        FileOutputStream fos = new FileOutputStream(file);
                        fos.write(edt.getText().toString().getBytes());
                        fos.close();
                    } catch (Exception e) {
    
                    }
                    break;
                case R.id.read_btn:
                    try {
                        FileInputStream fis = new FileInputStream(file);
                        byte[] b = new byte[1024];
                        int len = fis.read(b);
                        String str2 = new String(b, 0, len);
                        txt.setText(str2);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
            }
        }
    }
    

    四、外部存储与内部存储对比

    这里对比的是私有目录,如下表格所示:

    外部存储内部存储
    目录获取方式getExternalFilesDir()getFilesDir()
    位置SDCard/Android/data/包名/files/data/data/包名/files

    getExternalCacheDir()getCacheDir() 同理。

    五、小结

    内部存储与外部存储的知识点我们都已经讲完了,那我们在存储数据的时候应该怎么用呢?一般来说我们不会去用Environment.getExternalStorageDirectory() 这个目录的,因为新的手机基本上都是基于 SDK 29 的,所以,如果我们的内存卡不存在或者被移除的情况下,我们就采用内部存储,如果内存卡存在或者手机自带内存卡的情况下我们就把数据存到外部存储的私有目录下。

    最后

    小编在这将自己收集的一份《Android核心知识汇总》分享给大家,希望能对大家有所帮助。请点击GitHub获取。 喜欢本文的话,不妨顺手给我点个小赞、评论区留言或者转发支持一下呗~

    展开全文
  • Android开发实现内部和外部存储文件

    千次阅读 2021-04-05 14:15:13
    Android开发实现内部和外部存储文件 效果图: activity_main.xml代码: <?xml version="1.0" encoding="utf-8"?> ...文件名字:" android:textSize="35dp"></TextView> ...

    Android开发实现内部和外部存储文件

    效果图:
    在这里插入图片描述
    activity_main.xml代码:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp"
                android:orientation="horizontal">
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="文件名字:"
                    android:textSize="35dp"></TextView>
    
                <EditText
                    android:id="@+id/et_name"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textSize="35dp"></EditText>
            </LinearLayout>
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp">
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="文件内容:"
                    android:textSize="35dp"></TextView>
    
                <EditText
                    android:id="@+id/et_content"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textSize="35dp"></EditText>
            </LinearLayout>
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp">
                <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="20dp"
                    android:layout_weight="1"
                    android:text="存入INTERNAL文件"
                    android:onClick="Save_in"></Button>
                <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="20dp"
                    android:layout_weight="1"
                    android:text="存入EXTERNAL文件"
                    android:onClick="Save_ex"></Button>
            </LinearLayout>
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp">
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Internal文件内容:"
                    android:textSize="30dp">
    
                </TextView>
                <TextView
                    android:id="@+id/incontent"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="30dp">
                </TextView>
            </LinearLayout>
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp">
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="External文件内容:"
                    android:textSize="30dp">
    
                </TextView>
                <TextView
                    android:id="@+id/excontent"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="30dp">
                </TextView>
            </LinearLayout>
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp">
                <Button
                    android:layout_weight="1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="20dp"
                    android:text="从INTERNAL取文件"
                    android:onClick="Out_in"></Button>
                <Button
                    android:layout_weight="1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="20dp"
                    android:text="从EXTERNAL取文件"
                    android:onClick="Out_ex"></Button>
            </LinearLayout>
        </LinearLayout>
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    MainActivity.java代码:

    package com.henu.saveinfile;
    
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.core.app.ActivityCompat;
    
    import android.Manifest;
    import android.content.Context;
    import android.content.pm.PackageManager;
    import android.os.Bundle;
    import android.os.Environment;
    import android.util.Log;
    import android.view.View;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.nio.file.FileVisitOption;
    
    public class MainActivity extends AppCompatActivity {
        private EditText et_name;
        private EditText et_content;
        private TextView tv_in_content;
        private TextView tv_ex_content;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            et_name = (EditText) findViewById(R.id.et_name);
            et_content = (EditText) findViewById(R.id.et_content);
            tv_in_content = (TextView) findViewById(R.id.incontent);
            tv_ex_content = (TextView) findViewById(R.id.excontent);
    
            //弹出请求获取存储权限的对话框
            int REQUEST_EXTERNAL_STORAGE = 1;
            String[] PERMISSIONS_STORAGE = {
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
            };
            int permission = ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
            if (permission != PackageManager.PERMISSION_GRANTED) {
                // We don't have permission so prompt the user
                ActivityCompat.requestPermissions(
                        MainActivity.this,
                        PERMISSIONS_STORAGE,
                        REQUEST_EXTERNAL_STORAGE
                );
            }
        }
    //存入内部存储区
        public void Save_in(View v) {
            FileOutputStream fos;
            try {
                fos = openFileOutput(et_name.getText().toString().trim(), Context.MODE_PRIVATE);
                fos.write(et_content.getText().toString().trim().getBytes());
                fos.close();
                Toast.makeText(this, "存入内部成功", Toast.LENGTH_SHORT).show();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    //从内部存储区取出文件并显示
        public void Out_in(View v) {
    
            FileInputStream fis;
            try {
                fis = openFileInput(et_name.getText().toString().trim());
                byte[] buffer = new byte[fis.available()];
                fis.read(buffer);
                tv_in_content.setText(getFilesDir() + "/" + et_name.getText().toString().trim() + ".txt" + ":" + new String(buffer));
                fis.close();
                Toast.makeText(this, "从内部读取成功", Toast.LENGTH_SHORT).show();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    //判断外部存储区是否可用
        public boolean isExternalStorageWritable() {
            if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
                return true;
            }
            return false;
        }
        //把文件存入外部存储区
        public void Save_ex(View v) {
            if (isExternalStorageWritable()) {
                File file = new File(Environment.getExternalStorageDirectory(), et_name.getText().toString().trim() + ".txt");
                FileOutputStream fos = null;
                try {
                    fos = new FileOutputStream(file);
                    fos.write(et_content.getText().toString().trim().getBytes());
                    Toast.makeText(this, "创建成功", Toast.LENGTH_SHORT).show();
                } catch (FileNotFoundException e) {
                    Toast.makeText(this, "请允许\"SavelInFile\"访问您设备上的照片、\n" +
                            "媒体内容和文件\n", Toast.LENGTH_LONG).show();
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                Toast.makeText(this, "外部存储区不可用", Toast.LENGTH_SHORT).show();
            }
    
        }
    //取出外部文件并显示出来
        public void Out_ex(View v) {
            File file = new File(Environment.getExternalStorageDirectory(), et_name.getText().toString().trim() + ".txt");
            FileInputStream fis;
            try {
                fis = new FileInputStream(file);
                byte[] buffer = new byte[fis.available()];
                fis.read(buffer);
                tv_ex_content.setText(Environment.getExternalStorageDirectory().getPath() + "/" + et_name.getText().toString().trim() + ".txt" + ":" + new String(buffer));
                Toast.makeText(this, "从外部读取成功", Toast.LENGTH_SHORT).show();
                fis.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    AndroidManifest.xml代码:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.henu.saveinfile">
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>//获取外部存储区写的权限(有了写的权限就能有了读的权限)
        <application
            android:requestLegacyExternalStorage="true"//停用分区存储
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/Theme.SaveInFile">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    

    遇到的问题:
    在外部存储文件时老是报错:FileNotFoundException,找不到文件。一般这样的问题有两个原因,一个是路径错误,一个是没有权限。我这是在创建文件时报错,所以原因是后者。但是我已经在AndroidManifest.xml文件中加入android:name=“android.permission.WRITE_EXTERNAL_STORAGE”/>获取到权限了,为什么还是报错。原来是安卓6版本以上,需要获取运行时权限。我又在加上对话框,在初次进入时弹出询问用户获取权限。在这里插入图片描述
    但是还是报错,FileNotFoundException。查了下原因,原来是Android 10之前,Android的文件存储现象就像个垃圾桶,但凡app取得了存储空间的读写权限WRITE_EXTERNAL_STORAGE,就可以肆意创建文件,难以管理。用户体验也特别差,打开文件管理器,会发现,想找个具体的文件根本无从下手。为了更好地管理自己的文件并减少混乱,加强隐私保护,Android Q开始引入了分区存储机制。外部存储空间被重新设计,按应用私有和公用共享划分。应用只能访问到自己私有空间,或者通过MediaStore API 和Storage Access Framework去访问共享的资源目录。
    关闭了分区存储:android:requestLegacyExternalStorage="true"就能和原来一样在外部存储区肆意创建文件了 哈哈
    在这里插入图片描述

    参考https://zhuanlan.zhihu.com/p/351713186
    参考https://blog.csdn.net/qxs965266509/article/details/50606385?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161760026116780265414814%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=161760026116780265414814&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-1-50606385.pc_search_result_no_baidu_js&utm_term=Android+filenotfoundexception

    展开全文
  • 细说Android的内部存储和外部存储

    千次阅读 2019-02-19 21:32:06
    无论哪种存储,都会涉及到手机的存储空间,而其中比较绕人的就是Android手机的内部存储和外部存储了,这两天花了点时间总结了一番,这里写成博客权当记录。 内部存储 概念:注意内部存储不是内存,它是手机中的一...

    数据存储,是我们在Android开发中经常遇到的场景,数据的存储方式也有多种方式,例如文件存储、数据库存储、网路存储等等。无论哪种存储,都会涉及到手机的存储空间,而其中比较绕人的就是Android手机的内部存储和外部存储了,这两天花了点时间总结了一番,这里写成博客权当记录。

    内部存储

    概念:注意内部存储不是内存,它是手机中的一块存储区域,是系统本身和系统应用程序主要的数据存储所在地。手机的内部存储通常不会很大,一旦手机的内部存储容量被用完,可能会出现手机无法使用的情形。对于开发者来说,不宜存储视频等大文件,适和存储一些小文件。比如我们常常用的SharedPreferences和SQLite数据库都是存储在内部存储中的,不会占用太大的空间。其主要的api如下:

            //获取手机内部存储空间的绝对路径。
            Environment.getDataDirectory().getAbsolutePath();
    
            //获取当前应用包名文件夹下的files文件夹
            getFilesDir().getAbsolutePath();
            
            //获取当前应用包名文件夹下cache文件夹
            getCacheDir().getAbsolutePath();
    
            //在内部存储空间内创建(或打开现有的)目录。
            getDir(String name, MODE_PRIVATE);
    

    这么看太苍白,截一张我手机的图解释下:


    在这里插入图片描述

    通常我们手机安装了一个app,都会在data/data目录下新增一个我们应用包名的文件夹,而数据库,SharedPreferences文件都是存放在这个文件夹中,getFilesDir是用来获取这个文件夹下的files文件夹路径(如果存在的话),getCacheDir则是获取cache文件夹路径的。至于Environment.getDataDirectory()获取到的路径是这样的:


    在这里插入图片描述

    就是最外层的/data目录,也就是我们所说的内部存储所在的根目录。内部存储没什么好说的,对于一个app来说,无非就是data/data目录下应用包名所在的文件夹。这里不禁想起来一个问题,似乎我们买手机,手机参数从来都没告诉我们内部存储有多大,我们常说的64g,128g可能只是外部存储或者是内部存储和外部存储的总和,无论你怎么搜索,都不会有关于一部手机内部存储的信息的,那我们如何获取一部手机的内部存储大小呢?作为Android程序员,当然是有固定的api给我们用啦,看代码:

     public static long getTotalInternalMemorySize() {
            File path = Environment.getDataDirectory();
            
            StatFs stat = new StatFs(path.getPath());
            
            //获取内部存储中每个区块的存储大小。
            long blockSize = stat.getBlockSize();
            
            //获取内部存储中所有的区块数量。
            long totalBlocks = stat.getBlockCount();
            
            //返回内部存储空间的总大小。
            return totalBlocks * blockSize;
        }
    

    我的手机是小米6 64g版本,看下我的手机内部存储空间有多大:


    在这里插入图片描述

    当然这个是字节数。55425040384/1000/1000/1000得到的GB大小,值为52.8个GB。有人会问了,出去系统占用的内存,这不是和手机宣传的64g差不多么?不应该是SD卡,属于外部存储么?当然,现在的手机大部分都不再支持外接SD卡了,内部存储和外部存储都是在一起的,但是概念上做了区分,内部存储和外部存储是一块存储介质上的不同区域。而以前外接SD卡则是在硬件上做了区分(Android 4.4以前),手机自带的存储卡就是内部存储,外接的SD卡就是外部存储。其实本质上没有区别,只是现在的手机都一体化了,再暴力拆解不符合现在的美学原理,也可以说是时代进化的产物吧~

    外部存储

    说完了内部存储,咱们再来聊一聊外部存储。外部存储,首先可以明确一点的是,如果现在的手机还能外接SD卡,那么外接的SD卡一定是外部存储。但是一部手机可能自己本身就区分了内部存储和外部存储,这个时候又外接一个SD卡,不是有两个外部存储了么?是的,理论上是可以有两个外部存储。存储方式都一样,关键是如何去区分这两个外部存储,看代码:

    File[] files;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        files = getExternalFilesDirs(Environment.MEDIA_MOUNTED);
        for(File file:files){
            Log.e("main",file);
        }
    }
    

    getExternalFilesDirs可以获取多个外部存储空间,返回一个数组。这样就可以得到手机自身所带的外部存储和外接SD卡所定义的外部存储了。我这里没有可以插SD卡的手机,大家如果有可以插SD卡的手机,可以自行试一试。外部存储常用的api:

            //获取手机外部存储的路径:/storage/emulated/0
            Environment.getExternalStorageDirectory().getAbsolutePath();
    
            //获取某种特定内容,如视频、照片、警报、铃声、音乐所在的路径,传入的参数是内容类型。  /storage/emulated/0/DCIM
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM ).getAbsolutePath();
    
            //获取某个应用在外部存储中的files路径  /storage/emulated/0/Android/data/demo.suning.com.demo/files
            getExternalFilesDir("").getAbsolutePath();
    
            //获取某个应用在外部存储中的cache路径 /storage/emulated/0/Android/data/demo.suning.com.demo/cache
            getExternalCacheDir().getAbsolutePath();
    

    获取特定内容的类型有以下几种:

    DIRECTORY_ALARMS //警报的铃声
    DIRECTORY_DCIM //相机拍摄的图片和视频保存的位置
    DIRECTORY_DOWNLOADS //下载文件保存的位置
    DIRECTORY_MOVIES //电影保存的位置, 比如 通过google play下载的电影
    DIRECTORY_MUSIC //音乐保存的位置
    DIRECTORY_NOTIFICATIONS //通知音保存的位置
    DIRECTORY_PICTURES //下载的图片保存的位置
    DIRECTORY_PODCASTS //用于保存podcast(博客)的音频文件
    DIRECTORY_RINGTONES //保存铃声的位置
    

    当然还有其他的一些api,这里就不一一列举了,google爸爸起名字还是比较见名思义的,看api名称大体可以猜到是干嘛用的。

    问:getExternalFilesDir和刚刚内部存储中的getFilesDir有什么区别呢和共同点呢?
    区别:一个时在外部存储中,一个是在内部存储中。
    相同点:路径中都带有当前app的包名,表明是当前app的专属文件。当app卸载或手动清除某个应用数据,它们也会被清除掉,其实它们的作用都是为了管理app的数据,让每一个app都有一个自己专属的文件夹,这样方便于系统管理,避免因为文件随意存储导致的存储空间混乱;另外就是为了当卸载应用时会把这些文件删除,不至于应用不在了,却还留下一堆垃圾文件。

    问:既然内部存储和外部存储都会有当前app的专属文件夹,那我们应该优先用哪个呢?
    答:理论上是优先使用外部存储,防止手机因为内部存储耗尽导致手机无法使用。当然一些无关紧要的小文件也可以存储在内部存储中,诸如数据库,SharedPreferences,大文件优先于外部存储。

    当然使用之前可能需要做一下判断,是否有外部存储,如果没有,则使用内部存储,有的话才使用外部存储:

    public static String getFilePath(Context context, String dir) {
            String directoryPath = "";
            if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {//判断外部存储是否可用 
                directoryPath = context.getExternalFilesDir(dir).getAbsolutePath();
            } else {//没外部存储就使用内部存储  
                directoryPath = context.getFilesDir() + File.separator + dir;
            }
            File file = new File(directoryPath);
            if (!file.exists()) {//判断文件目录是否存在
                file.mkdirs();
            }
            return directoryPath;
        }
    

    关于内部存储和外部存储的关系,我想引用另一篇博客的一张图:


    在这里插入图片描述

    参考:https://blog.csdn.net/u010937230/article/details/73303034,这里盗的图,如果作者看到了还希望作者多多包涵~

    至于Android每个版本SD卡的路径都不一样的问题,这里就不去分析了,管他google怎么玩,反正我们有api,只要api不变,我们就可以玩得转。所谓它自皮来它自恶,我自一口真气足。不过有时间和有兴趣的小伙伴可以研究研究哈,毕竟钻研是一种学习精神,是一种学习态度。而我很懒不想钻研~


    在这里插入图片描述

    展开全文
  • 文件数据储存外部储存

    万次阅读 多人点赞 2019-03-01 23:39:06
    Android官方Api:每个兼容 Android 的设备都支持可用于保存文件的共享“外部存储”。 该存储可能是可移除的存储介质(例如 SD 卡)或内部(不可移除)存储。 保存到外部存储的文件是全局可读取文件,而且,在计算机...

    Android官方Api:每个兼容 Android 的设备都支持可用于保存文件的共享“外部存储”。 该存储可能是可移除的存储介质(例如 SD 卡)或内部(不可移除)存储。 保存到外部存储的文件是全局可读取文件,而且,在计算机上启用 USB 大容量存储以传输文件后,可由用户修改这些文件。
    详解: 外部存储中的文件可以被用户或者其他应用程序读写的,其中有两种类型的文件。
    (1).公共文件public fies这类文件可被自由访问,当应用被卸载之后,文件仍然保留。比如相机类应用被卸载后,照片仍然存在。公共文件有9大类,均为系统创建的文件夹,详细如下:

    文件夹类型包括:

    • DCIM : 数字相机拍摄的照片
    • Music:用户音乐
    • Podcasts:音频/视频的剪辑片段
    • Ringtones:铃声
    • Alarms:闹钟的声音
    • Notification:通知
    • Pictures:所有的图片(不包括那些用照相机拍摄的照片)
    • Movies:所有的电影(不包括那些用摄像机拍摄的视频)和Download/其他下载的内容。

    使用外部存储数据需要在应用程序中设置访问SD卡的权限,在AndroidManifest.xml中添加权限

    <!-- 在sd卡中创建和删除文件权限-->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    <!-- 往sd卡写入数据权限-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <!-- 从sd卡读取数据权限-->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    

    首先判断是否存在可用的SD卡,Environment.getExternalStorageState()方法获取当前设备的状
    态,判断是否为Environment.MEDIA_MOUNTED状态。

      //判断SD卡是否存在
            if(Environment.getExternalStorageState().equals(
                    Environment.MEDIA_MOUNTED)){
                //记得最后要调用保存文件的方法实现保存
                Toast.makeText(getApplicationContext(),"sd卡存在",Toast.LENGTH_LONG).show();
            }else{
                Toast.makeText(getApplicationContext(), "sd卡不存在", Toast.LENGTH_LONG).show();
            }
    

    存储的文件路径使用Environment.getExternalStorageDirectory()方法获取当SD卡的根目录,进而访问相应的文件。创建公有文件的方法 :
    File file=new File(Environment.getExternalStorageDirectory(),“boreseven”);
    第二个参数为自己设置的名字

    (2).私有文件Private files在应用被卸载后,私有文件也会被删除,类似与内部储存。获得外部储存私有文件路径的方法Context.getExternalFilesDir(),如:
    如:File file = new File(this.getExternalFilesDir(Environment.DIRECTORY_PICTURES), “boreseven”);

    下面小提一下两个方法:
    1.保存文件到SD卡:

    //保存文件到SD卡
        public  void saveToSDCard(String filename,String content){
            File file=new File(Environment.getExternalStorageDirectory(),filename);
            try {
                FileOutputStream outputStream=new FileOutputStream(file);
                outputStream.write(content.getBytes());
                outputStream.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    

    2.读取SD卡文件:

     //读取SD卡文件
        public String readFileSdcard(String filename){
            String res="";
            try {
                FileInputStream myfin=new FileInputStream(filename);
                int length=myfin.available();
                byte [] buff=new byte[length];
                myfin.read(buff);
                res= new String(buff, "UTF-8");
    
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return  res;
        }
    

    拓展:点击按钮下载图片,可在系统相册中显示。
    记得要添加权限,代码如下:

    xml文件:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity"
        >
    
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            />
    
        <Button
            android:id="@+id/mybutton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true"
            android:text="保存" />
    
    </RelativeLayout>
    

    java文件:

    public class MainActivity extends Activity {
    
    
        private ImageView imageView;
        private Button mybutton;
        private Handler handler;
        private String URL="https://www.baidu.com/img/bd_logo1.png";//百度首页图片地址
    
    
        @Override
        protected void onCreate(final Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView();
            handler=new Handler(new Handler.Callback() {
                @Override
                public boolean handleMessage(Message msg) {
                    switch (msg.what){
                        case 1://成功
                            byte[]result= (byte[]) msg.obj;
                            final Bitmap bitmap=BitmapFactory.decodeByteArray(result,0,result.length);//利用BitmapFactory将数据转换成bitmap类型
                            imageView.setImageBitmap(bitmap);//加载图片
                           imageView.setOnLongClickListener(new View.OnLongClickListener() {
                               @Override
                               public boolean onLongClick(View v) {
                                   saveImageToGallery(MainActivity.this,bitmap);
                                   return false;
                               }
                           });
                    }
                    return false;
                }
            });
            OkHttpClient client=new OkHttpClient();//实例化
            final Request request = new Request.Builder().url(URL).build(); //传入图片网址,,URL为自己定义好的网址。
            client.newCall(request).enqueue(new Callback() {//实例化一个call的对象
                @Override
                public void onFailure(Call call, IOException e) {
    
                }
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    Message message=handler.obtainMessage();//声明一个传递信息的Message
                    if (response.isSuccessful()){//成功
                        Log.e("YF", "onResponse: "+"YES" );//一个log,可以不写
                        message.what=1;  //设置成功的指令为1
                        message.obj=response.body().bytes();//带入图片的数据
                        handler.sendMessage(message);//将指令和数据传出去
                    }else{//失败
                        Log.e("YF", "onResponse: "+"NO" );//一个log,可以不写
                        handler.sendEmptyMessage(0);//设置其他指令为零,然后进入handler
                    }
                }
            });
    
        }
        private void saveImageToGallery(Context context, Bitmap bmp) {
            // 首先保存图片
            File appDir = new File(Environment.getExternalStorageDirectory(),
                    "desheng");
    
            if (!appDir.exists()) {
                appDir.mkdir();
            }
            String fileName = System.currentTimeMillis() + ".jpg";
            File file = new File(appDir, fileName);
            try {
                FileOutputStream fos = new FileOutputStream(file);
                bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);
                fos.flush();
                fos.close();
            } catch (FileNotFoundException e) {
                Toast.makeText(context, "保存失败", Toast.LENGTH_SHORT).show();
                e.printStackTrace();
            } catch (IOException e) {
                Toast.makeText(context, "保存失败", Toast.LENGTH_SHORT).show();
                e.printStackTrace();
            }
    
            // 其次把文件插入到系统图库
            try {
                MediaStore.Images.Media.insertImage(context.getContentResolver(),
                        file.getAbsolutePath(), fileName, null);
                Toast.makeText(context, "保存成功", Toast.LENGTH_SHORT).show();
            } catch (FileNotFoundException e) {
                Toast.makeText(context, "保存失败", Toast.LENGTH_SHORT).show();
                e.printStackTrace();
            }
            // 最后通知图库更新
            context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
                    Uri.fromFile(new File(file.getPath()))));
        }
    
        private void initView() {
            imageView = (ImageView) findViewById(R.id.imageView);
            mybutton = (Button) findViewById(R.id.mybutton);
    
    
        }
    
    }
    

    记得加网络权限,图片是加载的百度首页图片!!!

    展开全文
  • 对于很多做Android开发的同学来说,可能认为文件存储很简单,调用一些诸如getFilesDir,getExternalStorageDirectory方法行了,但是虽然说它们会调用相应的方法来实现简单的数据存储。但是他们未必就搞懂了他的数据...
  • Android4.4 访问外部存储 在Android 4.4系统中,外置存储卡(SD卡)被称为二级外部存储设备(secondary storage),应用程序已无法往外置存储卡(SD卡)写入数据,并且WRITE_EXTERNAL_STORAGE只为设备上的主要外部存储...
  • 外部存储

    2017-04-08 09:28:58
    最容易混淆的是外部存储,如果说pc上也要区分出外部存储和内部存储的话,那么自带的硬盘算是内部存储,U盘或者移动硬盘算是外部存储,因此我们很容易带着这样的理解去看待安卓手机,认为机身固有存储是内部存储,而...
  • 解析Android内部存储、外部存储的区别

    万次阅读 多人点赞 2018-03-26 11:06:12
    可插拔的SD卡就是外部存储,其实这些理解都是有误的。这个知识点本人也重复看过好几次,但每次看完,过一段时间就会忘记,于是打算对这一知识点做个总结,也可当成学习笔记分享给大家。 主要分为下面两点进行分析:...
  • 将数据存储在app目录下,保存到外部存储设备,比如SD卡中,数据既可以公有,也可以私有,空间相对充足。 存储路径 公有:Environment.getExternalStorageDirectory() 私有:/Android/data/&amp;amp;amp;lt;...
  • 每个 Android 设备都支持共享的外部存储用来保存文件,它也是手机中的存储介质。保存在外部存储的文件都是全局可读的,而且在用户使用 USB 连接电脑后,可以修改这些文件。在 Android程序中,对外部存储的文件进行...
  • 彻底了解Android中的内部存储与外部存储 1.内部存储 data文件夹就是我们常说的内部存储,当我们打开data文件夹之后(没有root的手机是不能打开该文件夹),里面有两个文件夹值得我们关注,如下: 一个文件夹是app...
  • 该压缩包实现了app可以使用访问手机外部存储卡写权限,app可以通过申请外部存储卡写权限,在外部存储任意目录进行创建、删除/重命名/拷贝/剪切等功能。
  • 今天看了一篇文章。...1、Android4.4之前,手机的外部存储外部存储,类似电脑的内部存储个外部存储,是物理的,可以拆开。 4.4之后,手机自带的存储,从逻辑上分为内和外。此时,外部存储指的就是手机存
  • 外部存储适配方案3.1 Android 10.0 以下外部存储权限适配3.2 Android 11 及以上申请外部存储权限4.权限申请框架推荐4.1 [XXPermissions](https://github.com/getActivity/XXPermissions)4.1 [AndPermission](https:/
  • 彻底理解android中的内部存储与外部存储

    万次阅读 多人点赞 2015-12-12 10:05:34
    我们先来考虑这样一个问题:打开手机设置,选择应用管理,...在android开发中我们常常听到这样几个概念,内存,内部存储,外部存储,很多人常常将这三个东西搞混,那么我们今天就先来详细说说这三个东西是怎么回事?内
  • :floppy_disk: 用于外部存储的Nextcloud SharePoint后端 利用SharePoint后端,管理员可以将SharePoint文档库添加为Nextcloud中的文件夹。 这为用户提供了一种在他们找到其他文件的相同位置访问SharePoint数据的简便...
  • Android设备支持外部存储,比如SD卡等,保存在外部存储的数据具有全局可读性,可供在其他设备比如电脑上阅读,修改等。注意:使用外部存储需要获取外部存储的访问权限。本篇...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 693,636
精华内容 277,454
关键字:

外部存储