Android数据存储
导语
数据存储介绍
Android 数据存储
测试
- 黑盒测试
- 测试人员不知道源代码
- 白盒测试
- 测试人员知道源代码, 写测试用例
按测试粒度(精细度)区分
- 方法测试 (function test)
- 集成测试 (integration test)
- 系统测试 (system test)
单元测试框架(Junit)
Android的代码只能运行在手机中的Dalvik虚拟机里, 在PC机的JVM下会报错异常. 写测试用例, 通过将测试代码上传到Android手机或模拟器中运行.
Android下单元测试的流程
- 写业务逻辑类,里面有待测试的方法
public class CalcService { public int sum(int a,int b){ return a+b; } }
- 写测试用例类, 一个类继承AndroidTestCase
- 写测试方法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); } }
- 单元测试需要配置清单文件??????
- 在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>
- 选中测试方法, 右键 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
- 初始化SharedPreferences arg0:文件名 arg1:权限
SharedPreferences sp = this.getSharedPreferences("config", MODE_PRIVATE);
- 通过SharedPreferences获取编辑器
Editor editor = sp.edit();
- 写入数据
editor.putString("qq", qq); editor.putString("pwd", pwd); editor.putBoolean("isChecked", isChecked);
- 提交数据
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