Android数据存储

作者: wxyass 分类: Android 发布时间: 2014-10-13 16:16

导语

数据存储介绍

Android 数据存储

测试

  • 黑盒测试
    • 测试人员不知道源代码
  • 白盒测试
    • 测试人员知道源代码, 写测试用例

按测试粒度(精细度)区分

  • 方法测试 (function test)
  • 集成测试 (integration test)
  • 系统测试 (system test)

单元测试框架(Junit)

Android的代码只能运行在手机中的Dalvik虚拟机里, 在PC机的JVM下会报错异常. 写测试用例, 通过将测试代码上传到Android手机或模拟器中运行.

Android下单元测试的流程

文件权限

  1. 写业务逻辑类,里面有待测试的方法
    public class CalcService {
    
        public int sum(int a,int b){
            return a+b;
        }
    }
    
  2. 写测试用例类, 一个类继承AndroidTestCase
  3. 写测试方法public void testAdd() throws Exception{}
    public class TestCalcService extends AndroidTestCase{
    
        public void testSum(){
            CalcService cs = new CalcService();
            int result = cs.sum(12, 3);
            //断言 判断结果是否与预期一致,如果不一致,抛出异常
            assertEquals(15, result);
    
        }
    }
    
  4. 单元测试需要配置清单文件??????
    • 在AndroidManifest.xml文件中配置
    • 1 指定测试用的指令集 在manifest的子节点,包名指向MainActivity.java所在的包名
    • 2 指定测试用的库 在application节点下

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.itheima.junit"
    android:versionCode="1"
    android:versionName="1.0" >

    <!--    1. 指定测试用的指令集 在manifest的子节点 -->
    <instrumentation
        android:name="android.test.InstrumentationTestRunner"
        android:targetPackage="com.itheima.junit" >
    </instrumentation>

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name">

            <!--   2. 指定测试用的库 在application节点下-->
            <uses-library android:name="android.test.runner"/>

    </application>
</manifest>
  1. 选中测试方法, 右键 Run as -> Android JUnit Test

Android 下的logcat

  • Log.v : verbose 提示 黑色
  • Log.d : debug 调试 蓝色
  • Log.i : info 提醒 绿色
  • Log.w : warn 警告 橙色
  • Log.e : error 错误 红色

保存数据到SD卡 /mnt/sdcard/info.txt

  • 获取外置sd卡目录: Environment.getExternalStorageDirectory()
  • 获取挂载状态: Environment.getExternalStorageState()
  • 获取sd卡剩余空间:Environment.getExternalStorageDirectory().getUsableSpace();

  • 示例


