【攻克Android (18)】数据存储

[b][size=large]本文围绕以下五个部分展开: [/size][/b]

[b][size=large]一、五种数据存储方式[/size][/b]
[b][size=large]二、文件内部存储[/size][/b]
[b][size=large]三、文件外部存储[/size][/b]
[b][size=large]案例:文件存储[/size][/b]
[size=medium][b]附 代码补充[/b][/size]
[b][size=large]四、选项存储(应用设置)[/size][/b]
[b][size=large]案例:选项存储[/size][/b]

[b][size=large]附 整个案例代码补充[/size][/b]


[b][size=large]一、五种数据存储方式[/size][/b]

[align=center][img]http://dl2.iteye.com/upload/attachment/0111/6693/aa29ca48-b193-3c9d-ac3b-8865206034a7.png[/img][/align]


[b][size=large]二、文件内部存储[/size][/b]

[size=medium][b]1. 文件内部存储[/b][/size]

[size=medium]应用程序直接将数据写入设备 Flash(ROM)的文件中,文件位于应用程序私有目录中,其他应用程序不能访问;当卸载应用程序时,文件会一同删除。[/size]

[size=medium][b]2. 数据存储位置[/b][/size]

[size=medium]/data/data/app_name/files[/size]

[size=medium][b]3. 相关方法[/b][/size]

[align=center][img]http://dl2.iteye.com/upload/attachment/0109/6526/9b7d7d1b-aee3-327d-a65e-ff64f89a019c.png[/img][/align]


[b][size=large]三、文件外部存储[/size][/b]

[size=medium][b]1. 文件外部存储[/b][/size]

[size=medium]android 支持将数据存储在共享的外部存储设备(可卸载的 SD 卡或 ROM)上,所有应用都可以读写文件(获得权限后),通常存储公共数据(音乐、照片、视频、下载的文件等内容)。[/size]

[size=medium][b]2. 设置访问 SDCard 的权限[/b][/size]

[size=medium](1)往 SDCard 写入数据权限[/size]

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


[size=medium](2)从 SDCard 读取数据权限[/size]

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>


[size=medium](3)在 SDCard 中创建与删除文件权限[/size]

<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>



[b][size=large]案例:文件存储[/size][/b]

[size=medium]主界面如下。当输入文件名和文件内容,点击“写入文件”,就会写入 内存 / SDCard 中;当只输入文件名,点击“读取文件”,就会读取相应文件名对应的文件内容,然后显示在“文件内容”栏中。[/size]

[align=center][img]http://dl2.iteye.com/upload/attachment/0109/6535/5a2945e9-4033-38ec-88b0-ea5cbc914a3a.png[/img][/align]

[size=medium][b]1. strings.xml。定义所需字符串[/b][/size]

<resources>
<string name="app_name">Storage</string>

<string name="action_settings">Settings</string>
<string name="file_name">文件名</string>
<string name="file_content">文件内容</string>
<string name="append_mode">追加模式</string>
<string name="btn_write">写入文件(内部存储)</string>
<string name="btn_read">读取文件(内部存储)</string>
<string name="btn_sd_write">写入文件(SDCard)</string>
<string name="btn_sd_read">读取文件(SDCard)</string>
<string name="op_success">操作成功</string>
<string name="op_fail">操作失败</string>
<string name="sdcard_fail">SD Card 不可用</string>

</resources>


[size=medium][b]2. activity_main.xml。写主界面。[/b][/size]

<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/txtFileName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/file_name"
android:singleLine="true" />

<EditText
android:id="@+id/txtFileContent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/txtFileName"
android:hint="@string/file_content"
android:lines="3" />

<CheckBox
android:id="@+id/cbAppendMode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/txtFileContent"
android:text="@string/append_mode" />

<Button
android:id="@+id/btnWrite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/cbAppendMode"
android:onClick="onClick"
android:text="@string/btn_write" />

<Button
android:id="@+id/btnRead"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/cbAppendMode"
android:layout_toRightOf="@id/btnWrite"
android:onClick="onClick"
android:paddingLeft="10dp"
android:text="@string/btn_read" />

