2.安卓基础之Android文件存储

1. Android中的测试

1.1 应用层的测试

测试常规的功能是否完善,不会出现致命的BUG.

1.2 Google 的CTS的测试

谷歌CTS,英文为 Compatibility Test Suite ,中文意思是兼容性测试,手机设备需要通过Android的兼容性测试(CTS),以确保在android上开发的程序在手机设备上都能运行.Google并没有在源代码中提供Android Market应用,因为他们希望所有设备生产商能够通过CTS测试.如果他们通过了CTS测试,那么就可以向Google申请使用Android market,Google才会给Market应用.

1.3 Framework的测试

在android 中谷歌程序员也将 junit 测试框架引入进来了.

1.4. android中测试程序的编写步骤
  • 编写一个类去继承 AndroidTestCase
  • 编写一个测试的运行的方法
  • 在manifest文件中添加如下内容

mainfest添加的内容

  • 在 application 元素下添加如下内容

添加类库

2. Log级别的分类

1
2
3
4
5
Log.v(TAG, "俺是 一个 详细 的日志 信息");
Log.i(TAG, "俺是 一个 一般的 的日志 信息");
Log.w(TAG, "俺是 一个 警告 的日志 信息");
Log.e(TAG, "俺是 一个 错误 的日志 信息");
Log.wtf(TAG, "俺是 一个xxxxx 的日志 信息");

查看窗口

3. android下保存数据

3.1 将数据保存到应用程序中(私有的)

保存数据存在的问题

是因为 , 这里的路径以及保存的方式都有问题 , 目前是运行在androd中, android底层是linux内核, linux 文件系统的根目录是 一个 / .

File file = new File(“info.txt”); 将数据保存到 linux 根目录 / 下, 而这时当前的应用程序不可能取得这样的权限的.

每个应用程序可以将数据保存到自己独有的一个文件夹下 :

独有的文件夹

