android自动构建
㈠ 如何利用jenkins来做android自动化
如何利用jenkins来做android自动化
概述
持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽快地发现集成错误。许多团队发现这个过程可以大大减少集成的问题,让团队能够更快的开发内聚的软件。其中包含一些代码静态检查工具,自动打包和自动测试功能。
持续集成流程
环境配置
启动Jenkins
1、 安装jdk
从略,建议1.6或以上版本,配置好环境变量。
2、 安装tomcat
http://tomcat.apache.org/download-70.cgi
从略,安装完调试下tomcat是否正常。
3、 安装ant
http://ant.apache.org/bindownload.cgi
下载zip包,解压后配置好环境变量。
4、 安装jenkins
http://java.net/projects/hudson/downloads/directory/war
下载war包,命名为Jenkins,拷贝到tomcat/webapps目录下。
5、 安装Android SDK
http://developer.android.com/sdk/index.html
下载安装,完成后配置好Android_SDK_HOME环境变量。此步骤主要用于进行android自动化测试,若不进行此项可略过。
安装完成后启动tomcat/bin/startup.bat文件(linux下是startup.sh),在浏览器输入http://localhost:8080/jenkins,8080为tomcat端口,即可访问jenkins服务器。
配置Jenkins
1、 JDK配置
新增JDK,指定JDK名字和JAVA_HOME
2、 ANT配置
新增ANT,指定ANT名字和ANT_HOME
3、 Maven配置
从略,本文未使用到Maven,具体配置方法参考Google。
4、 Subversion
选择1.6版本SVN,勾选Update default Subversion credentials cache after successful authentication
5、 邮件通知
填写SMTP server、Default user E-mail suffix、System Admin E-mail Address、Jenkins URL、勾选Use SMTP Authentication,填写User Name、Password、Use SSL、SMTP port、Chareset(UTF-8) 、Default Content Type(默认)、Default Recipients(默认收件人),配置完成后可进行测试邮件。
6、 Jenkins URL
配置该URL,用于别人访问。
插件管理春瞎渗
1、 Hudson Subversion Plug-in,jenkins的svn插件。
2、 Android Emulator Plugin,android模拟器插件。
3、 JUnit Attachments Plugin,junit测试报告附件插件。
4、 Email-ext plugin,邮件扩展插件。此处说明下,默认Jenkins只会发送构建失败的邮件,我们需安装此插件才神谨能自定义不同场景。
5、 Deploy to container Plugin远程发布插件。
自动化测试
打包源工程
Android程序
本小节讲诉如何打包一个Android工程,当前使用的是ant进行编译源码。
1、 首先构建一个自由风格的Job。
2、 添加扒脊源码路径,选择所使用的版本控制器,输入源码路径。
3、 构建触发器可根据需要选择是否定时构建。
4、 构建环境,此处Jenkins安装了Android Emulator Plugin插件,可以启动已有模拟器或添加新的模拟器,本文案例中使用真机调试。
5、 构建,卸载手机中原程序 adb –s uninstall com.XXXXXX
6、 生成bulid.xml文件,-p后面跟工程所在的本地jenkins下路径
android update project -n *** c:\被测工程Job路径\workspace
7、 Ant进行编译程序,并安装到当前手机中
ant debug install -f c:\被测工程Job路径\workspace\build.xml
8、 构建后操作,本案例中构建完成后自动启动构建下一个测试Job
Bulid other projects,选择测试工程的Job.
打包测试工程
Android程序
本小节讲诉如何构建一个Android测试工程,包括邮件发送和测试报告展示。
1、 构建步骤1-7和Android程序章节一样,从略。
2、 本文案例中测试程序是通过命令行启动运行的,所以在此处增加一个批处理运行。P.S. adb shell am instrument -w -e class com.megafon.test.MegafonTest#testDeleteContact com.megafon.test/android.test.InstrumentationTestRunner ,此处是通过批处理来单独运行一个个的测试用例。避免了Junit3的无序执行的问题。
3、 删除Workspace中原来存在的测试报告文件,一般不删除也会覆盖。
如何让测试程序生成xml格式的测试报告,其他文章会重点介绍。
4、 从手机中拷贝测试报告,最终测试是在手机上运行,所以报告也生成在手机中,使用adb pull命令把测试报告全部拷贝到workspace下制定目录。
5、 构建后操作,发布测试报告,如果报告中包含附件,此处使用到JUnit Attachments Plugin插件。
6、 邮件通知,此处使用到Email-ext plugin插件,前面的默认,直接使用我们在系统管理里面设置的默认值。
7、 点击右下角高级按钮,可选择不同场景下发送邮件。
8、 测试结果展示,在本次构建的控制台可以显示当前所有的构建日志。
9、测试报告点击Test Result可以显示所有测试记录。
z转载,仅供参考,祝你愉快,满意请采纳。
㈡ 如何搭建 android 开发环境
一.认识android的架构
Android其本质就是在标准的Linux系统上增加了Java虚拟机Dalvik,并在Dalvik虚拟机上搭建了一个JAVA的application framework,所有的应用程序都是基于JAVA的application framework之上。
android分为四个层,从高层到低层分别是应用程序层、应用程序框架层、系统运行库层和linux核心层。
二.搭建环境
搭建开发环境
对国内的开发者来说最痛苦的是无法去访问android开发网站。为了更好的认识世界,对程序员来说,会翻墙也是的一门技术,带你去领略墙外的世界,好了,不废话了, 国内开发者访问(androiddevtools) 上面已经有了所有你要的资源,同时可以下载到我们的主角framework
但是这样的搭建只能去阅读源代码,我们无法去更进一步去实现自己的rom,我们看到锤子的系统在早期的开放rom是自己从新实现了framework的代码,现在看起来他成功了,所以我们还要去搭建android系统的源码编译环境。
搭建源码编译环境
三.开始主题
在一开始写c程序的时候都有一个运行的入口,比如
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
//这里的main就是应用的入口
int main(int argc, const char * argv[]){
return 0;
}
在计算机网络原理中我们用socket实现一个服务器端,不断的接听客户端的访问,而且他的代码是这样实现的:
#include <winsock2.h>
#pragma comment(lib, "WS2_32.lib")
#include <stdio.h>
void main()
{
WORD wVersionRequested;//版本号
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);//2.2版本的套接字
//加载套接字库,如果失败返回
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
return;
}
//判断高低字节是不是2,如果不是2.2的版本则退出
if (LOBYTE(wsaData.wVersion) != 2 ||
HIBYTE(wsaData.wVersion) != 2)
{
return;
}
//创建流式套接字,基于TCP(SOCK_STREAM)
SOCKET socSrv = socket(AF_INET, SOCK_STREAM, 0);
//Socket地址结构体的创建
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//转换Unsigned long型为网络字节序格
addrSrv.sin_family = AF_INET;//指定地址簇
addrSrv.sin_port = htons(6000);
//指定端口号,除sin_family参数外,其它参数都是网络字节序,因此需要转换
//将套接字绑定到一个端口号和本地地址上
bind(socSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));//必须用sizeof,strlen不行
listen(socSrv, 5);
SOCKADDR_IN addrClient;//字义用来接收客户端Socket的结构体
int len = sizeof(SOCKADDR);//初始化参数,这个参数必须进行初始化,sizeof
//循环等待接受客户端发送请求
while (1)
{
//等待客户请求到来;当请求到来后,接受连接请求,
//返回一个新的对应于此次连接的套接字(accept)。
//此时程序在此发生阻塞
SOCKET sockConn = accept(socSrv, (SOCKADDR*)&addrClient, &len);
char sendBuf[100];
sprintf(sendBuf, "Welcome %s to JoyChou",
inet_ntoa(addrClient.sin_addr));//格式化输出
//用返回的套接字和客户端进行通信
send(sockConn, sendBuf, strlen(sendBuf)+1, 0);//多发送一个字节
//接收数据
char recvBuf[100];
recv(sockConn, recvBuf, 100, 0);
printf("%s\\n", recvBuf);
closesocket(sockConn);
}
}
他采用了一个while死循环去监听客户端的请求。
先上源代码
public final class ActivityThread {
public static void main(String[] args) {
SamplingProfilerIntegration.start();
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
EventLogger.setReporter(new EventLoggingReporter());
Security.addProvider(new AndroidKeyStoreProvider());
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
//从中可以看到为app开辟了一个线程进入了looper之中
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
}
看到源码失望了,没有一个while循环啊,其实用了他方法实现
//用一个looper的机制循环监听响应
Looper.prepareMainLooper();
Looper.loop();
进一步深入代码
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
// 在这里看到了一个循环监听消息
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that ring the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();
}
}
㈢ android中的build.gradle是干什么用的
为什么要用Gradle?
Gradle是比较先进的构建系统,也是一个很好的构建工具,允许通过插件自定义构建逻辑
以下是为什么Android Studio选择Gradle的主要原因:
使用领域专用语言(Domain Specific Language)来描述和处理构建逻辑。(以下简称DSL)
基于Groovy。DSL可以混合各种声明元素,用代码操控这些DSL元素达到逻辑自定义。
支持已有的Maven或者Ivy仓库基础建设
非常灵活,允许使用best practices,并不强制让你遵照它的原则来。
其它插件时可以暴露自己的DSL和API来让Gradle构建文件使用。
允许IDE集成,是很好的API工具
需要准备:
Gradle 1.6 or 1.7
SDK with Build Tools 17.0.0 (released 5/16/2013)
Basic Project
在Gradle项目的根目录下,有个叫build.gradle的文件,它描述了这个项目的整体构建基础。
build文件
最基本的java程序纤液,它的build.gradle文件就一句话:
apply plugin: 'java'
最基本的Android项目,它的build.gradle如下:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.5.6'
}
}
apply plugin: 'android'
android {
compileSdkVersion 17
}
我们一步步来分析一下上面三部分的内容。
buildscript{...} 配置了驱动build的代码,它声明将在Maven中央仓库,取一个classpath dependency,也就是Android plugin for Gradle v0.5.6
apply plugin 指明了用到的plugin是android,就像前面java程序中,用的plugin是java一样
android{...} 中配置了所有android构建的参数,这里也就是Android DSL的入口点。
默认的,只有目标编译环境是必要的,也就是compileSdkVersion这个属性。这和以前在project.properties中的target属性旦御类似。模竖岩
值得注意的是,如果你在Android项目中写 apply plugin:java 而不是apply plugin:android的话,将会build失败。