<Button
android:id="@+id/btnSDCardWrite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/btnWrite"
android:onClick="onClick"
android:text="@string/btn_sd_write" />

<Button
android:id="@+id/btnSDCardRead"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/btnWrite"
android:layout_toRightOf="@id/btnSDCardWrite"
android:onClick="onClick"
android:paddingLeft="10dp"
android:text="@string/btn_sd_read" />

</RelativeLayout>


[size=medium][b]3. MainActivity。写 onClick() 方法,声明变量,初始化变量。[/b][/size]

public void onClick(View view) {
switch (view.getId()) {
case R.id.btnWrite:
doWrite();
break;
case R.id.btnRead:
doRead();
break;
case R.id.btnSDCardWrite:
doSDCardWrite();
break;
case R.id.btnSDCardRead:
doSDCardRead();
break;
}
}


private EditText txtFileName;
private EditText txtFileContent;
private CheckBox cbAppendMode;


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

txtFileName = (EditText) findViewById(R.id.txtFileName);
txtFileContent = (EditText) findViewById(R.id.txtFileContent);
cbAppendMode = (CheckBox) findViewById(R.id.cbAppendMode);
}


[size=medium][b]4. 文件内部存储。[/b][/size]

[size=medium](1)自定义独立的 FileService 类,封装文件内部存储的写入、读取操作。[/size]

package com.xiangdong.storage;

import android.content.Context;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

/**
* 内部存储文件操作(不需要权限)
*/
public class FileService {
private Context context; // 上下文

public FileService(Context context) {
this.context = context;
}

/**
* 保存文件内容
*
* @param fileName 文件名
* @param fileContent 文件内容
* @param mode 保存模式
*/
public void write(String fileName, String fileContent, int mode) throws Exception {
// Android 中 通过上下文,就可以直接打开文件(通过 openFileOutput),Java I/O流中还得 new
/*
openFileOutput :Open a private file associated
with this Context's application package for writing.
Creates the file if it doesn't already exist.
*/
FileOutputStream out = context.openFileOutput(fileName, mode);
out.write(fileContent.getBytes());
out.close();
}

/**
* 读取文件
*
* @param fileName
* @return
* @throws Exception
*/
public String read(String fileName) throws Exception {
/*
openFileInput :Open a private file associated
with this Context's application package for reading.
*/
FileInputStream in = context.openFileInput(fileName);

byte[] buffer = new byte[1024];
int len = 0;

ByteArrayOutputStream out = new ByteArrayOutputStream();
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
//获得文件的二进制数据
byte[] data = out.toByteArray();
in.close();
out.close();

return new String(data);
}

}


[size=medium][b]补充:[/b][/size]

[size=medium]Activity提供了 openFileOutput() 方法可以用于把数据输出到文件中。[/size]

[size=medium]openFileOutput()方法的第一参数用于指定文件名称,不能包含路径分隔符“/” ,如果文件不存在,Android 会自动创建它。[/size]

[size=medium]openFileOutput()方法的第二参数用于指定操作模式,有四种模式:[/size]

[align=center][img]http://dl2.iteye.com/upload/attachment/0109/6545/8a099927-1461-3b29-9a87-54040e58a010.png[/img][/align]

[size=medium](2)声明变量,初始化变量。[/size]

private FileService fileService;


fileService = new FileService(this);


[size=medium](3)MainActivity。创建 doWrite() 方法,实现内部存储写入文件。[/size]

/**
* 内部存储写入文件
*/
private void doWrite() {
// 先得到 文件名、文件内容
String fileName = txtFileName.getText().toString();
String fileContent = txtFileContent.getText().toString();
try {
if (cbAppendMode.isChecked()) {
// 追加
fileService.write(fileName, fileContent, Context.MODE_APPEND);
} else {
// 覆盖
// 文件仅能被创建它的程序所访问
fileService.write(fileName, fileContent, Context.MODE_PRIVATE);
}
showToast(R.string.op_success);
} catch (Exception e) {
showToast(R.string.op_fail);
}
}


[size=medium]其中,用到自定义的 showToast() 方法:[/size]