public void login(View view) {
    // 点击事件
    // 1. 获取用户名密码
    String qq = et_qq.getText().toString().trim();
    String pwd = et_pwd.getText().toString().trim();

    try {
        // 检查数据, 如果有一个是空字符串, 则弹出吐司提醒?????
        if (TextUtils.isEmpty(qq) || TextUtils.isEmpty(pwd)) {
            // 吐司(面包), 在界面上显示一个提示, 一定记住要调用show()方法.

            // Context上下文
            Toast.makeText(this, "用户名或密码不能为空", Toast.LENGTH_SHORT).show();
        } else {
            // System.out.println("qq: " + qq + " pwd: " + pwd);
            // 检查是否勾选了
            boolean isChecked = cb_remember.isChecked();
            if (isChecked) {
                // 要记住密码
                Log.d(TAG, "勾选了记住密码");
                // 保存当前用户名密码 到sdcard
                // File file = new File("/mnt/sdcard/info.txt");
                // /storage/sdcard0
                // /mnt/storage
                // 获取外置sd卡挂载状态?????
                String state = Environment.getExternalStorageState();
                if (Environment.MEDIA_MOUNTED.equals(state)) {
                    // sd卡已挂载,可以写入

                    // 获取sd卡剩余空间
                    long usableSpace = Environment
                            .getExternalStorageDirectory().getUsableSpace();
                    System.out.println("usableSpace: " + usableSpace);

                    // 获取外置SD卡的目录????
                    File path = Environment.getExternalStorageDirectory();
                    FileOutputStream fos = new FileOutputStream(new File(
                            path, "info.txt"));
                    String str = qq + "##" + pwd;
                    fos.write(str.getBytes());
                    fos.close();

                    System.out.println("---------------------------" + str);
                } else {
                    // sd未挂载
                    Toast.makeText(this, "保存失败, 请检查sd卡", Toast.LENGTH_SHORT)
                            .show();
                }
            } else {
                // 不记住密码
                Log.d(TAG, "不记住密码");
            }
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

从SD卡读取数据 并显示到控件上

    // 读取之前的数据,并显示到控件上
    try {
        // 得到输入流, 读取数据
        File path = Environment.getExternalStorageDirectory();
        FileInputStream fis = new FileInputStream(
                new File(path, "info.txt"));
        //读取的是字符流
        BufferedReader br = new BufferedReader(new InputStreamReader(fis));
        // 读取一行
        String line = br.readLine();
        // aaa##123
        String qq = line.split("##")[0];
        String pwd = line.split("##")[1];
        et_qq.setText(qq);
        et_pwd.setText(pwd);

    } catch (Exception e) {
        e.printStackTrace();
    }

保存数据到内部存储设备 /data/data/包名/

  • 应用私有文件夹, 默认情况下, 其他应用无法访问. 保证其数据安全
  • Context.getFilesDir() == /data/data/包名/files 用户文件目录
  • Context.getCacheDir() == /data/data/包名/cache 缓存目录

示例:

    public void login(View v) {
    // 点击事件
    // 1. 获取用户名密码
    String qq = et_qq.getText().toString().trim();
    String pwd = et_pwd.getText().toString().trim();
    try {
        // 检查数据, 如果有一个是空字符串, 则弹出吐司提醒
        if (TextUtils.isEmpty(qq) || TextUtils.isEmpty(pwd)) {
            // 吐司(面包), 在界面上显示一个提示, 一定记住要调用show()方法.
            // Context上下文
            Toast.makeText(this, "用户名或密码不能为空", Toast.LENGTH_SHORT).show();
        } else {
            // System.out.println("qq: " + qq + " pwd: " + pwd);
            // 检查是否勾选了
            boolean isChecked = cb_remember.isChecked();
            if (isChecked) {
                // 要记住密码
                // 保存当前用户名密码 到sdcard
                // 获取外置sd卡挂载状态
                String state = Environment.getExternalStorageState();
                if (Environment.MEDIA_MOUNTED.equals(state)) {
                    // sd卡已挂载,可以写入
                    // 获取sd卡剩余空间
                    long usableSpace = Environment
                            .getExternalStorageDirectory().getUsableSpace();
                    System.out.println("usableSpace: " + usableSpace);
                    // 获取外置SD卡的目录
                    File path = Environment.getExternalStorageDirectory();
                    FileOutputStream fos = new FileOutputStream(new File(
                            path, "info.txt"));
                    String str = qq + "##" + pwd;
                    fos.write(str.getBytes());
                    fos.close();

                    System.out.println("---------------------------" + str);
                } else {
                    // sd未挂载
                    Toast.makeText(this, "保存失败, 请检查sd卡", Toast.LENGTH_SHORT)
                            .show();
                }
            } else {
                // 不记住密码
                Log.d(TAG, "不记住密码");
            }
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
    }

Android权限机制

  • MODE_PRIVATE 私有文件
  • MODE_WORLD_READABLE 全局可读文件
  • MODE_WORLD_WRITEABLE 全局可写文件
  • MODE_WORLD_READABLE + MODE_WORLD_WRITEABLE 全局可读可写

file_mode.png

文件权限

(重点)Android下,xml数据解析

  • a. 创建xml解析器
  •     XmlPullParser parser = Xml.newPullParser();
    
  • b. 初始化xml解析器, 指定解析哪个流, 以什么编码解析
        parser.setInput(is, "utf-8");
    
  • c. 解析xml数据
        while(type != XmlPullParser.END_DOCUMENT){ // 直到文档的结束
            // 读取数据
            ...
            type = parser.next(); // 到下一个
        }
    
  • d. 扫尾工作
    • 关闭数据流

// 读取之前的数据,并显示到控件上
try {
    // 得到输入流, 读取数据
    File cache = getCacheDir();
    FileInputStream fis = new FileInputStream(new File(cache,
            "user.xml"));
    // a. 创建xml解析器
    XmlPullParser pullParse = Xml.newPullParser();
    // b. 初始化xml解析器, 指定解析哪个流, 以什么编码解析
    pullParse.setInput(fis, "UTF-8");
    // c. 解析xml数据
    int type = pullParse.getEventType();// xml标签节点类型 头标签返回类型是0 根结束标签是1
    while (type != XmlPullParser.END_DOCUMENT) {// 循环的结束条件
        if (type == XmlPullParser.START_TAG) {
            if ("qq".equals(pullParse.getName())) {
                String qq = pullParse.nextText();
                et_qq.setText(qq);
            } else if ("pwd".equals(pullParse.getName())) {
                String pwd = pullParse.nextText();
                et_pwd.setText(pwd);
            }
        }
        // 循环 下一个
        type = pullParse.next();
    }
    // d 关闭数据流
    fis.close();

} catch (Exception e) {
    e.printStackTrace();
    System.out.println("解析异常!");
}

Android下,xml的生成 (序列化) (将JavaBean信息存放到xml中)

a. 创建Xml序列化器

    XmlSerializer serializer = Xml.newSerializer();

b. 初始化xml序列化器, 设置输出流, 指定编码集

    serializer.setOutput(fos, "utf-8");

c. 写xml数据
// 文档的开头
serializer.startDocument(“utf-8”, true);
serializer.startTag(null, “info”);

    serializer.startTag(null, "qq");
    serializer.text(qq);
    serializer.endTag(null, "qq");

    serializer.startTag(null, "pwd");
    serializer.text(pwd);
    serializer.endTag(null, "pwd");

    serializer.endTag(null, "info");
         // 文档的结束
    serializer.endDocument();

d. fos.close();

示例:

public void login(View v) {
    // 1. 获取用户名密码
    String qq = et_qq.getText().toString().trim();
    String pwd = et_pwd.getText().toString().trim();

    try {
        // 检查数据, 如果有一个是空字符串, 则弹出吐司提醒
        if (TextUtils.isEmpty(qq) || TextUtils.isEmpty(pwd)) {
            // 吐司(面包), 在界面上显示一个提示, 一定记住要调用show()方法.
            // Context上下文
            Toast.makeText(this, "用户名或密码不能为空", Toast.LENGTH_SHORT).show();
        } else {
            // 检查是否勾选了
            boolean isChecked = cb_remember.isChecked();
            if (isChecked) {
                // 要记住密码
                // 获取临时缓存目录cache
                File cacheDir = this.getCacheDir();
                FileOutputStream fos = new FileOutputStream(new File(
                        cacheDir, "user.xml"));
                // a. 创建Xml序列化器
                XmlSerializer serializer = Xml.newSerializer();
                // b. 初始化xml序列化器, 设置输出流, 指定编码集
                serializer.setOutput(fos, "utf-8");
                // c. 写xml数据
                // 文档的开头
                serializer.startDocument("utf-8", true);
                serializer.startTag(null, "info");

                serializer.startTag(null, "qq");
                serializer.text(qq);
                serializer.endTag(null, "qq");

                serializer.startTag(null, "pwd");
                serializer.text(pwd);
                serializer.endTag(null, "pwd");

                serializer.endTag(null, "info");
                // 文档的结束
                serializer.endDocument();

                Toast.makeText(this, "保存成功", 0).show();

            } else {
                // 不记住密码
                Log.d(TAG, "不记住密码");
            }
        }

    } catch (Exception e) {
        e.printStackTrace();
    }

}
  • OutOfMemory (OOM) 内存溢出

SharedPreference

  • 保存位置: /data/data/包名/shared_prefs/xxx.xml
  1. 初始化SharedPreferences arg0:文件名 arg1:权限
    SharedPreferences sp = this.getSharedPreferences("config", MODE_PRIVATE);
    
  2. 通过SharedPreferences获取编辑器
    Editor editor = sp.edit();
    
  3. 写入数据
    editor.putString("qq", qq);
    editor.putString("pwd", pwd);
    editor.putBoolean("isChecked", isChecked);
    
  4. 提交数据
    editor.commit();
    

-示例—————————

//点击事件
public void login(View v){
    // 点击事件
    // 1. 获取用户名密码
    String qq = et_qq.getText().toString().trim();
    String pwd = et_pwd.getText().toString().trim();

    //2 用户名密码是否为空
    if (TextUtils.isEmpty(qq)||TextUtils.isEmpty(pwd)) {
        //用户名或密码为空 吐司
        Toast.makeText(this, "用户名或密码不能为空", 0).show();
    } else {
        //用户名和密码都不为空
        //判断是否记住密码
        boolean isCheck = cb_remember.isChecked();
        if (isCheck) {
            //记住用户名密码,将其保存在内部存储设备
            //初始化SharedPreferences
            SharedPreferences sp = this.getSharedPreferences("user",MODE_PRIVATE );
            // 2. 通过SharedPreferences获取编辑器
             Editor edit = sp.edit();
            // 3. 写入数据
             edit.putString("qq", qq);
             edit.putString("pwd", pwd);
             edit.putBoolean("isCheck", isCheck);
            // 4. 提交数据
            edit.commit();
            Toast.makeText(this,"保存成功", 0).show();
        } else {
            //不记住用户名密码
            Toast.makeText(this,"没保存登录成功", 0).show();
        }
    }
}

读取数据

    // 1. 初始化SharedPreferences
    SharedPreferences sp = this.getSharedPreferences("config", MODE_PRIVATE);

    // 2. 读取数据, 设置数据
    String qq = sp.getString("qq", "");
    boolean isChecked = sp.getBoolean("isChecked", false);

-示例——————————-

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // 查找用户名输入框
    et_qq = (EditText) findViewById(R.id.et_qq);
    // 查找密码输入框
    et_pwd = (EditText) findViewById(R.id.et_pwd);
    // 查找CheckBox
    cb_remember = (CheckBox) findViewById(R.id.cb_remember);

    //回显用户名密码,显示在控件上
    //1 初始化SharedPreferences
    SharedPreferences sp = this.getSharedPreferences("user",MODE_PRIVATE );
    //2 读取数据,设置数据
    String qq = sp.getString("qq", "");
    et_qq.setText(qq);

    String pwd = sp.getString("pwd", "");
    et_pwd.setText(pwd);

    boolean isCheck = sp.getBoolean("isCheck",false);
    cb_remember.setChecked(isCheck);
}
  • # 超级管理员用户
  • $ 普通用户

836959067

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

邮箱地址不会被公开。 必填项已用*标注