3.2 android中图片的缓存策略:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
**MainActivity.java:**
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化控件
ed_qqnumber = (EditText) findViewById(R.id.qqnumber);
ed_qqpassword = (EditText) findViewById(R.id.qqpassword);
cbx = (CheckBox) findViewById(R.id.remember);
File file = new File(this.getFilesDir(), "info.txt");
//如果文件里面存在内容,显示数据
if(file.exists()&&file.length()>0){
//读取file中的数据,然后显示
try {
//111#itceo#111
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
String line = bufferedReader.readLine();
String num =line.split("#itceo#")[0];
String pwd = line.split("#itceo#")[1];
ed_qqnumber.setText(num);
ed_qqpassword.setText(pwd);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//点击登陆后执行 login 的方法
public void login(View view){
//获得输入框中写入的数据,trim()去掉字符串的首尾空格
String number = ed_qqnumber.getText().toString().trim();
String password = ed_qqpassword.getText().toString().trim();
if(TextUtils.isEmpty(number)||TextUtils.isEmpty(password)){
Toast.makeText(this, "请输入您的账号或密码!", 0).show();
return;
}
//判断是否勾选了checkbox,如果勾选了checkbox,那么就将QQ号和密码保存起来
boolean isChecked = cbx.isChecked();
if(isChecked){
try {
//如果勾选了,将数据保存起来.
File file = new File(this.getFilesDir(),"info.txt");
OutputStream outputStream = new FileOutputStream(file);
String value = number+"#itceo#"+password;
outputStream.write(value.getBytes());
outputStream.close();
Toast.makeText(this, "勾选,保存成功!", 0).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "勾选,但不保存成功!", 0).show();
}
}else {
Toast.makeText(this, "没勾选成功!", 0).show();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
activity_main.xml
<LinearLayout 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:orientation="vertical"
tools:context="net.itceo.qqlogin.MainActivity" >
<ImageView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/qq"
/>
<EditText
android:id="@+id/qqnumber"
android:hint="请输入账号:"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<EditText
android:id="@+id/qqpassword"
android:hint="请输入密码:"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<CheckBox
android:id="@+id/remember"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="请记住你的密码"/>
<Button
android:onClick="login"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="登陆"/>
</LinearLayout>

3.3 android中sdcard的细节问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化控件
ed_qqnumber = (EditText) findViewById(R.id.qqnumber);
ed_qqpassword = (EditText) findViewById(R.id.qqpassword);
cbx = (CheckBox) findViewById(R.id.remember);
File file = new File(Environment.getExternalStorageDirectory(), "info.txt");
//如果文件里面包含数据
if (file.exists()&&file.length()>0) {
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
String line = bufferedReader.readLine();
String num = line.split("#itceo#")[0];
String pwd = line.split("#itceo#")[1];
ed_qqnumber.setText(num);
ed_qqpassword.setText(pwd);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void login(View v){
//获得输入框的值
String number = ed_qqnumber.toString().trim();
String password = ed_qqpassword.toString().trim();
//判断是否填入了number和password的值
if (TextUtils.isEmpty(number)||TextUtils.isEmpty(password)) {
Toast.makeText(this, "请输入账号或密码", 0).show();
return;
}
//判断是否勾选了checkbox,如果勾选了checkbox,那么就将QQ和密码保存起来;
boolean isChecked = cbx.isChecked();
if (isChecked) {
try {
//说明勾选了,给提示!
// sdcard 做为 一个外部的 存储 设备, 有时候 sdcard 是处于 弹出状态, 未插入状态, 强制拔出 状态.
// 那么在这些 情况下,如果 要向 sdcard 中写数据, 为了 保证 数据 确切的存储, 提高用户的感受, 所以 , 在存储到
// sd 卡中之前, 会去动态 判断 sdcard 的状态,只有 在sdcard 是处于 挂载 的状态下 , 再去 写 sd 卡数据
String status = Environment.getExternalStorageState();//返回的状态
if (!Environment.MEDIA_MOUNTED.equals(status)) {//如果返回的状态非挂载
Toast.makeText(this, "请检查你的内存卡状态", 0).show();
return;
}
//返回内存卡可用的空闲空间
long freeSpace = Environment.getExternalStorageDirectory()
.getFreeSpace();
//拿到SD卡的总大小
Environment.getExternalStorageDirectory().getTotalSpace();
//拿到已经使用的大小
Environment.getExternalStorageDirectory().getUsableSpace();
//将返回的字节转换为单位
String avalabSize = Formatter.formatFileSize(this, freeSpace);
Toast.makeText(this, "你的可用大小为:" + avalabSize, 0).show();
File file = new File(Environment.getExternalStorageDirectory(),
"info.txt");
//取出数据
OutputStream outputStream = new FileOutputStream(file);
//写入数据
String value = number+"#itceo#"+password;
outputStream.write(value.getBytes());
outputStream.close();
Toast.makeText(this, "勾选成功", 0).show();
} catch (Exception e) {
Toast.makeText(this, "没勾选成功", 0).show();
}
}else{
Toast.makeText(this, "不勾选,是无法保存数据的", 0).show();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
activity_main.xml
<LinearLayout 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:orientation="vertical"
tools:context=".MainActivity" >
<ImageView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/qq"
/>
<EditText
android:id="@+id/qqnumber"
android:hint="请输入qq号码"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<EditText
android:id="@+id/qqpassword"
android:hint="请输入qq密码"
android:inputType="textPassword"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<CheckBox
android:id="@+id/remember"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="记住用户名和密码" />
<Button
android:onClick="login"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="登录" />
</LinearLayout>

3.4 android中文件权限问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/*
* 创建一个私有的文件
*
* 每个应用程序 都一个私有的文件夹, /data/data/net.itceo.filemode
*
*
* 私有的文件 ,只有当前的应用 自己可以去访问, 其他的应用没有办法 去访问,其他的应用既不可以读,也不可以写 
*/
public void getPrivateFile(View v) {
try {
File file = new File(this.getFilesDir(), "private.txt");
OutputStream out = new FileOutputStream(file);
out.write("private".getBytes());
out.close();
Toast.makeText(this, "写入私有文件成功", 0).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "写入私有文件失败 ", 0).show();
}
}
// 谷歌不推荐咱们这样做 : 引入了新的组件 --- contentProvider
// 创建一个只读的文件 :其他的应用可以去读但是不能去写 
public void getReadOnlyFile(View v) {
try {
FileOutputStream out = openFileOutput("readonly.txt",
Context.MODE_WORLD_READABLE);
out.write("readonly".getBytes());
out.close();
Toast.makeText(this, "写入只读文件成功", 0).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "写入只读文件失败 ", 0).show();
}
}
//写入只可写文件
public void getWriteOnlyFile(View v) {
try {
FileOutputStream out = openFileOutput("writeonly.txt",
Context.MODE_WORLD_WRITEABLE);
out.write("writeonly".getBytes());
out.close();
Toast.makeText(this, "写入只可写文件成功", 0).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "写入只可写文件失败 ", 0).show();
}
}
// 其他应用可以读也可以写的文件
public void getPublicFile(View v) {
try {
FileOutputStream out = openFileOutput("public.txt",
Context.MODE_WORLD_WRITEABLE+Context.MODE_WORLD_READABLE);
out.write("public".getBytes());
out.close();
Toast.makeText(this, "写入可读可写成功", 0).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "写入可读可写失败 ", 0).show();
}
}

3.5 android中SharedPreferences的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化控件
ed_qqnumber = (EditText) findViewById(R.id.qqnumber);
ed_qqpaswword = (EditText) findViewById(R.id.qqpassword);
cbx = (CheckBox) findViewById(R.id.remember);
sp = getSharedPreferences("config", 0);
//如果找到了number的值,那么就返回number的值,否则就返回这里的默认值
String num = sp.getString("number", "");
String pwd = sp.getString("password", "");
ed_qqnumber.setText(num);
ed_qqpaswword.setText(pwd);
}
//点击登录后会执行 login 方法
public void login(View v){
//获得输入框中写入的值
String number = ed_qqnumber.getText().toString().trim();
String password= ed_qqpaswword.getText().toString().trim();
//判断是否输入了number以及password的值
if (TextUtils.isEmpty(number)||TextUtils.isEmpty(password)) {
Toast.makeText(this, "请输入QQ号或密码", 0).show();
return;
}
//判断是否勾选了checkbox,如果勾选了即把数据保存起来
boolean isChecked = cbx.isChecked();
if(isChecked){
try {
// 将数据 保存起来,使用 sharedPreference
// config文件将会生成 在 应用的文件夹下 --- 一个 xml格式 的文件
// 一般情况下,应用自己的数据只有当前应用 自己可以去读, 所以通常会写
sp = getSharedPreferences("config", 0);
Editor editor = sp.edit();
editor.putString("number", number);
editor.putString("password", password);
editor.commit();
Toast.makeText(this, "勾选了,保存成功", 0).show();
} catch (Exception e) {
Toast.makeText(this, "勾选了,不保存成功", 0).show();
}
}else{
Toast.makeText(this, "没勾选", 0).show();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
activity_main.xml
<LinearLayout 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:orientation="vertical"
tools:context=".MainActivity" >
<ImageView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/qq"
/>
<EditText
android:id="@+id/qqnumber"
android:hint="请输入qq号码"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<EditText
android:id="@+id/qqpassword"
android:hint="请输入qq密码"
android:inputType="textPassword"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<CheckBox
android:id="@+id/remember"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="记住用户名和密码" />
<Button
android:onClick="login"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="登录" />
</LinearLayout>

3.6 android中模拟setting设置使用sp保存数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
cbx = (CheckBox) findViewById(R.id.cbx);
sb = (SeekBar) findViewById(R.id.seekBar);
sp = this.getSharedPreferences("config", 0);
boolean isCheckStatus = sp.getBoolean("isChecked", false);
int pgs = sp.getInt("progress", 0);
sb.setProgress(pgs);
cbx.setChecked(isCheckStatus);
cbx.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
Editor edit = sp.edit();
edit.putBoolean("isChecked", arg1);
}
});
sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
//停止 拖动 seek bar
@Override
public void onStopTrackingTouch(SeekBar arg0) {
//拿到 停止 拖动的时刻的进度
int progress = arg0.getProgress();
//将进度条保存到sharedPreference中
Editor editor = sp.edit();
editor.putInt("progress",progress);
editor.commit();
}
//开始 拖动 seek bar
@Override
public void onStartTrackingTouch(SeekBar arg0) {
}
@Override
public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
}
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Activity_Main.xml
<LinearLayout 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:background="#113965"
android:orientation="vertical"
tools:context=".MainActivity" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#000000">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="自动旋转屏幕"
android:textColor="#ffffff"/>
<CheckBox android:id="@+id/cbx"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"/>
</RelativeLayout>
<View android:layout_width="fill_parent"
android:layout_height="1dip"
android:background="#ff0000"/>
<SeekBar
android:id="@+id/seekBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:visibility="visible"/>
</LinearLayout>