private void showToast(int resId) {
Toast.makeText(this, getString(resId), Toast.LENGTH_SHORT).show();
}


[size=medium](4)MainActivity。创建 doRead() 方法,实现内部存储读取文件。[/size]

/**
* 内部存储读取文件
*/
private void doRead() {
// 获得文件名
String fileName = txtFileName.getText().toString();
try {
String fileContent = fileService.read(fileName);
txtFileContent.setText(fileContent);
showToast(R.string.op_success);
} catch (Exception e) {
showToast(R.string.op_fail);
}
}


[size=medium][b]5. 文件外部存储。[/b][/size]

[size=medium](1)在功能清单文件中,授权往 SDCard 写入和读取数据。[/size]

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


[size=medium](2)自定义独立的 SDCardService 类,封装文件外部存储的写入、读取操作。[/size]

package com.xiangdong.storage;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

/**
* 外部存储(SDCard)文件操作 (需要权限 - WRITE/READ : 在功能清单中授予权限)
*/
public class SDCardService {

public void write(File file, String fileContent, boolean append) throws Exception {
FileOutputStream out = new FileOutputStream(file, append);
out.write(fileContent.getBytes());
out.close();
}

public String read(File file) throws Exception {
FileInputStream in = new FileInputStream(file);

byte[] buffer = new byte[1024];
int len = 0;

ByteArrayOutputStream out = new ByteArrayOutputStream();
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
//获得文件的二进制数据
byte[] data = out.toByteArray();
in.close();
out.close();

return new String(data);
}
}


[size=medium](3)声明变量,初始化变量。[/size]

private SDCardService sdCardService;


sdCardService = new SDCardService();


[size=medium](4)MainActivity。创建 doSDCardWrite() 方法,实现外部存储写入文件。[/size]

/**
* 外部存储写入文件
*/
private void doSDCardWrite() {
// 先得到 文件名、文件内容
String fileName = txtFileName.getText().toString();
String fileContent = txtFileContent.getText().toString();

// 判断手机是否装有 SDCard ,并且可以进行读写
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
try {
// 获得 SDCard 根目录
File sdCardDir = Environment.getExternalStorageDirectory();
// 在根目录下面,获得文件
File file = new File(sdCardDir, fileName);

boolean append = false; // 默认是覆盖
if (cbAppendMode.isChecked()) {
append = true; // 追加
}
sdCardService.write(file, fileContent, append);
showToast(R.string.op_success);
} catch (Exception e) {
showToast(R.string.op_fail);
}
} else {
showToast(R.string.sdcard_fail);
}
}


[size=medium](5)MainActivity。创建 doSDCardRead() 方法,实现外部存储读取文件。[/size]

/**
* SDCard 读取文件
*/
private void doSDCardRead() {
String fileName = txtFileName.getText().toString();
// 判断手机是否装有 SDCard ,并且可以进行读写
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
try {
// 获取 SDCard 根目录
File sdCardDir = Environment.getExternalStorageDirectory();
// 在根目录下面,获得文件
File file = new File(sdCardDir, fileName);
String fileContent = sdCardService.read(file);
txtFileContent.setText(fileContent);
showToast(R.string.op_success);
} catch (Exception e) {
showToast(R.string.op_fail);
}
} else {
showToast(R.string.sdcard_fail);
}
}



[size=medium][b]附 代码补充[/b][/size]

[size=medium]MainActivity:[/size]

package com.xiangdong.storage;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;


public class MainActivity extends Activity {
private EditText txtFileName;
private EditText txtFileContent;
private CheckBox cbAppendMode;

private FileService fileService;
private SDCardService sdCardService;

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

txtFileName = (EditText) findViewById(R.id.txtFileName);
txtFileContent = (EditText) findViewById(R.id.txtFileContent);
cbAppendMode = (CheckBox) findViewById(R.id.cbAppendMode);

fileService = new FileService(this);
sdCardService = new SDCardService();
}

public void onClick(View view) {
switch (view.getId()) {
case R.id.btnWrite:
doWrite();
break;
case R.id.btnRead:
doRead();
break;
case R.id.btnSDCardWrite:
doSDCardWrite();
break;
case R.id.btnSDCardRead:
doSDCardRead();
break;
}
}

