Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Android网络与数据存储——File存储(实现SD卡文件浏览器)

Android网络与数据存储——File存储(实现SD卡文件浏览器)

作者头像
trampcr
发布于 2018-09-28 07:44:17
发布于 2018-09-28 07:44:17
1.7K00
代码可运行
举报
文章被收录于专栏:7号代码7号代码
运行总次数:0
代码可运行

Java提供了一套完整的IO流体系,包括FileInputStream、FileOutPutStream等,通过这些IO流可以非常方便的访问磁盘上的文件内容。Android同样支持以这种方式来访问手机存储器上的文件。

一.存储在内部还是外部?


AndroidManifest.xml中manifest标签下有一个属性android:installLocation,用于指定应用程序安装在什么地方,该属性有三个可选值:

  • auto:程序可能被安装在外部存储器上,例如SD卡;但是默认会被安装到手机内存中。当手机内存为空时,程序将被安装到外部存储器上;当程序安装到手机上后,用户可以决定把程序放在外部存储器还是内存中。
  • internalOnly:默认值,程序只能被安装在内存中,如果内存为空,程序则不能成功被安装。
  • preferExternal:将程序安装在外部存储器,但是系统不保证程序一定会被安装到外部存储器上。当外部存储器不可以安装或为空时,程序将被安装到内存中。当程序使用了forward-locking机制时也将被安装到内存中,因为外部存储不支持此机制。程序安装后,用户可以自由切换程序应该在外部还是内部存储器上。

获取External存储的权限:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

二.openFileInput和openFileOutput


Context提供了两个方法打开应用程序的数据文件夹里的文件IO流:

  • FileInputStream openFileInput(String name):打开应用程序的数据文件夹下的name文件对应的输入流。
  • FileOutputStream openFileOutput(String name, int mode):打开应用程序的数据文件夹下的name文件对应的输出流。第二个参数指定打开文件的模式,该模式支持如下值:
    • MODE_PRIVATE:该文件只能被当前程序读写。
    • MODE_APPEND:以追加方式打开该文件,应用程序可以向该文件中追加内容。
    • MODE_WORLD_READABLE:该文件的内容可以被其他程序读取。
    • MODE_WORLD_WRITEABLE:该文件的内容可以由其他程序读写。

Context还提供了访问应用程序的数据文件夹的方法:

  • getDir(String name, int mode):在应用程序的数据文件夹下获取或创建name对应的子目录。
  • File getFileDir():获取应用程序的数据文件夹的绝对路径。
  • String[] fileList():返回应用程序的数据文件夹下的全部文件。
  • deleteFile(String):删除应用程序的数据文件夹下的指定文件。

三.读写SD卡上的文件


为了更好的存取应用程序的大文件数据,应用程序需要读写SD卡上的文件。

读写SD卡上文件的步骤:

  1. 调用Environment的getExternalStorageState()方法判断手机上是否插入了SD卡,并且应用程序具有读写SD卡的权限。使用如下代码:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//如果返回true,说明已插入SD卡,且应用程序具有读写SD卡的能力
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) 
  1. 调用Environment的getExternalStorageDirectory()方法来获取外部存储器,也就是SD卡的目录。
  2. 使用FileInputStream、FileOutputStream、FileReader或FileWriter读写SD卡里的文件。

为了读写SD卡上的数据,必须在AndroidManifest.xml中添加读写SD卡的权限:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!--SD卡中创建于删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!--SD卡中写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

四.操作assets、raw、res目录下文件


1.assets

资源文件夹,在main下与res同级,与res不同的是,该目录下的资源文件在打包apk时,会按原格式一并被打包。

有三种使用方法:

  • 在assets下放一个test.html文件,加载该文件:

webView.loadUrl("file:///android_asset/test.html");//假设已经创建了一个WebView实例```

  • 同样是读取test.html文件:

//这里的open只能打开文件,不能打开文件夹 InputStream inputStream = getResource().getAssets().open("test.html");

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- 读取列表、读取图片、读音乐,assets目录下包含一个images目录和一个mp3文件xuwei.mp3,images目录中包含一张图片dog.jpg:

String[] fileNames = getAssets().list("images/");//读列表

InputStream inputStream = getAssets().open("images/dog.jpg");//读图片 Bitmap bitmap = BitmapFactory.decodeStream(inputStream); imageView.setImageBitmap(bitmap);

AssetFileDescriptor assetFileDescriptor = getAssets().openFd("xuwei.mp3");//得到asset文件描述符 player.reset();//假设已创建一个MediaPlayer实例 player.setDataResource(assetFileDescriptor.getFileDescriptor(), assetFileDescriptor.getStartOffset(), assetFileDescriptor.getLength()); player.prepare(); player.start();

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
### 2.raw
资源文件夹,在res目录下,系统会为res目录下的所有资源生成相应的资源ID,raw中的文件也不例外,所以可以通过ID去访问res/raw目录中的任何文件,而assets目录中的文件就需要借助AssetManager去访问了。

assets目录允许下面有多级子目录,而res/raw下不允许存在目录结构。