3.7 android中XmlSerializer的应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
MainActivity.java
package net.itceo.studentsystem;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import org.xmlpull.v1.XmlSerializer;
import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Xml;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.Toast;
public class MainActivity extends Activity {
private EditText ed_ssname;
private EditText ed_ssnumber;
private RadioGroup rgb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//控件的初始化
ed_ssname = (EditText) findViewById(R.id.studentname);
ed_ssnumber = (EditText) findViewById(R.id.studentnumber);
rgb = (RadioGroup) findViewById(R.id.radiogb);
}
public void save(View v){
String studentName = ed_ssname.getText().toString().trim();
String studentNumber = ed_ssnumber.getText().toString().trim();
if(TextUtils.isEmpty(studentName)||TextUtils.isEmpty(studentNumber)){
Toast.makeText(this, "学生姓名或密码不能为空", 0).show();
return;
}
//获得性别
int id = rgb.getCheckedRadioButtonId();
String sex = "男";
if(id==R.id.male){
sex = "男";
}else if(id==R.id.female){
sex = "女";
}
try {
File file = new File(getFilesDir(), studentName+".xml");
OutputStream outputStream = new FileOutputStream(file);
// 专门生成xml 文件的 序列化器
XmlSerializer serializer = Xml.newSerializer();
serializer.setOutput(outputStream, "UTF-8");
// <?xml version="1.0" encoding="utf-8" standalone?>
serializer.startDocument("UTF-8", true);
serializer.startTag(null, "student");
//设置 文本信息 -- 学生的姓名
serializer.startTag(null, "name");
serializer.text(studentName);
serializer.endTag(null, "name");
serializer.startTag(null, "number");
serializer.text(studentNumber);
serializer.endTag(null, "number");
serializer.startTag(null, "sex");
serializer.text(sex);
serializer.endTag(null, "sex");
serializer.endTag(null, "student");
serializer.endDocument();
outputStream.close();
Toast.makeText(this, "保存"+studentName+"信息 成功 ...", 0).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "保存"+studentName+"信息 失败 .... ...", 0).show();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
Activity_main.xml
<LinearLayout 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:orientation="vertical"
tools:context=".MainActivity" >
<EditText
android:id="@+id/studentname"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="请输入学生的姓名" />
<EditText
android:id="@+id/studentnumber"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="请输入学生的学号" />
<RadioGroup
android:orientation="horizontal"
android:id="@+id/radiogb"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<RadioButton
android:id="@+id/male"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="wrap_content"
android:checked="true"
android:text="男" />
<RadioButton
android:id="@+id/female"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="女" />
</RadioGroup>
<Button
android:text="保存"
android:onClick="save"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:text="查询"
android:onClick="save"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/tv_display"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>

4 总结

不够细心,当点击一次就保存一次.不用考虑循环问题.