/**
* SDCard 读取文件
*/
private void doSDCardRead() {
String fileName = txtFileName.getText().toString();
// 判断手机是否装有 SDCard ,并且可以进行读写
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
try {
// 获取 SDCard 根目录
File sdCardDir = Environment.getExternalStorageDirectory();
// 在根目录下面,获得文件
File file = new File(sdCardDir, fileName);
String fileContent = sdCardService.read(file);
txtFileContent.setText(fileContent);
showToast(R.string.op_success);
} catch (Exception e) {
showToast(R.string.op_fail);
}
} else {
showToast(R.string.sdcard_fail);
}
}

/**
* 外部存储写入文件
*/
private void doSDCardWrite() {
// 先得到 文件名、文件内容
String fileName = txtFileName.getText().toString();
String fileContent = txtFileContent.getText().toString();

// 判断手机是否装有 SDCard ,并且可以进行读写
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
try {
// 获得 SDCard 根目录
File sdCardDir = Environment.getExternalStorageDirectory();
// 在根目录下面,获得文件
File file = new File(sdCardDir, fileName);

boolean append = false; // 默认是覆盖
if (cbAppendMode.isChecked()) {
append = true; // 追加
}
sdCardService.write(file, fileContent, append);
showToast(R.string.op_success);
} catch (Exception e) {
showToast(R.string.op_fail);
}
} else {
showToast(R.string.sdcard_fail);
}
}

/**
* 内部存储读取文件
*/
private void doRead() {
// 获得文件名
String fileName = txtFileName.getText().toString();
try {
String fileContent = fileService.read(fileName);
txtFileContent.setText(fileContent);
showToast(R.string.op_success);
} catch (Exception e) {
showToast(R.string.op_fail);
}
}

/**
* 内部存储写入文件
*/
private void doWrite() {
// Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容
// Context.MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
// MODE_WORLD_READABLE:表示当前文件可以被其他应用读取;
// MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入

// 先得到 文件名、文件内容
String fileName = txtFileName.getText().toString();
String fileContent = txtFileContent.getText().toString();
try {
if (cbAppendMode.isChecked()) {
// 追加
fileService.write(fileName, fileContent, Context.MODE_APPEND);
} else {
// 覆盖
// 文件仅能被创建它的程序所访问
fileService.write(fileName, fileContent, Context.MODE_PRIVATE);
}
showToast(R.string.op_success);
} catch (Exception e) {
showToast(R.string.op_fail);
}
}

private void showToast(int resId) {
Toast.makeText(this, getString(resId), Toast.LENGTH_SHORT).show();
}

// ----------------------------------------------------------------------------
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();

if (id == R.id.action_settings) {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
return true;
}

return super.onOptionsItemSelected(item);
}

}



[b][size=large]四、选项存储(应用设置)[/size][/b]

[size=medium][b]1. 选项存储(应用设置)[/b][/size]

[size=medium]选项存储,也称为应用设置。保存用户在使用应用程序时的偏好,数据以键值对形式保存在 xml 文件中。[/size]
[size=medium]很多时候我们开发的软件需要向用户提供软件参数设置功能,例如我们常用的QQ,用户可以设置是否允许陌生人添加自己为好友。Android平台给我们提供了一个SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数。使用SharedPreferences保存数据,其背后是用xml文件存放数据。[/size]

[size=medium][b]2. 目标位置[/b][/size]

[size=medium]/data/data/app_name/shared_prefs/[/size]

[size=medium][b]3. 两种实现方式[/b][/size]

[align=center][img]http://dl2.iteye.com/upload/attachment/0109/6562/80664ea2-4e1c-3a60-a03b-8d42d5a75034.png[/img][/align]


[b][size=large]案例:选项存储[/size][/b]

[size=medium]主界面如下:[/size]

[align=center][img]http://dl2.iteye.com/upload/attachment/0109/6576/792c8692-e12c-3059-966d-287a93cf210a.png[/img][/align]

[size=medium]点击“设置”菜单,进入 选项屏幕:[/size]

