`
XiangdongLee
  • 浏览: 86696 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

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

 
阅读更多
本文围绕以下五个部分展开:

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

附   整个案例代码补充





一、五种数据存储方式




二、文件内部存储

        1. 文件内部存储

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

        2. 数据存储位置

        /data/data/app_name/files

        3. 相关方法




三、文件外部存储

        1. 文件外部存储

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

        2. 设置访问 SDCard 的权限

        (1)往 SDCard 写入数据权限

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


        (2)从 SDCard 读取数据权限

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


        (3)在 SDCard 中创建与删除文件权限

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



案例:文件存储

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



        1. strings.xml。定义所需字符串

<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>


        2. activity_main.xml。写主界面。

<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>


        3. MainActivity。写 onClick() 方法,声明变量,初始化变量。

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);
    }


        4. 文件内部存储。

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

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);
    }

}


        补充:

        Activity提供了 openFileOutput() 方法可以用于把数据输出到文件中。

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

        openFileOutput()方法的第二参数用于指定操作模式,有四种模式:



        (2)声明变量,初始化变量。

private FileService fileService;


fileService = new FileService(this);


        (3)MainActivity。创建 doWrite() 方法,实现内部存储写入文件。

/**
     * 内部存储写入文件
     */
    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);
        }
    }


        其中,用到自定义的 showToast() 方法:

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


        (4)MainActivity。创建 doRead() 方法,实现内部存储读取文件。

/**
     * 内部存储读取文件
     */
    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);
        }
    }


        5. 文件外部存储。

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

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


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

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);
    }
}


        (3)声明变量,初始化变量。

private SDCardService sdCardService;


sdCardService = new SDCardService();


        (4)MainActivity。创建 doSDCardWrite() 方法,实现外部存储写入文件。

/**
     * 外部存储写入文件
     */
    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);
        }
    }


        (5)MainActivity。创建 doSDCardRead() 方法,实现外部存储读取文件。

/**
     * 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);
        }
    }



        附   代码补充

        MainActivity:

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);
    }
    
}



四、选项存储(应用设置)

        1. 选项存储(应用设置)

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

        2. 目标位置

        /data/data/app_name/shared_prefs/

        3. 两种实现方式




案例:选项存储

        主界面如下:



        点击“设置”菜单,进入 选项屏幕:



        Welcome_text 修改前(Hello World):



        Welcome_text 修改(你好!):



        Welcome_text_color 修改前(black):



        Welcome_text_color 修改(blue):



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



        1. strings.xml。定义所需字符串。

<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>


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

<?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>


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



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

        (2)文件位置: /res/xml/。

        (3)元素类型:



<?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>


        4. activity_main.xml。在最后加一个 TextView,用来显示“欢迎文本”。



<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" />


        5. 在 Java 包下,创建 选项碎片 SettingsFragment,用来加载 选项屏幕 preferences.xml。

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);
    }
}


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

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();
    }
}


        7. 在功能清单文件中,注册 SettingsActivity。

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


        注:

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

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

@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);
    }


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

/**
     * 重绘界面
     * (由 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);
        }
    }



附   整个案例代码补充



        1. strings.xml。

<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>


        2. activity_main.xml。

<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>


        3. MainActivity。

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);
        }
    }
}
  • 大小: 23.2 KB
  • 大小: 35.7 KB
  • 大小: 22.2 KB
  • 大小: 7.3 KB
  • 大小: 25.7 KB
  • 大小: 28.1 KB
  • 大小: 28.4 KB
  • 大小: 24.4 KB
  • 大小: 57.1 KB
  • 大小: 25.3 KB
  • 大小: 24.5 KB
  • 大小: 25.6 KB
  • 大小: 13.8 KB
  • 大小: 23.8 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics