1.测试
1.从代码的可见角度。黑盒测试,通过文档进行代码不可见的测试。自动化测试通过编写脚本进行测试。白盒测试,程序员写代码进行测试。
2.从测试的粒度。单元测试,集成测试,系统测试。
3.从暴力程度。压力测试、冒烟测试(一直测试到挂)。
4.在安卓中可以使用monkey 1000,进行随机点1000次的测试。monkey -p com.my.androidPro1 1000,在当前应用进行测试。
2.Android的单元测试
1.编写测试类extends AndroidTestCase,在此类编写方法进行测试。
2.这时在编写的方法上右键 -> Run As -> Android JUint Test,进行测试。这是会报错,[2019-10-12 18:37:06 - Android-pro-1] Android-pro-1 does not specify a android.test.InstrumentationTestRunner instrumentation or does not declare uses-library android.test.runner in its AndroidManifest.xml
,说明需要在AndroidManifest.xml文件中选择添加Instrumentation,然后Name选择要使用的测试类android.test.InstrumentationTestRunner,Target package选择要测试的类所在的包com.my.androidPro1。
3.然后会在AndroidManifest.xml文件中生成<instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.my.androidPro1"></instrumentation>
标签。
4.然后在application标签下添加<uses-library android:name="android.test.runner"/>
表示要引入测试的类库。
3.日志处理
1.可以使用Logcat查看日志,并对日志进行过滤。过滤的时候使用tag进行过滤。
2.实际在项目中是用android.util.Log类进行日志的输出,传入tag和日志信息,在Logcat中可以使用tag进行过滤,一般传入的tag是当前类名。
3.实际生产中会对日志类进行封装来控制是否使用日志,保证上线之后就不需要日志。
//一个简单的对日志处理的工具类,在项目上线之后通过修改flag,关系日志的使用
public class LogUtils {
private static boolean flag = true;
public static void logD(String tag,String msg){
if(flag)
Log.d(tag, msg);
}
}
4.Android简单登陆的实现
<EditText
android:id="@+id/ed_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入用户名" />
<EditText
android:id="@+id/ed_password"
android:layout_below="@id/ed_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:hint="请输入密码" />
<CheckBox
android:id="@+id/cb_isSave"
android:layout_below="@id/ed_password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="保存信息"/>
<Button
android:id="@+id/bnt_login"
android:layout_below="@id/ed_password"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登陆"
/>
//登陆见到那逻辑实现
public class MainActivity extends Activity {
//使用到的组件
private EditText et_username;
private EditText et_password;
private CheckBox cb_isSave;
private Button btn_login;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//加载页面
setContentView(R.layout.activity_main);
//获取需要操作的组件
et_username = (EditText) findViewById(R.id.ed_username);
et_password = (EditText) findViewById(R.id.ed_password);
cb_isSave = (CheckBox) findViewById(R.id.cb_isSave);
btn_login = (Button) findViewById(R.id.bnt_login);
//为按钮绑定点击事件
btn_login.setOnClickListener(new MyListener());
//如果用户信息保存 进行显示
String[] infos = Utils.read();
if(infos != null){
et_username.setText(infos[0]);
et_password.setText(infos[1]);
}
}
//通过内部类实现点击事件
class MyListener implements OnClickListener {
@Override
public void onClick(View v) {
//获得输入的用户名和密码
String username = et_username.getText().toString().trim();
String password = et_password.getText().toString().trim();
//判断输入的用户名和密码
if(TextUtils.isEmpty(username) || TextUtils.isEmpty(password)){
Toast.makeText(MainActivity.this, "用户名或密码为空", Toast.LENGTH_SHORT).show();
}else {
//判断是否进行信息的保存
boolean checked = cb_isSave.isChecked();
if(checked){
boolean info = Utils.saveInfo(username,password);
if(info){
Log.d("MainActivity", "用户信息保存成功");
}
}
Log.d("MainActivity", "用户登陆11");
}
}
}
}
//保存信息和读取信息的工具类
public class Utils {
public static boolean saveInfo(String username, String password) {
String info = username + "---" + password;
FileOutputStream fos = null;
try {
fos = new FileOutputStream(new File("data/data/com.my.androidPro03/info.txt"));
fos.write(info.getBytes());
return true;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}finally {
if(fos != null){
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static String[] read() {
FileInputStream fis = null;
BufferedReader br = null;
try {
fis = new FileInputStream(new File("data/data/com.my.androidPro03/info.txt"));
br = new BufferedReader(new InputStreamReader(fis));
String string = br.readLine();
String[] split = string.split("---");
return split;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static String[] readByContext(Context context) {
FileInputStream fis = null;
BufferedReader br = null;
try {
fis = context.openFileInput("info2.txt");
br = new BufferedReader(new InputStreamReader(fis));
String string = br.readLine();
String[] split = string.split("---");
return split;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static boolean saveInfoByContext(Context context,String username, String password) {
String info = username + "---" + password;
FileOutputStream fos = null;
try {
fos = context.openFileOutput("info2.txt", Context.MODE_PRIVATE);
fos.write(info.getBytes());
return true;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}finally {
if(fos != null){
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
5.Android中Context上下文的作用
1:可以获取应用相关的全局信息。
2:可以访问当前应用的私有资源和类。
3:也可以进行系统级别的调用,如开启另一个Activicy、发广播。
4:getFilesDir(),操作的是data/data/包名/files目录。
5:openFileInput、openFileOutPut,分别获去输入流、输出流,底层使用的是getFilesDir()。
6.将文件保存在sd卡中的代码实现
//当sd卡被过载 就将文件保存在sd卡上
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "info.txt");
try {
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write("保存信息".getBytes());
fileOutputStream.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//获取sd卡 空间信息
File file = Environment.getExternalStorageDirectory();
long totalSpace = file.getTotalSpace(); //总空间
long freeSpace = file.getFreeSpace(); //空闲空间
//将字节单位进行转换
String totalSize = Formatter.formatFileSize(this, totalSpace);
String freeSize = Formatter.formatFileSize(this, freeSpace);
Log.d("MainActivity", totalSize);
Log.d("MainActivity", freeSize);
7.Android中的单位
1:表示空间大小使用dp,android:width="100dp"。
2:表示文字大小使用sp,android:textSize="15sp"。
8.文件权限
1:第一位是文件还是目录。
2:下来分别是当前用户、同组用户、其他用户,各占三位。
3:每三位分别是r、w、x权限,权重分别是4、2、1,可以使用chmod 权重 文件名修改文件的权限。
9.使用openFileOutPut操纵文件时的文件模式
1:MODE_PRIVATE,权重660,修改文件时会覆盖原文件。
2:MODE_APPEND,权重660,修改文件时会进行文件的追加。
3:MODE_WORLD_READABLE,权重664,所有的用户都可以读文件。
4:MODE_WORLD_WRITEABLE,权重662,所有的用户都可以写文件。
10.使用SharedPreferences保存配置信息
1:SharedPreferences轻量级保存信息的api。
2:可以保存的数据类型有6中,int long float boolean String Set<String>。
3:常用的方法有,保存可以使用sp.edit();edit.putString("username", username);edit.commit();进行数据的保存。
4:获取可以使用sp.getBoolean("isSave", false);进行获取,第二个参数是,当对象没有找到的时候返回的值。
5:SharedPreferences保存的数据在data/data/包名/shared_prefs/文件名
6:数据保存的格式是xml形式,如
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<boolean name="isSave" value="true" />
<string name="password">1234</string>
<string name="username">1234</string>
</map>
//使用SharedPreferences保存信息的代码实现
public class MainActivity extends Activity implements OnClickListener{
private EditText et_username;
private EditText et_password;
private CheckBox cb_isSave;
private Button btn_login;
private SharedPreferences sp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_username = (EditText) findViewById(R.id.et_username);
et_password = (EditText) findViewById(R.id.et_password);
cb_isSave = (CheckBox) findViewById(R.id.cb_isSave);
btn_login = (Button) findViewById(R.id.btn_login);
//为按钮设置点击事件接口i
btn_login.setOnClickListener(this);
//SharedPreferences轻量级保存信息的api,可以保存的数据类型有6中
//int long float boolean String Set<String>
//获取SharedPreferences第一个参数是要保存数据的文件名,第二个参数是保存的模式
sp = getSharedPreferences("info", MODE_PRIVATE);
//如果前面的操作保存过数据 则此时获取的就是true,就需要将数据自动写入到输入框
boolean isSave = sp.getBoolean("isSave", false);
if(isSave){
String username = sp.getString("username", "");
String password = sp.getString("password", "");
et_username.setText(username);
et_password.setText(password);
cb_isSave.setChecked(true);
}
}
@Override
public void onClick(View v) {
//获取用户输入的数据
String username = et_username.getText().toString().trim();
String password = et_password.getText().toString().trim();
if(TextUtils.isEmpty(username) || TextUtils.isEmpty(password)){
Toast.makeText(this, "用户名密码为空", Toast.LENGTH_SHORT).show();
}else{
boolean checked = cb_isSave.isChecked();
Editor edit = sp.edit();
//通过Editor进行数据的保存
if(checked){
edit.putString("username", username);
edit.putString("password", password);
}
edit.putBoolean("isSave", checked);
//将保存的数据写入文件
edit.commit();
}
}
}
11.对象的xml序列化
public void saveInfo(View v){
//获取xml的序列化对象。
XmlSerializer serializer = Xml.newSerializer();
try {
//设置序列化的输出流和编码
serializer.setOutput(openFileOutput("info.xml", MODE_PRIVATE), "utf-8");
serializer.startDocument("utf-8", true);
serializer.startTag(null, "List");
for(SMS sms : list){
serializer.startTag(null, "sms");
serializer.startTag(null, "from");
serializer.text(sms.from);
serializer.endTag(null, "from");
serializer.startTag(null, "content");
serializer.text(sms.content);
serializer.endTag(null, "content");
serializer.startTag(null, "time");
serializer.text(sms.time);
serializer.endTag(null, "time");
serializer.endTag(null, "sms");
}
serializer.endTag(null, "List");
serializer.endDocument();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
12.对象的xml解析
public void parseInfo(View v){
XmlPullParser parser = Xml.newPullParser();
List<SMS> list = null;
SMS sms = null;
try {
parser.setInput(openFileInput("info.xml"), "utf-8");
int eventType = parser.getEventType();
while(eventType != XmlPullParser.END_DOCUMENT){
if(eventType == XmlPullParser.START_TAG){
if("List".equals(parser.getName())){
list = new ArrayList<SMS>();
}else if("sms".equals(parser.getName())){
sms = new SMS();
}else if("from".equals(parser.getName())){
sms.from = parser.nextText();
}else if("content".equals(parser.getName())){
sms.content = parser.nextText();
}else if("time".equals(parser.getName())){
sms.time = parser.nextText();
}
}else if(eventType == XmlPullParser.END_TAG){
if("sms".equals(parser.getName())){
list.add(sms);
}
}
eventType = parser.next();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(SMS s : list){
System.out.println(s);
}
}