[align=center][img]http://dl2.iteye.com/upload/attachment/0109/6580/5175e28a-3a9d-3ae4-9579-af9f6b9c4463.png[/img][/align]

[size=medium]Welcome_text 修改前(Hello World):[/size]

[align=center][img]http://dl2.iteye.com/upload/attachment/0109/6574/61ace005-49ec-3478-a924-6fc7cd7e6ea0.png[/img][/align]

[size=medium]Welcome_text 修改(你好!):[/size]

[align=center][img]http://dl2.iteye.com/upload/attachment/0109/6572/da1c2c85-5ebd-3e36-ae54-8ad13b5f1658.png[/img][/align]

[size=medium]Welcome_text_color 修改前(black):[/size]

[align=center][img]http://dl2.iteye.com/upload/attachment/0109/6570/65701cf8-9df6-3cd5-b222-dabf88a2843f.png[/img][/align]

[size=medium]Welcome_text_color 修改(blue):[/size]

[align=center][img]http://dl2.iteye.com/upload/attachment/0109/6568/74d741e3-557e-32b8-872c-d08fce2acb2f.png[/img][/align]

[size=medium]选项屏幕中,“Show welcome text”是勾选了的,因此会在主界面显示“欢迎文字”。修改之后,返回主界面,如下:[/size]

[align=center][img]http://dl2.iteye.com/upload/attachment/0109/6578/79831f7c-3207-3f6c-9b77-fe9c81d2a74c.png[/img][/align]

[size=medium][b]1. strings.xml。定义所需字符串。[/b][/size]

<resources>
<string name="app_name">Storage</string>

<!-- Strings related to Settings -->
<string name="pref_title_welcome_text">Welcome text</string>
<string name="pref_summary_welcome_text">The welcome text to show in the main activity.</string>
<string name="pref_default_welcome_text">Hello World</string>

<string name="pref_title_welcome_text_color">Welcome text color</string>
<string name="pref_summary_welcome_text_color">The color of the welcome text to show in the main activity.</string>
<string name="pref_default_welcome_text_color">#000000</string>

<string name="pref_title_show_welcome_text">Show welcome text</string>
<string name="pref_summary_show_welcome_text">Shows the welcome text in the main activity.</string>

</resources>


[size=medium][b]2. 在 values 下面创建 array.xml 数组文件。里面包含了 “颜色标签”的数组和“每个颜色对应的值”的数组。[/b][/size]

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="colorLabelsArray">
<item>Aqua</item>
<item>Black</item>
<item>Blue</item>
<item>Fushsia</item>
<item>Gray</item>
<item>Green</item>
<item>Lime</item>
<item>Maroon</item>
<item>Navy</item>
<item>Olive</item>
<item>Purple</item>
<item>Red</item>
<item>Silver</item>
<item>Teal</item>
<item>White</item>
<item>Yellow</item>
</string-array>
<string-array name="colorValuesArray">
<item>#00FFFF</item>
<item>#000000</item>
<item>#0000FF</item>
<item>#FF00FF</item>
<item>#808000</item>
<item>#008000</item>
<item>#00FF00</item>
<item>#800000</item>
<item>#000080</item>
<item>#808080</item>
<item>#800080</item>
<item>#FF0000</item>
<item>#C0C0C0</item>
<item>#008080</item>
<item>#FFFFFF</item>
<item>#FFFF00</item>
</string-array>
</resources>


[size=medium][b]3. 定义用户接口(“选项屏幕”):在 res 下面创建一个目录:xml。在该目录下,创建 preferences.xml。[/b][/size]

[align=center][img]http://dl2.iteye.com/upload/attachment/0109/6580/5175e28a-3a9d-3ae4-9579-af9f6b9c4463.png[/img][/align]

[size=medium](1)与定义活动、菜单一样,使用 XML 形式定义用户接口,根元素 PreferenceScreen 。[/size]

[size=medium](2)文件位置: /res/xml/。[/size]

[size=medium](3)元素类型:[/size]

[align=center][img]http://dl2.iteye.com/upload/attachment/0109/6566/5e5f25fa-b4b2-32d9-8046-7feec924ede9.png[/img][/align]

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<!--
EditTextPreference :文本框选项(允许修改欢迎文本)
defaultValue 默认值
key 键
summary 摘要
title 标题
-->

