本节书摘来自异步社区《精通移动App测试实战:技术、工具和案例》一书中的第1章,第1.7节,作者 于涌 , 王磊 , 曹向志,更多章节内容可以访问云栖社区“异步社区”公众号查看
前面已经完成了Android开发环境的搭建工作,现在就让我们一起来编写一个简单的Android程序。这里我们要实现一个两个整型数字相加的程序。
启动Eclipse,单击“File > New > Android Application Project”菜单项,如图1-42所示。
在弹出的图1-43所示界面中,“Application Name”表示应用名称,如果后续我们将该应用安装到手机设备上,会在手机上显示该名称,这里我们给其起名为“CalculatorOfTwoNum”。
“Project Name”表示项目名称,在项目创建完成后该名称会显示在Eclipse左侧的Package Explorer中,这里我们保留其自动生成的内容,即“CalculatorOfTwoNum”。“Package Name”表示项目的包名,Android系统是通过包名来区分不同应用程序的,因此要保证包名的唯一性,这里我们将其命名为“com.yuy.calculatoroftwonum”。“Minimum Required SDK”表示程序运行需要的最低兼容版本,这里我们保留其默认值,即Android 4.0版本。“Target SDK”表示目标版本,通常我们要在该版本经过非常全面的系统测试,这里我们选择Android 4.4版本。“Complie With”表示程序将使用那个版本的SDK进行编译,这里我们也选择Android 4.4版本。“Theme”表示程序的UI所使用的主题,这里我们选择其默认的“Holo Light with Dark Action Bar”主题。
单击“Next”按钮,进入到图1-44所示对话框,这个对话框可以对项目的一些属性信息进行配置,如是否创建启动图标、创建活动和项目的存放位置等内容,我们不做修改,保留其默认值。单击“Next”按钮,将出现图1-45所示界面,在这个对话框中我们可以配置应用的启动图标,通常启动图标是一个应用的门面,必须好好设计来吸引用户的眼球,但作为一个简单的示例程序,我们可以保留其默认的设置不做更改,单击“Next”按钮,出现图1-46所示界面。
如图1-46所示,我们可以在该对话框选择要创建活动的类型,这里选择创建一个空白活动,也就是其默认的选项,单击“Next”按钮,将出现图1-47所示界面。
在弹出的图1-47所示界面中,包括了2项内容,即“Activity Name”和“Layout Name”,其中“Activity Name”表示给新建的空白活动起的名字,这里保留“MainActivity”,“Layout Name”是针对这个活动的布局文件名字,我们也保留“activity_main”这个名字。然后,单击“Finish”按钮,完成新项目的创建工作,将出现图1-48所示界面。
在做任何事情之前,大家都要想好怎样去实施。这里我们想做一个基于图形界面的手机应用,作者用“画笔”程序做了一个简单的应用预实现的界面,供大家参考,如图1-49所示。
下面,我们就来实现这个小的手机应用程序。首先来实现布局文件,将相应标签、文本框和按钮控件放到图1-49所示的相应位置。当然有两种方式可以实现,一种方式是直接从图 1-48 所示的控件面板中拖放控件到右侧的活动中,另外一种方式是直接修改“activity_main.xml”文件。这里我们选择第二种方式,双击“res”目录下的“layout”子目录中的“activity_main.xml”文件,然后选择右侧的“activity_main.xml”页,如图1-50所示。
将“activity_main.xml”文件修改为如下内容。
布局文件创建好以后,我们可以切换到图形布局,来看一下效果,如图1-51所示。
从图1-51可以进一步确认它实现了我们预设计界面的需求。也许细心的读者已经从上面的布局文件中发现了以下一些问题。
(1)在上面的配置文件中,并没有出现“数值1:”“数值2:”“求和计算”和“退出”汉字。
(2)上面的布局文件是一个XML文件,那么在XML中不同的标签表示什么控件呢?
下面我们就主要针对这两个问题向大家介绍一下,第一个问题为了解决日后手机应用版本的国际化问题,开发人员通常不直接把文本标签、按钮名称直接写到对应控件的属性中,而是通过一个配置文件来进行设置,这样就可以根据不同国家应用不同的语言,加载不同的配置文件,而不用再每次编译不同的安装包进行分发。这里对应汉字的标题都存放在“res”目录下“values”子目录的“strings.xml”文件中,如图1-52所示。
为了让大家看得更清楚,这里将“strings.xml”文件内容展示如下。
CalculatorOfTwoNum
数值1:
数值2:
求和计算
退出
Settings
从这个XML文件中,我们可以看到定义了很多标签。第一个标签“CalculatorOfTwoNum”定义了名称“app_name”,其值为“CalculatorOfTwoNum”这样的一组键值对。它将会在另一个非常重要的文件,即“AndroidManifest.xml”文件中得到应用,在后续内容中我们将会介绍到。第二个标签“数值1:”,定义了名称为“num1”的键值,其值为“数值1:”。我们不难理解在“activity_main.xml”布局文件中“android:text="@string/num1"”引用的就是“数值1:”。后续的内容类似,就不再进行赘述说明。下面再说一下第二个问题,在布局文件中,用“”标签来声明一个相对布局,用“”来声明一个文本标签控件,用“”来声明一个文本框控件,而用“
来声明一个按钮控件,各个控件标签中还有一些属性来描述其高度、宽度、相对位置等信息,如果想深入地学习,建议大家看系统性书籍,这里作者不再过多地讲述。
接下来,我们实现这个小程序的源代码,单击“src”目录,在“com.yuy.calculatoroftwonum”包下双击“MainActivity.java”文件,打开该文件,如图1-53所示。
我们将“MainActivity.java”文件的信息修改为以下内容。
package com.yuy.calculatoroftwonum;
import android.R.string;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
public int add(int num1,int num2){
return num1+num2;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button calc = (Button)findViewById(R.id.btncalc);
calc.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
EditText t1 = (EditText)findViewById(R.id.edtnum1);
EditText t2 = (EditText)findViewById(R.id.edtnum2);
int a= Integer.parseInt(t1.getText().toString());
int b= Integer.parseInt(t2.getText().toString());
String s= Integer.toString(add(a, b));
Toast.makeText(MainActivity.this,s, Toast.LENGTH_LONG).show();
}
}
);
Button exit = (Button)findViewById(R.id.btnexit);
exit.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}}
上面的代码很简单,主要的代码是求和计算部分代码,即下面的内容。
Button calc = (Button)findViewById(R.id.btncalc);
calc.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
EditText t1 = (EditText)findViewById(R.id.edtnum1);
EditText t2 = (EditText)findViewById(R.id.edtnum2);
int a= Integer.parseInt(t1.getText().toString());
int b= Integer.parseInt(t2.getText().toString());
String s= Integer.toString(add(a, b));
Toast.makeText(MainActivity.this,s, Toast.LENGTH_LONG).show();
}
}
);
我们从上面的代码可以看到有findViewById()方法,这个方法是获取布局文件中定义的元素,这里传入的是R.id.btncalc,得到“求和计算”按钮的实例。它涉及了R.java文件,那么就让我们来说一下这个文件。在项目“gen”文件夹下的“com.yuy.calculatoroftwonum”包中会自动生成一个叫“R.java”的文件。在项目中添加的任何资源都会在其中生成一个与之对应的资源ID,请不要自行修改该文件内容,如图1-54所示。得到“求和计算”按钮实例后,通过调用setOnClickListener()方法为该按钮注册一个监听器,单击该按钮就会执行监听器的onClick()方法。
因此就会执行下面的内容。
EditText t1 = (EditText)findViewById(R.id.edtnum1);
EditText t2 = (EditText)findViewById(R.id.edtnum2);
int a= Integer.parseInt(t1.getText().toString());
int b= Integer.parseInt(t2.getText().toString());
String s= Integer.toString(add(a, b));
//显示求和结果
Toast.makeText(MainActivity.this,s, Toast.LENGTH_LONG).show();
这几条语句的含义是先获得布局中的两个文本框实例,再将“数值1”和“数值2”的文本内容转换为整数赋给整型变量a和b,而后通过add()函数将a与b的和转换为字符串类型赋给字符串类型变量s,最后通过Toast对象的show()方法将求和结果显示出来。
“AndroidManifest.xml”文件位于项目目录之下,如图1-55所示。
它是Android项目的配置文件,程序中定义的四大组件都需要在这个文件里注册。有时候我们需要对SD卡的读写操作、网络等资源进行访问,也需要在该文件中添加相应的权限。还可以在该文件中指定运行这个手机应用所要求的最低兼容版本和目标版本。下面就让我们一起来看一下这个文件的内容。
需要大家注意的是所有的活动都要在“AndroidManifest.xml”文件进行注册后才能被使用,以下配置即为注册“MainActivity”活动,在“MainActivity”前面有一个“.”,它表示当前目录的意思,因为我们的包为“com.yuy.calculatoroftwonum”,也就是“com.yuy.calculatoroftwonum. MainActivity”,“. MainActivity”为其简写形式。为了使“MainActivity”作为这个手机应用的主活动,也就是说能通过单击手机桌面应用的图标直接打开这个活动,就需要加入“”标签,并加入“”和“”,才能使之成为应用的主活动,如下所示。
如果没有声明任何一个活动作为主活动,这个程序仍然是可以正常安装的,只是没有办法在手机桌面上看到它,如我们将在后续做自动化测试时讲到的测试程序,将只能看到被测试应用,而看不到测试应用也就是这个原因,这种形式的应用一般作为第三方服务来进行内部调用。
下面的配置用于指定这个程序所支持的最低向下兼容的系统版本和目标版本。
下面的配置用于指定应用的图标、应用标题、序的UI所使用的主题,这些内容引用的也是“strings.xml”和“R.java”这2个文件中的内容。当“allowBackup”标志为“true”时,用户可通过“adb backup”和“adb restore”来进行对应用数据的备份和恢复,这可能存在一定的安全风险。
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
图1-54中,在项目的最下面有一个名为“project.properties”的文件,该文件的内容如下。
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir,
# user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-19
从上面的内容来看,有效的内容仅为“target=android-19”,它指定了编译程序所使用的SDK版本。
结合图1-54项目的结构,我们再向大家介绍和补充说明如下。
“src”:这个目录是存放Java源代码文件的地方。
“gen”:这个目录里的内容都是自动生成的,它主要有一个R.java文件,我们在项目中添加的任何资源其实都会在该文件中生成一个对应的资源ID,请大家不要自行去修改该文件。
“assets”:这个目录主要用于存放一些随程序打包的文件,在程序运行过程中可以动态读取到这些文件的内容。如果程序使用到了WebView加载本地网页的功能,这个目录也将是存放网页相关文件的位置。
“bin”:这个目录主要包含了一些在编译时自动产生的文件,比如安装包文件就会存放在该目录。
“libs”:如果在项目中使用到了第三方的一些jar包,就需要把这些jar包都放在该目录下,放在这个目录下的jar包都会被自动添加到构建路径里去。
“res”:这个目录主要存放项目中使用的所有图片、布局、字符串等资源,前面提到的R.Java文件中的内容也是根据这个目录下的文件自动生成的。当然这个目录下还有很多子目录,图片放在“drawable”目录下,布局放在“layout”目录下,字符串放在“values”目录下。
如果手机模拟器没有启动,则需要开启我们先前创建的手机模拟器,保证其处于运行状态,如图1-56所示。
而后选中“CalculatorOfTwoNum”项目,单击鼠标右键,从弹出的快捷菜单中,选择“Run As > Android Application”菜单项,如图1-57所示。
接下来,将会在“Console”的输出内容中看到图1-58所示信息。
以下内容为其具体的输出信息。
[2015-05-28 13:46:39 - CalculatorOfTwoNum] ------------------------------
[2015-05-28 13:46:39 - CalculatorOfTwoNum] Android Launch!
[2015-05-28 13:46:39 - CalculatorOfTwoNum] adb is running normally.
[2015-05-28 13:46:39 - CalculatorOfTwoNum] Performing com.yuy.calculatoroftwonum.MainActivity activity
launch
[2015-05-28 13:46:40 - CalculatorOfTwoNum] Automatic Target Mode: using existing emulator 'emulator-5554'
running compatible AVD 'Galaxy_Nexus_4.4.2'
[2015-05-28 13:46:40 - CalculatorOfTwoNum] Uploading CalculatorOfTwoNum.apk onto device 'emulator-5554'
[2015-05-28 13:46:41 - CalculatorOfTwoNum] Installing CalculatorOfTwoNum.apk...
[2015-05-28 13:46:53 - CalculatorOfTwoNum] Success!
[2015-05-28 13:46:54 - CalculatorOfTwoNum] Starting activity com.yuy.calculatoroftwonum. MainActivity on device emulator-5554
[2015-05-28 13:46:57 - CalculatorOfTwoNum] ActivityManager: Starting: Intent
{ act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER]
cmp=com.yuy.calculatoroftwonum/.MainActivity }
从上面的输出信息,我们能够清楚地看到执行该应用的操作全过程,可以清楚地看到其启动过程中检测“adb”命令是否可以成功执行,是否能够调用应用的主活动,上传应用的安装包到手机模拟器,安装应用,启动主活动这一完整过程。从输出的信息来看,应用是安装成功的并启动了主活动,所以我们用鼠标操作手机模拟器滑开被锁住的屏幕,如图1-59所示。
我们在“数值1”后的文本框中输入2,在“数值2”后的文本框中输入3,而后单击“求和计算”按钮,会发现在手机屏幕的下方显示一个Toast提示信息“5”,如图1-60所示。
单击图1-60所示的“后退键”或者单击“退出”按钮,则回到模拟器的桌面,在桌面上,我们能够看到一个名称为“CalculatorOfTwoNum”的应用,它就是我们的样例程序,如图1-61所示。
当然也可以使用物理的手机设备作为调试设备,在应用物理的手机设备时,需要保证我们的手机设备可以被一些360手机助手、腾讯手机助手等工具成功访问,如图1-62所示。因为只有被成功识别了,才说明其相关的一些驱动正确安装了,这也是最简单的一种保证手机设备处于可调试状态的处理方式。
当使用手机设备作为调试工具时,选中“CalculatorOfTwoNum”项目,单击鼠标右键,从弹出的快捷菜单中,选择“Run As > Android Application”菜单项后,将出现如图1-63所示界面。
从运行的Android 设备列表中选择相应的手机设备,单击“OK”按钮,就会产生和在模拟器上相同的效果,这部分内容就不再进行赘述了。
这里作者强调一点,如果在条件允许的情况下请最好还是通过手机设备进行测试用例脚本的编写、调试以及测试工作,一方面物理设备是真实的设备,模拟器有些情况是模拟不了的、和物理设备还是有一定差异的,另一方面,物理设备的运行速度也明显优于模拟器,所以在本书无特殊说明的情况下,都是通过我的物理手机设备进行调试和测试工作。`