Android基础笔记(二)
测试的相关概念
好的程序不是开发出来的,是测试出来的。
- 根据是否知道源程序源码:
- 黑盒测试:不知源码,只是测试程序的功能
- 白盒测试:知道源码,根据源代码进行测试
- 根据测试的粒度:(模块的大小)
- 单元测试:unit test
- 功能测试:function test
- 集成测试:integration test :几个模块的测试,服务器/客户端的联调
- 系统测试:system test: JavaEE企业级开发中常常用到
- 根据测试的次数:(暴力测试)
- ① 冒烟测试:smoke test,不停的执行操作,直到系统崩溃
- ② 猴子测试,测试方法如下
-
Adb shell:进入模拟器目录,monkey 2000,通过monkey是随机点击2000次
# monkey –p 包名 次数:只测试某个应用程序 adb shell monkey -p com.bzh.beijingwisdom 2000
- ③ 压力测试:pressure test
Android中的单元测试
- 手动增加单元测试的步骤
- ① 写一个类继承
AndroidTestCase
-
② 在清单文件中增加指令集
<instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="程序包名" > </instrumentation>
-
③ 在清单文件下的
application
节点下增加测试库<uses-library android:name="android.test.runner"/>
- 创建Android测试工程进行测试
-
创建工程
-
创建后的清单文件
日志猫的介绍
- Android LogCat的获取有两种方式:
- 1、DDMS提供的LogCat视图
- 2、通过adb命令行
- DDMS提供的LogCat视图如下
- ① 如果该视图没有打开,点击window->showview->other->android->Logcat来进行选择
-
② 视图的左侧可以选择或者添加过滤信息,运行一个应用程序时,此处会默认创建一个该包的过滤。视图的右上角区域用于选择LogCat的log级别,共有verbose、debug、info、warn、error、assert6个可选项。如图所示:
-
③该视图的主体部分是log的详细信息,包括错误级别(Level)、时间(Time)、进程ID(PID)、线程ID(TID)、应用程序包名(Application)、标签(Tag)、日志正文(Text)。
其中的TID并不等同于Java中的Thread.currentThread().getId(),而是我们Linux中的Thread ID,跟PID相同。 - LogCat日志的级别及使用
- android.util.Log常用的方法有以下5个:
- Log.v() Log.d() Log.i() Log.w() 以及 Log.e() 。
- 根据首字母对应VERBOSE,DEBUG,INFO, WARN,ERROR。
Log.v 的调试颜色为黑色的,任何消息都会输出,这里的v代表verbose啰嗦的意思,平时使用就是Log.v(“”,”“);
Log.d的输出颜色是蓝色的,仅输出debug调试的意思,但他会输出上层的信息,过滤起来可以通过DDMS的Logcat标签来选择.
Log.i的输出为绿色,一般提示性的消息information,它不会输出Log.v和Log.d的信息,但会显示i、w和e的信息,System.out输出信息是Info级别
Log.w的意思为橙色,可以看作为warning警告,一般需要我们注意优化Android代码,同时选择它后还会输出Log.e的信息。
Log.e为红色,可以想到error错误,这里仅显示红色的错误信息,这些错误就需要我们认真的分析,查看栈的信息了。
程序中我们可以使用Log类来输出信息
结果:
登陆案例
获取/data/data/com.xxx.xxx/files路径
String savePath = MainActivity.this.getFilesDir().getPath();
直接使用AndroidAPI获取内部存储路径的输入、输出流
// 1
FileInputStream fis = context.openFileInput("info3.txt");
// 2
FileOutputStream fos = context.openFileOutput("info3.txt", Context.MODE_PRIVATE);
把数据保存到SD卡上
增加权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
获取SD卡的存储路径
String savePath = Environment.getExternalStorageDirectory().getPath();
Android中几个常用的目录
- 内部应用程序的默认文件路径
- 使用的API:
context.getFilesDir().getPath()
-
路径:
/data/data/com.itheima.getsdavail/files
// /data/data/com.itheima.getsdavail/files Log.i(TAG, "内部应用程序的默认文件目录:" + getFilesDir().getPath());
- 内部应用程序的默认缓存路径
- 使用的API:
context.getCacheDir().getPath()
-
路径:
/data/data/com.itheima.getsdavail/cache
// /data/data/com.itheima.getsdavail/cache Log.i(TAG, "内部应用程序的默认缓存目录:" + getCacheDir().getPath());
- SD卡应用程序的默认文件目录
- 使用的API:
context.getExternalFilesDir(null).getPath()
-
路径:
/mnt/sdcard/Android/data/com.itheima.getsdavail/files
// /mnt/sdcard/Android/data/com.itheima.getsdavail/files Log.i(TAG, "SD卡应用程序的默认文件目录:" + getExternalFilesDir(null).getPath());
- SD卡应用程序的默认缓存目录
- 使用的API:
context.getExternalCacheDir().getPath()
-
路径:
/mnt/sdcard/Android/data/com.itheima.getsdavail/cache
// /mnt/sdcard/Android/data/com.itheima.getsdavail/cache Log.i(TAG, "SD卡应用程序的默认缓存目录:" + getExternalCacheDir().getPath());
- SD卡根路径
- 使用的API:
Environment.getExternalStorageDirectory().getPath()
-
路径:
/mnt/sdcard
// /mnt/sdcard Log.i(TAG, "SD卡根路径:" + Environment.getExternalStorageDirectory().getPath());
获取SD卡的大小及可用空间
Andoird2.3版本以上的获取方法
// 获取到SD卡目录
File file = Environment.getExternalStorageDirectory();
TextView tvTotal = (TextView) findViewById(R.id.tv_total);
// 获取SK卡目录的总共空间大小,返回值为long型
long totalSpace = file.getTotalSpace();
// 使用AndroidAPI进行数据的格式化
String total = Formatter.formatFileSize(this, totalSpace);
tvTotal.setText(total);
TextView tvAvail = (TextView) findViewById(R.id.tv_avail);
// 获取SK卡目录的可用空间大小,返回值为long型
long usableSpace = file.getUsableSpace();
// 使用AndroidAPI进行数据的格式化
String avail = Formatter.formatFileSize(this, usableSpace);
tvAvail.setText(avail);
兼容Andoird2.2版本的获取方法
/**
* 获取手机外部可用空间大小
*
* @return
*/
public static long getAvailableExternalMemorySize() {
// 判断SD卡是否可用
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
// 获取SD卡目录
File path = Environment.getExternalStorageDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
return availableBlocks * blockSize;
} else {
throw new RuntimeException("Don‘t have sdcard.");
}
}
/**
* 获取手机外部空间大小
*
* @return
*/
public static long getTotalExternalMemorySize() {
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
File path = Environment.getExternalStorageDirectory();// 获取外部存储目录即
// SDCard
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long totalBlocks = stat.getBlockCount();
return totalBlocks * blockSize;
} else {
throw new RuntimeException("Don‘t have sdcard.");
}
}
文件权限的概念
以下是一个典型linux下目录文件权限图
- Linux下目录文件权限由10位组成
- 第 1 位:
d
为目录,-
为文件 - 2 - 4位(当前用户):
r
为读权限,w
为写权限,x
为可执行权限 - 5 - 7位(当前用户所在组):
r
为读权限,w
为写权限,x
为可执行权限 - 8 - 10为(其他用户):
r
为读权限,w
为写权限,x
为可执行权限
简图如下
- 创建私有、追加、可读、可写权限的文件
- 主要是通过
context.openFileOutput()
方法的第二个参数进行设置 - ①私有
-
代码如下
public void Private(View v) throws Exception { FileOutputStream fos = context.openFileOutput("Private.txt", MODE_PRIVATE); fos.write("Private".getBytes()); fos.close(); }
- 截图,可以看到私有的在其他用户组中的权限为
- - -
- ②可追加
-
代码如下
FileOutputStream fos = openFileOutput("Append.txt", MODE_APPEND); fos.write("Append".getBytes()); fos.close();
- 截图,可以看到可追加的在其他用户组中的权限为
- - -
,与私有的一致,可追加和私有的权限,并不能在文件权限中体现出来。
- ③可读
-
代码如下
FileOutputStream fos = openFileOutput("Read.txt", MODE_WORLD_READABLE); fos.write("Read".getBytes()); fos.close();
- 截图,可以看到可读的在其他用户组中的权限为
r - -
- ④可写
-
代码如下
FileOutputStream fos = openFileOutput("Write.txt", MODE_WORLD_WRITEABLE); fos.write("Write".getBytes()); fos.close();
- 截图,可以看到可写的在其他用户组中的权限为
- r -
SharedPreferences使用
- 使用步骤
-
① 通过上下文的API获取到SharedPreferences实例
SharedPreferences sp = getSharedPreferences("config", Context.MODE_PRIVATE);
-
② 通过SharedPreferences.Editor存储数据
Editor editor = sp.edit(); editor.putString("username", username); editor.putString("password", password);
-
③ 通过Editor提交数据
editor.commit();
-
④ 使用SharedPreferences实例对象获取key对应的数据
String username = sp.getString("username", ""); String password = sp.getString("password", "");
使用SharedPreferences创建的文件如下图
可以看到使用SP存储文件,在内部应用程序目录下创建了shared_prefs
文件夹,并在文件夹下以指定的权限,创建了一个XML文件。
Android官方推荐的生成XML的方式
- 使用步骤
- ① 生成一个xml序列化器
- ② 设置序列化参数
- ③ 开始文档
- ④ 生成根节点
- ⑤ 循环生成子节点元素
具体代码如下,写的有详细注释:
// 1. 生成一个xml序列化器
XmlSerializer xmlSerializer = Xml.newSerializer();
// 2. 设置序列化参数,参数1:xml文件输出流;参数2:xml文件编码格式
FileOutputStream fos = openFileOutput("users.xml", Context.MODE_PRIVATE);
xmlSerializer.setOutput(fos, "UTF-8");
// 3. 开始文档,参数1:XML文档中第一行的encoding内容;参数2:是否是独立的,不依赖约束
xmlSerializer.startDocument("UTF-8", true);
// 4. 生成users根节点
xmlSerializer.startTag(null, "users");
// 5. 循环生成user子节点元素
for (User user : userList) {
xmlSerializer.startTag(null, "user");
// 6. 设置标签属性
xmlSerializer.attribute(null, "id", user.getId());
// 7. 设置user属性
xmlSerializer.startTag(null, "name");
xmlSerializer.text(user.getName());
xmlSerializer.endTag(null, "name");
// 8. 设置password属性
xmlSerializer.startTag(null, "password");
xmlSerializer.text(user.getPassword());
xmlSerializer.endTag(null, "password");
xmlSerializer.endTag(null, "user");
}
xmlSerializer.endTag(null, "users");
xmlSerializer.endDocument(); // 当文档结束时,会把输出流刷新,所有数据输出到文件中。
序列化后的XML文件如下:
Android官方推荐的解析XML的方式
- 使用步骤:
- ① 得到Xml解析器
- ② 得到Xml解析器参数
- ③ 获取事件,XMLPull是类似于SAX的基于事件、一行一行解析的
- ④ 循环处理事件
- ⑤ 处理根节点、子节点、子节点元素等
代码如下:
List<User> userList = null;
User user = null;
// 1. 得到Xml解析器
XmlPullParser parser = Xml.newPullParser();
// 2. 设置解析器
InputStream in = getClass().getClassLoader().getResourceAsStream(
"users.xml");
// 参数1:解析的文件流;参数2:解析XML的编码格式
parser.setInput(in, "UTF-8");
// 3. 获取事件,XMLPull是类似于SAX的基于事件、一行一行解析的
int eventType = parser.getEventType();
// 4. 循环处理事件
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_TAG:
if ("users".equals(parser.getName())) {
// 根节点时,初始化集合
userList = new ArrayList<User>();
} else if ("user".equals(parser.getName())) {
// 子元素时,初始化对象
user = new User();
// 获取子元素中的属性
String id = parser.getAttributeValue(0);
user.setId(id);
} else if ("name".equals(parser.getName())) {
String name = parser.nextText();
user.setName(name);
} else if ("password".equals(parser.getName())) {
String password = parser.nextText();
user.setPassword(password);
}
break;
case XmlPullParser.END_TAG:
if ("user".equals(parser.getName())) {
// 将元素添加到集合中
userList.add(user);
}
break;
default:
break;
}
eventType = parser.next();
}
System.out.println(userList.toString());
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。