<!--选项的屏幕-->
<EditTextPreference
android:defaultValue="@string/pref_default_welcome_text"
android:key="welcome_text"
android:summary="@string/pref_summary_welcome_text"
android:title="@string/pref_title_welcome_text" />
<ListPreference
android:defaultValue="@string/pref_default_welcome_text_color"
android:entries="@array/colorLabelsArray"
android:entryValues="@array/colorValuesArray"
android:key="welcome_text_color"
android:summary="@string/pref_summary_welcome_text_color"
android:title="@string/pref_title_welcome_text_color" />
<CheckBoxPreference
android:defaultValue="true"
android:key="show_welcome_text"
android:summary="@string/pref_summary_show_welcome_text"
android:title="@string/pref_title_show_welcome_text" />

</PreferenceScreen>


[size=medium][b]4. activity_main.xml。在最后加一个 TextView,用来显示“欢迎文本”。[/b][/size]

[align=center][img]http://dl2.iteye.com/upload/attachment/0109/6576/792c8692-e12c-3059-966d-287a93cf210a.png[/img][/align]

<TextView
android:id="@+id/tvPreference"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/btnSDCardWrite"
android:text="@string/app_name"
android:textSize="30sp" />


[size=medium][b]5. 在 Java 包下,创建 选项碎片 SettingsFragment,用来加载 选项屏幕 preferences.xml。[/b][/size]

package com.android.storage;

import android.os.Bundle;
import android.preference.PreferenceFragment;

/**
* 选项 Fragment 界面
*/
public class SettingsFragment extends PreferenceFragment {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// 从资源文件中,加载 选项屏幕 界面
addPreferencesFromResource(R.xml.preferences);
}
}


[size=medium][b]6. 在 Java 包下,创建 活动类 SettingsActivity,在点击菜单中的“Settings”时,用来加载 选项碎片 SettingsFragment。[/b][/size]

package com.android.storage;

import android.app.Activity;
import android.os.Bundle;

/**
* 选项的活动(界面)
*/
public class SettingsActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Display the preferences fragment as the content of the activity
// 在活动(界面)中显示 选项屏幕 碎片 界面
// android.R.id.content:来自 Android 的默认的 Layout: LinearLayout
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment()).commit();
}
}


[size=medium][b]7. 在功能清单文件中,注册 SettingsActivity。[/b][/size]

<activity
android:name=".SettingsActivity"
android:label="@string/action_settings"
android:parentActivityName=".MainActivity">
</activity>


[size=medium][b]注:[/b][/size]

[size=medium]创建 Activity 三步曲:布局、活动、注册。直接创建 Activity 的时候,三步会自动完成。当只创建活动,不需要布局的时候,还需要自己注册。建议:直接创建 Activity,然后删除掉不需要的 布局。[/size]

[size=medium][b]8. MainActivity。在设置菜单中,通过意图,设置 主活动界面跳转到设置活动中,而设置活动显示的是 选项屏幕 界面,因此点击设置后,显示的是 选项屏幕 的界面。[/b][/size]

@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();

//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
// Starts the Settings activity on top of the current activity
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
return true;
}

return super.onOptionsItemSelected(item);
}


[size=medium][b]9. 重绘界面。(由 SettingsActivity跳转到MainActivity后,需要重绘界面,才会显示出更新之后的效果。重绘界面,用到Activity生命周期中的 onResume()方法。)[/b][/size]

/**
* 重绘界面
* (由 SettingsActivity跳转到 MainActivity后,
* 需要重绘界面,才会显示出更新之后的效果。
* 重绘界面,用到Activity生命周期中的 onResume()方法。)
*/
@Override
public void onResume() {
super.onResume();
// 通过选项管理器,从目录中(data/data/app_name/shared_prefs)获得选项信息
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);

// 获得 文本框控件 (为了改显示的文本)
TextView welcomeTextView = (TextView) findViewById(R.id.tvPreference);