读raw下的xuwei.mp3文件:

InputStream is = getResources().openRawResource(R.raw.xuwei);

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
### 3.res
res目录下的文件都可用getResources()方法读取。

# 五.SD卡文件浏览器
***
利用Java的File类开发一个SD卡文件浏览器,通过Environment.getExternalStorageDirectory()访问系统的SD卡目录,然后通过File的listFiles()方法获取指定目录下的全部文件和文件夹。

布局文件如下:

activity_main.xml
```xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context="com.trampcr.sdfileexplorer.MainActivity">

  <TextView
      android:id="@+id/path"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_alignParentTop="true"
      android:gravity="center_horizontal" />

  <ListView
      android:id="@+id/list"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_below="@id/path" />

  <Button
      android:id="@+id/parent"
      android:layout_width="38dp"
      android:layout_height="34dp"
      android:layout_alignParentBottom="true"
      android:layout_centerHorizontal="true"
      android:background="@drawable/home" />

</RelativeLayout>

布局文件包含一个TextView用于显示当前路径,ListView显示当前目录下文件和文件夹,Button用于返回上一级目录。

ListView中的子布局,包含一个ImageView和一个TextView:

line.xml:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:orientation="horizontal"
    android:gravity="center_vertical">

    <ImageView
        android:id="@+id/icon"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:background="@drawable/folder"/>

    <TextView
        android:id="@+id/file_name"
        android:layout_marginLeft="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="abc"/>

</LinearLayout>

主程序代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MainActivity extends AppCompatActivity {

    private ListView mListView;
    private TextView mTextView;
    //记录当前的父文件夹
    private File mCurrentParent;
    //记录当前路径下的所有文件的文件数组
    File[] mCurrentFiles;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mListView = (ListView) findViewById(R.id.list);
        mTextView = (TextView) findViewById(R.id.path);
        //获取系统的SD卡的目录
        File root = new File(String.valueOf(Environment.getExternalStorageDirectory()));
        //如果SD卡存在
        if (root.exists()){
            mCurrentParent = root;
            mCurrentFiles = root.listFiles();
            //使用当前目录下的全部文件、文件夹来填充ListView
            inflateListView(mCurrentFiles);
        }

        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (mCurrentFiles[position].isFile()){
                    return;
                }
                File[] tmp = mCurrentFiles[position].listFiles();
                if (tmp == null || tmp.length == 0){
                    Toast.makeText(MainActivity.this, "当前路径不可访问或该路径下没有文件", Toast.LENGTH_SHORT).show();
                }else {
                    mCurrentParent = mCurrentFiles[position];
                    mCurrentFiles = tmp;
                    inflateListView(mCurrentFiles);
                }
            }
        });
        //获取上一级目录的按钮
        Button parent = (Button) findViewById(R.id.parent);
        parent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    if (!mCurrentParent.getCanonicalFile().equals("/mnt/shell/emulated/0")){
                        mCurrentParent = mCurrentParent.getParentFile();
                        mCurrentFiles = mCurrentParent.listFiles();
                        inflateListView(mCurrentFiles);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }


    private void inflateListView(File[] files) {
        //创建一个List集合,List集合的元素是Map
        List<Map<String, Object>> listItems = new ArrayList<>();
        for (int i = 0; i < files.length; i++) {
            Map<String, Object> listItem = new HashMap<>();
            if (files[i].isDirectory()){
                listItem.put("icon", R.drawable.folder);
            }else {
                listItem.put("icon", R.drawable.file);
            }
            listItem.put("fileName", files[i].getName());
            listItems.add(listItem);
        }
        //创建一个SimpleAdapter
        SimpleAdapter simpleAdapter = new SimpleAdapter(this, listItems, R.layout.line, new String[]{"icon", "fileName"}, new int[]{R.id.icon, R.id.file_name});
        mListView.setAdapter(simpleAdapter);
        try {
            mTextView.setText("当前路径为:" + mCurrentParent.getCanonicalPath());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用File[]数组填充ListView,填充是程序会根据File[]数组里的数据元素代表的是文件还是文件夹来选择使用文件图标或文件夹图标。

运行上面程序,可以看到:

SDExplorer.png

六.扩展学习


  • android-sdk中的samples
  • github/google samples
  • developers
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016.08.14 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
9.Android-读写SD卡案例
2.读写SD卡时,需要给APP添加读写外部存储设备权限,修改AndroidManifest.xml,添加:
诺谦
2020/02/12
1.7K0
android 数据存储<一>----android短信发送器之文件的读写(手机+SD卡)
1.布局文件,android布局有相对布局,线性布局,绝对布局,表格布局,标签布局等,各个布局可以嵌套的。本文的布局文件就是线性布局的嵌套
用户4148957
2022/06/14
1.4K0
android 数据存储<一>----android短信发送器之文件的读写(手机+SD卡)
数据存储之文件存储
openFileOutput和openFileInput方法可以获得操作文件的OutputStream以及InputStream对象,而且可以通过流对象处理任何文件的数据,但是这两个方法同SharedPreferences一样,只能在手机内存卡的指定目录建立文件,因此在使用上仍然有一定的局限性。
小小工匠
2021/08/16
23.6K0
[android] 保存文件到手机内存
/*****************2016年5月4日 更新*******************************/
唯一Chat
2019/09/10
9840
Carson带你学Android:全面解析列表ListView与AdapterView
2. 在MainActivity上定义一个链表,将所要展示的数据以存放在里面 3. 构造ArrayAdapter对象,设置适配器 4. 将LsitView绑定到ArrayAdapter上 如下图:
Carson.Ho
2022/03/24
1.1K0
Carson带你学Android:全面解析列表ListView与AdapterView
Android中的资源
Android中的资源是一种非常优秀的、高效的解耦设计,通过使用资源文件,Android应用可以把各种字符串、图片、颜色、界面布局等交给XML文件管理,可以避免在Java代码中以硬编码的方式直接定义这些内容。本章中我们就针对Android中的各种资源,包括字符串资源、尺寸资源、样式和主题资源、图片资源、布局资源等以及国际化和资源自适应等知识进行深入讲解。
用户9184480
2024/12/17
1280
Android中的资源
android ListView 例子
程序效果是实现一个ListView,ListView里面有标题、内容和图片,并加入单击和长按响应。
全栈程序员站长
2022/09/15
7260
android ListView 例子
Android SimpleAdapter显示ListView、GridView
SimpleAdapter作为一个数据集,主要向ListView、GridView容器填充数据,总结了几种填充方式,原理很简单,直接看代码和效果图
阳光岛主
2019/02/19
6340
[android] 保存文件到SD卡
/****************2016年5月4日 更新*****************************/
唯一Chat
2019/09/10
2.7K0
Android开发:ListView、AdapterView、RecyclerView全面解析
AdapterView本身是一个抽象类,AdapterView及其子类的继承关系如下图:
Carson.Ho
2019/02/22
3.5K0
Android静默安装实现方案,仿360手机助手秒装和智能安装功能
用户1158055
2018/01/08
3.3K0
Android静默安装实现方案,仿360手机助手秒装和智能安装功能
android入门 — ListView
  ListView主要是用来解决大量数据展示的问题,它的用途很广泛,几乎所有的app都会用到,比如说知乎、今日头条、微博、通讯录等。     ListView允许用户通过上下滑动的方式将屏幕外的数据
Mister24
2018/05/14
1.2K0
【Android 应用开发】Android 数据存储 之 SQLite数据库详解
转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/19028665
韩曙亮
2023/03/27
2.5K0
【Android 应用开发】Android 数据存储 之 SQLite数据库详解
【Android 应用开发】Android 上实现非root的 Traceroute -- 非Root权限下移植可执行二进制文件 脚本文件
转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/36438365
韩曙亮
2023/03/27
4990
【Android 应用开发】Android 上实现非root的 Traceroute -- 非Root权限下移植可执行二进制文件 脚本文件
ListView和SimpleAdapter(图文列表)
新添加一个资源文件list_array.xml,主要作用是为simpleAdapter添加显示规则:
李小白是一只喵
2020/04/24
1.3K0
Android读写SD卡
SD卡的读写是我们在开发Android 应用程序过程中最常见的操作。下面介绍SD卡的读写操作方式:
全栈程序员站长
2022/07/15
1.2K0
GridView属性和使用方法
前面一共用了8期来学习ListView列表的相关操作,其实学习的ListView的知识完全适用于AdapterView的其他子类,如GridView、Spinner、AutoCompleteTextView等组件,那么接下来分别来学习一下这些列表组件,本期先学习GridView的使用。 一、认识GridView 前面学的ListView是列表, 这里的GridView就是显示网格,用于在界面上按行、列分布的方式来显示多个组件。 GridView 和 ListView 有共同的父类:A
分享达人秀
2018/02/02
2.9K0
GridView属性和使用方法
Arcgis For Android之离线地图实现的几种方式
为什么要用,我想离线地图的好处是不言而喻的,所以很多人做系统的时候都会考虑用离线地图。在此,我给大家介绍几种Arcgis For Android下加载离线地图的方式。
牛老师讲GIS
2018/10/23
2.8K1
Arcgis For Android之离线地图实现的几种方式
Android开发 经验技巧汇总(基于Android Studio)(二)
assets文件夹里面的文件都是保持原始的文件格式,需要用AssetManager以字节流的形式读取文件。
cutercorley
2020/07/23
1.3K0
Android开发 经验技巧汇总(基于Android Studio)(二)
2014-10-25Android学习------布局处理(三)------常见且常用的列表布局
我学习Android都是结合源代码去学习,这样比较直观,非常清楚的看清效果,觉得很好,今天的学习源码是网上找的个HealthFood 源码 百度搜就知道很多下载的地方
wust小吴
2022/03/07
1.1K0
2014-10-25Android学习------布局处理(三)------常见且常用的列表布局
推荐阅读
相关推荐
9.Android-读写SD卡案例
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文