在实际开发中,Android提供了5种方式存储数据,从这一讲开始,我们来学习一下Android中的数据存储。
1. 文件存储数据 [也就是通常说的SD卡中]2. 使用SharedPreferences存储数据3. SQLite数据库存储数据4. 使用ContentProvider存储数据5. 网络存储数据 [可以把本地的数据存储在网络的服务端]
1. 文件存储数据介绍
我们都知道Java提供了一套完整的IO流体系,包括FileInputStream和FileOutStream等,通过这些类我们可以方便的访问磁盘上的文件内容
Android同样支持这种方式访问手机存储器上的文件。
OpenFileOutput和openFileInput的使用, Context提供了如下两个方法来打开应用程序的数据文件夹里的文件IO流。
1) FileInputStream openFileInput(String name):打开应用程序的数据文件夹下的name文件对应的输入流2) FileOutStream openFileOutput(String name,int mode):打开应用程序的数据文件夹下的name文件对应输出流
mode : 指定打开文件的模式, 该模式支持如下值:
Context.MODE_PRIVATE = 0Context.MODE_APPEND = 32768 \\追加Context.MODE_WORLD_READABLE = 1 \\可读Context.MODE_WORLD_WRITEABLE = 2 \\可写
以上两个方法都是分别打开文件输入流、输出流, 除此之外,Context还提供了如下几个方法来访问应用程序的数据文件夹:
getDir(String name,int mode) : 在应用程序的数据文件夹下获取或者创建name对应的子目录
File getFilesDir() : 获取该应用程序的数据文件夹的绝对路径
String[] fileList() : 返回该应用程序的数据文件夹下的指定文件
2. 文件存储步骤
在进行文件存储的时候,都会首先去判断是否存在外部存储设备。
查看 Android文档 :Using the External Storage [使用可扩展的存储设备]:
每一台Android设备都会支持 "可扩展存储" 的设备来让你保存文件. 它是可以移动的存储设备(例如SD卡)或者集成的(不可移动)的存储设备。
检查媒体存在:
在你做任何外部存储工作之前,你应该调用 getExternalStorageState() 方法来检查存储媒体是否可以用。这些存储媒体状态可能是已安装,没有存储卡,只读,或者其他的一些状态。
3. 程序实现
1) 在对SD卡进行操作的时候,必须在AndroidManifest.xml清单文件中添加它的授权,在AndroidManifest.xml下的Permissions标签下添加,如下图所示:
2) 进行单元测试,在AndroidManifest.xml下的Instrumentation标签下添加 单元测试,测试内容只需要添加测试名称和包的内容即可,如下图所示:
同时在 AndroidManifest.xml 代码中加一个单元测试的标签就可以进行单元测试的内容了:
<uses-library android:name="android.test.runner"/>
3) AndroidManifest.xml 代码如下:
4) 布局文件 activity_main.xml<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.sdcarddemo" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <!-- 添加读写SD card 的授权 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.android.sdcarddemo" > </instrumentation> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <uses-library android:name="android.test.runner"/> <activity android:name="com.android.sdcarddemo.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
5) FileService.java 服务类,用来实现读写SD卡的方法<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" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <EditText android:id="@+id/editText1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginLeft="21dp" android:layout_marginTop="18dp" android:ems="10" > </EditText> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/textView1" android:layout_alignBottom="@+id/textView1" android:layout_alignLeft="@+id/button1" android:text="读取信息" /> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/button1" android:layout_centerHorizontal="true" android:layout_marginTop="40dp" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/editText1" android:layout_below="@+id/editText1" android:layout_marginTop="20dp" android:text="保存信息" /> </RelativeLayout>
6) 主程序文件 MainActivity.javapackage com.android.sdcarddemo; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import android.content.Context; import android.os.Environment; import android.util.Log; import android.widget.Toast; public class FileService { private final static String TAG = "FileService"; private Context context; public FileService(Context context) { this.context = context; } public FileService() { } public String getFileFromSdcard(String fileName) { FileInputStream inputStream = null; // 在手机应用开发中 ByteArrayOutputStream 流是缓冲的流,和磁盘无关,可以不需要关闭 // Environment.MEDIA_MOUNTED 如果是可读写的状态,并且SD卡是存在的情况下 ByteArrayOutputStream outputSteam = new ByteArrayOutputStream(); File file = new File(Environment.getExternalStorageDirectory(), fileName); if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { try { inputStream = new FileInputStream(file); int length = 0; byte[] buffer = new byte[1024]; while (-1 != (length = (inputStream.read(buffer)))) { outputSteam.write(buffer, 0, length); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } else { Toast.makeText(context, "Please input SD card", Toast.LENGTH_LONG).show(); Log.i(TAG, "No SD card"); } return new String(outputSteam.toByteArray()); } /** * 把内容保存在SD 卡上 * * @param fileName 文件的名称 * @param content 文件的内容 * @return */ public boolean saveContentToSDcard(String fileName, String content) { boolean flag = false; FileOutputStream fileOutputStream = null; // 获得SD卡的路径 File file = new File(Environment.getExternalStorageDirectory(), fileName); // 判断SD卡是否可以用 if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageDirectory())) { try { fileOutputStream = new FileOutputStream(file); fileOutputStream.write(content.getBytes()); flag = true; } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } return flag; } }
package com.android.sdcarddemo; import android.os.Bundle; import android.app.Activity; import android.content.Context; import android.util.Log; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class MainActivity extends Activity { private static final String TAG = "MainActivity"; private Button button; private Button button1; private EditText editText; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initComponent(); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub MainActivity.this.saveFile(); } }); button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub MainActivity.this.readFile(); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } private void initComponent(){ button = (Button)findViewById(R.id.button1); button1 = (Button)findViewById(R.id.button2); editText = (EditText)findViewById(R.id.editText1); textView = (TextView)findViewById(R.id.textView1); } private void saveFile(){ String str = editText.getText().toString(); FileService fileService = new FileService(); boolean flag = fileService.saveContentToSDcard("hello.txt", str); Log.i(TAG, "------->> " + flag); } private void readFile(){ FileService fileService = new FileService(MainActivity.this); String str = fileService.getFileFromSdcard("hello.txt"); textView.setText(str); } }
4. 程序执行结果
5. 备注知识点
Environment类[查看Android API文档]:这个类提供了一些操作系统环境应用的操作,在这里面的 Constants 里面的返回值可以判断出SD卡的状态:装载、卸载、或者是允许可读写的操作
如下图所示:
File file = new File(Environment.getxxxx); //得到扩展存储卡的路径
Eclipse使用技巧:方法前面自动增加注释快捷键是 alt+shift+j