// 获得 欢迎文本
String defaultWelcomeText = getResources().getString(R.string.pref_default_welcome_text);
String welcomeText = preferences.getString("welcome_text", defaultWelcomeText);
welcomeTextView.setText(welcomeText);

// 获得 欢迎文本的字体颜色
String defaultWelcomeTextColor = getResources().getString(R.string.pref_default_welcome_text_color);
String welcomeTextColor = preferences.getString("welcome_text_color", defaultWelcomeTextColor);
welcomeTextView.setTextColor(Color.parseColor(welcomeTextColor));

// 显示欢迎文本
boolean showWelcomeText = preferences.getBoolean("show_welcome_text", true);
if (showWelcomeText) {
welcomeTextView.setVisibility(View.VISIBLE);
} else {
welcomeTextView.setVisibility(View.INVISIBLE);
}
}



[b][size=large]附 整个案例代码补充[/size][/b]

[align=center][img]http://dl2.iteye.com/upload/attachment/0109/6599/b23bbd84-b5e0-3f08-85fc-738709ad4e92.png[/img][/align]

[size=medium][b]1. strings.xml。[/b][/size]

<resources>
<string name="app_name">Storage</string>

<string name="file_name">文件名</string>
<string name="file_content">文件内容</string>
<string name="append_mode">追加模式</string>
<string name="btn_writer">写入文件(内部存储)</string>
<string name="btn_read">读取文件(内部存储)</string>
<string name="btn_sdcard_writer">写入文件(SDCard)</string>
<string name="btn_sdcard_read">读取文件(SDCard)</string>

<string name="op_success">操作成功</string>
<string name="op_fail">操作失败</string>
<string name="sdcard_fail">SD Card 是否可用.</string>

<!-- Strings related to Settings -->
<string name="action_settings">Settings</string>
<string name="pref_title_welcome_text">Welcome text</string>
<string name="pref_summary_welcome_text">The welcome text to show in the main activity.</string>
<string name="pref_default_welcome_text">Hello World</string>

<string name="pref_title_welcome_text_color">Welcome text color</string>
<string name="pref_summary_welcome_text_color">The color of the welcome text to show in the main activity.</string>
<string name="pref_default_welcome_text_color">#000000</string>

<string name="pref_title_show_welcome_text">Show welcome text</string>
<string name="pref_summary_show_welcome_text">Shows the welcome text in the main activity.</string>
</resources>


[size=medium][b]2. activity_main.xml。[/b][/size]

<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/txtFileName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/file_name"
android:singleLine="true"/>

<EditText
android:id="@+id/txtFileContent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/txtFileName"
android:hint="@string/file_content"
android:lines="3"/>

<CheckBox
android:id="@+id/cbAppendMode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/txtFileContent"
android:text="@string/append_mode"/>

<Button
android:id="@+id/btnWriter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/cbAppendMode"
android:onClick="onClick"
android:text="@string/btn_writer"/>

<Button
android:id="@+id/btnRead"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/btnWriter"
android:onClick="onClick"
android:text="@string/btn_read"/>

<Button
android:id="@+id/btnSDCardWriter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/btnRead"
android:onClick="onClick"
android:text="@string/btn_sdcard_writer"/>

<Button
android:id="@+id/btnSDCardRead"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/btnSDCardWriter"
android:onClick="onClick"
android:text="@string/btn_sdcard_read"/>

<!-- Widget related to Settings -->
<TextView
android:id="@+id/tvPreference"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/btnSDCardRead"
android:text="@string/app_name"
android:textSize="30sp"/>

</RelativeLayout>


[size=medium][b]3. MainActivity。[/b][/size]

package com.android.storage;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;


public class MainActivity extends Activity {
private EditText txtFileName;
private EditText txtFileContent;
private CheckBox cbAppendMode;

private FileService fileService;
private SDCardService sdCardService;

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

txtFileName = (EditText) findViewById(R.id.txtFileName);
txtFileContent = (EditText) findViewById(R.id.txtFileContent);
cbAppendMode = (CheckBox) findViewById(R.id.cbAppendMode);

fileService = new FileService(this);
sdCardService = new SDCardService();
}

