一、测试相关:
测试方法:
白盒测试
黑盒测试
adb shell
monkey 5000(点击次数):猴子测试
测试强度
冒烟测试
压力测试
测试粒度
方法测试
单元测试
集成测试
系统测试
二、安卓中的单元测试
安卓中不能使用main方法,也不能够使用原始的 @Test 框架,
因为android是要发布到Dalvike虚拟机中运行的,如果直接运行则使用的是eclipse中的jvm,
如果需要在android中进行测试,则需要使用如下方法:
(1)写一个类继承AndroidTestCase
(2)在类中写测试方法
该方法需满足:必须是public void 无参
(3)在清单文件AndroidManifest.xml中添加测试配置
a.在清单文件的根目录下加载指令集
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetPackage="net.csing.junit">
</instrumentation>
b.在清单文件中application下配置
<uses-library android:name="android.test.runner"/>
(4)在eclipse中的outline中找到要测试的方法,右键 按照Run as Android Junit Test
三、logcat的使用
console是pc机jvm的控制台输出
而安卓程序是运行在dalvik中的,直接输出是无法打印到console中的。
可通过android提供的logcat查看相关信息。日志等级:
verbose:提醒 黑色
debug: 调试 蓝色
info: 信息 绿色
warn: 警告 橙色
error: 错误 红色
如果使用syso进行输出,默认是info级别信息。
也可以使用Log对象打印不同级别的信息,如:
Lod.v(String tag,String message);
Lod.d(String tag,String message);
Lod.i(String tag,String message);
Lod.w(String tag,String message);
Lod.e(String tag,String message);
在logcat中,我们可以输入tag名称直接定位信息。
android 支持debug调试,尽量使用debug调试。
四、文件的存取
1.保存数据到内部存储空间
(1)路径问题
采用动态路径的方法:
获取当前应用的下的files路径,即:[应用包名]/files
context.getFilesDir();
通常我们将数据保存在该路径下,可以实现长久保存。
获取当前应用的下的cache路径,即:[应用包名]/cache
context.getCacheDir();
通常我们将缓存文件保存在当前路径下,如果系统运行内存不足,则系统将清理当前文件夹下的内容以释放内存。谷歌建议缓存使用完毕后即清理。
在应用中执行“清除数据”将清除files中的数据,执行“清除缓存”将清除cache中的数据。
(2)文件的读写
创建输出流:
将数据保存到内部存储空间的files中。
FileOutputStream fos=new FileOutputStream(context.getFilesDir()+"/info.txt");
将数据保存到内部存储空间的cache中。
FileOutputStream fos=new FileOutputStream(context.getCacheDir()+"/cache.txt");
随后采用文件操作的方式将数据写入到fos中即可,此方式即可实现将数据保存到手机的内部存储空间中。
2.保存数据到外部存储空间
(1)路径问题
sdcard路径为/mnt/sdcard/
但部分手机厂商可能修改了路径,导致上述路径出现问题,如双sdcard卡情况。
通过以下方式可以动态获得sdcard的路径:
Environment.getExternalStorageDirectory();
表示sdcard卡根目录的files对象。
获取路径后即可按照常规的文件操作方式对文件进行读写。
(2)sdcard卡状态问题
sdcard由于其可卸载和挂载性导致状态不确定,此时我们可以通过如下方式判断sdcard卡的状态。
Environment.getExternalStorageState();
(3)需要注意的问题
a.安卓手机用包名唯一区分一个引用。
b.sdcard的访问需要权限。
c.默认情况下sdcard的读取不需要权限。可通过“开发者选项”对sdcard的读取设置读写权限。模拟器不支持,部分真机支持。
d.应用设计时,在权限配置中,一般读权限和写权限都需要添加。
3.文件流的获取
在android中提供了如下的方式对文件流进行获取
FileInputStream in=context.openFileInput(filename);
直接获取输入流,指向:[应用包名]/files/filenaem
FileOutputStream out=context.openFileOutput(filename,MODE);
直接获取输出流,指向:[应用包名]/files/filename
五、文件的访问权限
(1)文件的操作MODE中总共有四种方式:
MODE_PRIVATE 只有当前应用可写,如果之前文件已经存在,则在写的时候原内容将被覆盖。
MODE_APPEND 只有当前应用可写,如果之前文件已经存在,则在写的时候追加内容。
MODE_WORLD_READABLE 文件全局可读,即其他应用也可以读。
MODE_WORLD_WRITEABLE 文件全局可写,即其他应用也可以写。
MODE_WORLD_READABLE + MODE_WORLD_READABLE
or
MODE_WORLD_READABLE & MODE_WORLD_WRITEABLE
可通过+或者&进行权限合并,实现既可读又可写。
(2)在linux中使用10位二进制表示文件的访问权限。
第一位表示:文件的类型:
前三位表示:当前用户对文件的访问权限:是否可读(r),是否可写(w),是否可执行(x)
中间三位表示:当前用户所在的组中其他用户对文件的访问权限:是否可读,是否可写,是否可执行。
最后三位表示:当前组以外的其他用户对文件的访问权限。
注意:android中每一个应用程序都独占一个用户,并且通常情况下该用户独占一个用户组。
六、SharedPreferences数据存储
(1)SharedPreferences是什么?
SharedPreferences是安卓为我们提供的存储键值对类型的快速API,本质是[应用目录]/shared_prefs/xx.xml 文件,里面通常存储着应用的配置信息,可以方便的存储键值类型的信息。
(2)数据的读写
/*
* SharedPreferences文件的存储
*/
SharedPreferences sp=getSharedPreferences("config", MODE_PRIVATE);
Editor editor=sp.edit();
editor.putString("username", "cs001");
editor.putBoolean("isBoy", true);
/*
* SharedPreferences文件的读取
*/
String username=sp.getString("username", "cs");
Boolean isBoy=sp.getBoolean("isBoy", false);
SharedPreferences可以存取int,float,double,string,boolean,甚至是map,set等多种类型的值。
七、XML文件的序列化
(1)什么是xml文件的序列化?
XML序列化是将对象的公共属性和字段转换为XML格式,以便存储或传输的过程。反序列化则是从XML输出中重新创建原始状态的对象。XML序列化中最主要的类是XmlSerializer类。它的最重要的方法是Serialize和Deserialize方法。
(2)注意事项
序列化的类必须要求无参构造函数,默认的也可以。但注意当默认的无参构造函数被覆盖时,要补上一个无参构造函数。另外,私有属性,只读属性是不能被序列化的。
(3)实现过程
在此过程中我们将Message类进行了序列化,该类中包含的属性为:id,from,to,content。类似短信备份的部分内容。
//1.创建序列化工具
XmlSerializer serializer = Xml.newSerializer();
FileOutputStream os;
try {
//2.指定需要序列化的xml文件对象。
os = this.openFileOutput("back_sms.xml", MODE_PRIVATE);
//3.创建序列化工具域xml文件对象间的联系。
serializer.setOutput(os, "utf-8");
//4.开始序列化
serializer.startDocument("utf-8", true);
serializer.startTag(null, "Msgs");
for (Message message : list) {
serializer.startTag(null,"msg");
serializer.startTag(null, "from");
serializer.text(message.getFrom());
serializer.endTag(null, "from");
serializer.startTag(null, "to");
serializer.text(message.getTo());
serializer.endTag(null, "to");
serializer.startTag(null, "content");
serializer.text(message.getContent());
serializer.endTag(null, "content");
serializer.endTag(null,"msg");
}
serializer.endTag(null, "Msgs");
//5.序列化文档结束
serializer.endDocument();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
八、XML文件解析
(1)需要解析的文件
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<weather>
<channel id='1'>
<city>北京</city>
<temp>38°</temp>
<wind>5</wind>
<pm250>888</pm250>
</channel>
<channel id='2'>
<city>上海</city>
<temp>30°</temp>
<wind>2</wind>
<pm250>555</pm250>
</channel>
</weather>
(2)解析过程
a.获取解析对象
InputStream inputStream = this.getClass().getClassLoader()
.getResourceAsStream("weather.xml");
b.创建解析器:
XmlPullParser parser = Xml.newPullParser();
c.建立解析器与解析对象间的联系:
parser.setInput(inputStream, "utf-8");
//获取要处理的当前事件的状态(类型)
//type:the type of the current event (START_TAG, END_TAG, TEXT, etc.)
int type = parser.getEventType();
d.解析文件
Channel chanel = null;
List<Channel> list=null;
while (XmlPullParser.END_DOCUMENT != type) {
switch (type) {
case XmlPullParser.START_DOCUMENT:
list=new ArrayList<Channel>();
break;
case XmlPullParser.START_TAG:
if ("channel".equals(parser.getName())) {
chanel = new Channel();
chanel.setId(parser.getAttributeValue(null, "id"));
}else if ("city".equals(parser.getName())) {
chanel.setCity(parser.nextText());
}else if ("temp".equals(parser.getName())) {
chanel.setTemp(parser.nextText());
}else if ("pm250".equals(parser.getName())) {
chanel.setPm250(parser.nextText());
}else if ("wind".equals(parser.getName())) {
chanel.setWind(parser.nextText());
}
break;
case XmlPullParser.END_TAG:
if ("channel".equals(parser.getName())) {
list.add(chanel);
chanel = null;
}
break;
default:
break;
}
//获取下一个要解析的事件类型
type = parser.next();
}
e.显示解析内容
/*
* 将获取的xml信息显示到activity页面中。
*/
TextView tv_city = (TextView) findViewById(R.id.tv_city);
TextView tv_temp = (TextView) findViewById(R.id.tv_temp);
TextView tv_wind = (TextView) findViewById(R.id.tv_wind);
TextView tv_pm250 = (TextView) findViewById(R.id.tv_pm250);
tv_city.setText(list.get(0).getCity());
tv_temp.setText("温度:"+list.get(0).getTemp());
tv_wind.setText("风力:"+list.get(0).getWind()+"级");
tv_pm250.setText("pm250:"+list.get(0).getPm250());