public void onClick(View view) {
switch (view.getId()) {
case R.id.btnWriter:
doWrite();
break;
case R.id.btnRead:
doRead();
break;
case R.id.btnSDCardWriter:
doSDCardWriter();
break;
case R.id.btnSDCardRead:
doSDCardRead();
break;
}
}


/**
* SDCard 写入文件
*/
private void doSDCardWriter() {
String fileName = txtFileName.getText().toString();
String fileContent = txtFileContent.getText().toString();

// 判断手机是否装有SDCard,并且可以进行读写
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
try {
// 获取SDCard根目录
File sdCardDir = Environment.getExternalStorageDirectory();
File file = new File(sdCardDir, fileName);

boolean append = false; // 默认:覆盖
if (cbAppendMode.isChecked()) {
append = true; // 追加
}
sdCardService.write(file, fileContent, append);
showToast(R.string.op_success);
} catch (Exception e) {
showToast(R.string.op_fail);
}
} else {
showToast(R.string.sdcard_fail);
}
}

/**
* SDCard 读取文件
*/
private void doSDCardRead() {
String fileName = txtFileName.getText().toString();
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
try {
// 获取SDCard目录
File sdCardDir = Environment.getExternalStorageDirectory();
File file = new File(sdCardDir, fileName);
String fileContent = sdCardService.read(file);
txtFileContent.setText(fileContent);
showToast(R.string.op_success);
} catch (Exception e) {
showToast(R.string.op_fail);
}
} else {
showToast(R.string.sdcard_fail);
}
}

/**
* 内部存储读取文件
*/
private void doRead() {
String fileName = txtFileName.getText().toString();
try {
String fileContent = fileService.read(fileName);
txtFileContent.setText(fileContent);
showToast(R.string.op_success);
} catch (Exception e) {
showToast(R.string.op_fail);
}
}

/**
* 内部存储写入文件
*/
private void doWrite() {
// Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容
// Context.MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
// MODE_WORLD_READABLE:表示当前文件可以被其他应用读取;
// MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入

String fileName = txtFileName.getText().toString();
String fileContent = txtFileContent.getText().toString();
try {
if (cbAppendMode.isChecked()) {
// 追加 abc -> abcxyz
fileService.write(fileName, fileContent, Context.MODE_APPEND);
} else {
// 覆盖 abc -> xyz
// 文件仅能被创建它的程序所访问
fileService.write(fileName, fileContent, Context.MODE_PRIVATE);
}
showToast(R.string.op_success);
} catch (Exception e) {
showToast(R.string.op_fail);
}
}

private void showToast(int resId) {
Toast.makeText(this, getString(resId), Toast.LENGTH_SHORT).show();
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();

//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
// Starts the Settings activity on top of the current activity
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
return true;
}

return super.onOptionsItemSelected(item);
}

/**
* 重绘界面
* (由 SettingsActivity跳转到 MainActivity后,
* 需要重绘界面,才会显示出更新之后的效果。
* 重绘界面,用到Activity生命周期中的 onResume()方法。)
*/
@Override
public void onResume() {
super.onResume();
// 通过选项管理器,从目录中(data/data/app_name/shared_prefs)获得选项信息
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);

// 获得 文本框控件 (为了改显示的文本)
TextView welcomeTextView = (TextView) findViewById(R.id.tvPreference);

// 获得 欢迎文本
String defaultWelcomeText = getResources().getString(R.string.pref_default_welcome_text);
String welcomeText = preferences.getString("welcome_text", defaultWelcomeText);
welcomeTextView.setText(welcomeText);

// 获得 欢迎文本的字体颜色
String defaultWelcomeTextColor = getResources().getString(R.string.pref_default_welcome_text_color);
String welcomeTextColor = preferences.getString("welcome_text_color", defaultWelcomeTextColor);
welcomeTextView.setTextColor(Color.parseColor(welcomeTextColor));

// 显示欢迎文本
boolean showWelcomeText = preferences.getBoolean("show_welcome_text", true);
if (showWelcomeText) {
welcomeTextView.setVisibility(View.VISIBLE);
} else {
welcomeTextView.setVisibility(View.INVISIBLE);
}
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值