2017年5月29日星期一

使用Jenkins构建Android 工程(四)参数化构建

安装插件

首先需要安装Git Parameter Plug-in插件,用来配置Git相关构建参数。
打开首页 -> 系统管理 -> 管理插件,进入插件管理页面。切换到可选插件页,搜索git parameter即可找到插件,点击直接安装
安装完成后需要重启Jenkins,在浏览器中访问:http://xxx.xxx.xxx.xxx:8080/restart,确认重启即可。

添加构建参数

进入到我们的Android项目,选择配置进入设置页面,在General设置区勾选参数化构建过程,即可添加构建参数:
可以看到有以下几种参数:
参数类型描述
Boolean Value布尔型参数
Choice选择型参数
Credentials Parameter认证参数
File Parameter文件参数
Git ParameterGit参数
Multi-line String Parameter多行字符串参数
Password Parameter密码参数
Run Parameter运行参数
String Parameter字符串参数
其中Git参数是需要安装了Git Parameter Plug-in才能设置的参数。

布尔参数

布尔参数最简单,name为参数名称,Default Value设置是否默认选中(true),Description添加描述信息:
构建时显示效果如下:

选择型参数

选择型参数在列出的多个选项中选择一个,Choices中列出多个选项,每行一个选项,其中第一行为默认选项
构建时显示效果为:

认证参数

认证参数用来设置认证信息,Credential type用来选择认证的类型,包括ssh认证用户名/密码认证等多种认证类型;Default Value设置默认认证信息,通过后面的Add按钮还可以新增认证信息。
构建时显示效果:

文件参数

文件参数用来上传文件到工作空间,File location用来设置上传的文件保存的位置,这里需要使用相对于工作空间根目录的相对路径。
构建时显示效果:

Git参数

Git参数用来配置构建目标。
Parameter Type用来选择参数类型:
类型说明
Tag列出所有tag
Branch列出所有分支
Branch or Tag列出所有分支和tag
Revision可以让用户选择构建的revision
Branch用来设置分支,这个设置只有在Parameter Type设置为Revision时,才有效,用户可以选择指定分支的revision。
Branch Filter使用正则表达式来过滤分支的显示,为空时过滤器默认为".*"。
Tag Filter用来过滤tag,为空时默认为"*"。
Sort Mode用来设置排序方式,分为:none(不过滤)descending(降序)ascending(升序)acending smart(智能升序)descending smart(智能降序)
Default Value用来设置默认值,如果分支或tag等的列表获取为空,则采用设置的默认值。
Selected Value设置选中的值,分为:NONE(不选中)TOP(选中最上项)DEFAULT(选中默认项);如果选择了 DEFAULT且上面一项Default Value没有设置,则默认不会选中任一项。
Use repository用正则表达式指定使用哪个代码仓库。
Quick Filter勾选时,会在构建页面显示一个用来过滤的文本框,用户可输入文本在列表中显示的分支、tag等列表中过滤。
设置图及构建效果图如下:

多行字符串参数

这个也比较简单,用来输入多行字符串,可以设置默认值:

密码参数

比较简单,可用来输入密码,可以设置默认密码:

运行参数

指定其他构建任务的某一构建历史,具体作用还没搞清楚。TODO

字符串参数

这个类似与多行文本参数,不同的是这里只能输入单行文本

使用构建参数

使用Git参数构建指定版本

我们可以在构建时使用指定的分支、tag、revision来构建当前项目:
在项目设置里,切换到源码管理区,设置Branch Specifier属性为添加的git参数:${git_params}
我们新建branch_jenkins分支用来测试:
$ git checkout -b branch_jenkins
在新分支中app/build.gradle构建脚本中增加如下打印信息:
android {
    ...
    println "this is jenkins test!!!"
}
参数化构建页面,选择分支为branch_jenkins
查看构建输出:
[Gradle] - Launching build.
[android] $ /var/lib/jenkins/workspace/android/gradlew -Pmulti_params=这里用来输入多行文本。
默认文本可修改。
over。 -Pgit_params=origin/branch_jenkins "-Ptest_string_p=this is a default value" -Pchoice_type_color=red ******** -Pbool_type=true -Pupload/data.zip= ******** clean assemble
this is jenkins test!!!

可以看到打印输出了我们的测试信息,说明构建的是我们选择的branch_jenkins分支

指定Gradle任务

增加字符串参数gradle_tasks,设置默认值clean assemble
构建设置区中,指定Tasks属性为:${gradle_tasks}

在参数化构建页面,修改gradle_tasks参数值为tasks
点击开始构建,查看构建输出:
[Gradle] - Launching build.
[android] $ /var/lib/jenkins/workspace/android/gradlew -Pmulti_params=这里用来输入多行文本。
默认文本可修改。
over。 -Pgit_params=origin/develop "-Ptest_string_p=this is a default value" -Pchoice_type_color=red -Pgradle_tasks=tasks ******** -Pbool_type=true -Pupload/data.zip= ******** tasks
Incremental java compilation is an incubating feature.
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Android tasks
-------------
androidDependencies - Displays the Android dependencies of the project.
signingReport - Displays the signing info for each variant.
sourceSets - Prints out all the source sets defined in this project.
......

环境变量

在参数化构建过程中,设置的参数,除了文件参数运行参数,其他几种类型参数都会被设置为同名环境变量;
文件参数用来上传文件到工作空间已供构建过程使用;
运行参数会设置多个环境变量,譬如参数名称PARAMETER_NAME的运行参数会设置以下环境变量:
PARAMETER_NAME=<jenkins_url>/job/<job_name>/<run_number>/
PARAMETER_NAME_JOBNAME=<job_name>
PARAMETER_NAME_NUMBER=<run_number>
PARAMETER_NAME_NAME=<display_name>
PARAMETER_NAME_RESULT=<run_result>
在Android项目中打开设置页面,找到构建区,添加构建步骤执行脚本,添加脚本命令env,打印环境变量:
打开参数化构建,修改参数值,选择开始构建:
查看构建过程命令行输出:
[android] $ /bin/sh -xe /tmp/hudson9052812477166736119.sh
+ env
......
bool_type=false
credentials_type=ed7068da-a15e-415e-8060-846952c2f503
pwd_params=88888888
git_params=origin/master
test_string_p=单行文本参数
choice_type_color=green
multi_params=这里用来输入多行文本
默认文本可修改
结束
run_params=http://xxx.xxx.xxx.xxx:8080/job/android/18/
run_params_JOBNAME=android
run_params_NUMBER=18
run_params_NAME=#18
run_params_RESULT=SUCCESS
......
Archiving artifacts
Finished: SUCCESS
构建脚本即可通过环境变量来访问这些设置参数。

Gradle构建参数

Java系统属性

执行Gradle构建任务时,部分设置的参数会添加到Gradle构建命令中,作为Java系统属性,使用-D标识:
[Gradle] - Launching build.
[android] $ /var/lib/jenkins/workspace/android/gradlew -Dmulti_params=这里用来输入多行文本~~
默认文本可修改~~~ -Dgit_params=origin/master "-Dtest_string_p=单行文本参数" -Dchoice_type_color=green ******** -Dbool_type=false -Dupload/data.zip=usercmd ******** clean assemble

Gradle属性

在Android任务设置页面,切换到构建设置区:
添加Invoke Gradle script构建步骤时,如果勾选了Pass job parameters as Gradle properties选项,则设置的参数会以Gradle属性的方式添加到构建命令中,使用-P标识:
[Gradle] - Launching build.
[android] $ /var/lib/jenkins/workspace/android/gradlew -Pmulti_params=这里用来输入多行文本~~
默认文本可修改~~~ -Pgit_params=origin/master "-Ptest_string_p=单行文本参数" -Pchoice_type_color=green ******** -Pbool_type=false -Pupload/data.zip=usercmd ******** clean assemble

参看

2017年5月25日星期四

使用Jenkins构建Android 工程(三)创建Android任务

安装 Git

$ sudo apt install git

安装JDK

Ubuntu 16.04默认安装了openjdk 8,构建时会报错:
Could not find tools.jar. Please check that /usr/lib/jvm/java-8-openjdk-amd64 contains a valid JDK installation.
因此自己安装了oracle jdk 8:
$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt install oracle-java8-installer

设置默认工作目录

Jenkins通过环境变量JENKINS_HOME来设置默认工作目录,默认取/etc/default/jenkins文件中设置的环境变量:
NAME=jenkins
...
JENKINS_HOME=/var/lib/$NAME
我们可以修改这个默认配置文件,也可以修改~/.bashrc文件,增加JENKINS_HOME环境变量。
JENKINS_HOME=/home/jenkins
修改完成后,重启服务:
/etc/init.d/jenkins start

创建Android任务

Jenkins首页点击左侧新建按钮,进入Jenkins任务创建页面:
输入任务名称,选择构建一个自由风格的软件项目,点击OK,进入任务设置页面
进入源码管理区,选择Git,然后在展开的设置区下的Repository URL项中输入代码仓库地址
Credentials项中点击Add添加认证信息,这个获取Git仓库源代码的认证;认证方式很多,常用的是账户密码方式(Username with password),输入用户名、密码即可
Branch Specifier里选择Git分支,默认是主分支*/master
下一步在构建区点击增加构建步骤,在弹出菜单中选择Invoke Gradle Script
然后勾选Use Gradle Wrapper,选择使用项目自身gradle配置。然后在Tasks里添加gradle任务:
clean assemble
最后可以配置构建后操作,点击增加构建后操作步骤,选择Archive the artifacts功能归档构建产物。
以上是Android任务的基本设置,完成后就可以构建Android项目了.

问题

Cannot run program "./android-sdk-linux/build-tools/23.0.1/aapt": error=2, No such file or directory

使用的 build-tools 23.0.1 需要安装:
$ sudo apt install lib32stdc++6 lib32z1

参考

2017年5月24日星期三

使用Jenkins构建Android 工程(二)安装Android SDK

构建Android项目需要安装Android SDK
首先进入下载页面,获取 Android SDK tools 下载链接,当前最新Linux版本为:sdk-tools-linux-3859397.zip


下载:
$ cd
$ mkdir android-sdk-linux
$ cd android-sdk-linux
$ wget https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip
解压文件:
$ unzip sdk-tools-linux-3859397.zip
解压后,即可使SDK manager工具安装、更新所需的包。
可以使用以下命令查看所有可安装项:
$ ./tools/bin/sdkmanager --list
Available Packages:
  Path                              | Version      | Description                      
  -------                           | -------      | -------                          
  add-ons;addon-g..._apis-google-15 | 3            | Google APIs                      
  add-ons;addon-g..._apis-google-16 | 4            | Google APIs                      
  add-ons;addon-g..._apis-google-17 | 4            | Google APIs                      
  add-ons;addon-g..._apis-google-18 | 4            | Google APIs                      
  add-ons;addon-g..._apis-google-19 | 20           | Google APIs                      
  add-ons;addon-g..._apis-google-21 | 1            | Google APIs                      
  add-ons;addon-g..._apis-google-22 | 1            | Google APIs                      
  add-ons;addon-g..._apis-google-23 | 1            | Google APIs                      
  add-ons;addon-g..._apis-google-24 | 1            | Google APIs                      
  add-ons;addon-g...e_gdk-google-19 | 11           | Glass Development Kit Preview    
  build-tools;19.1.0                | 19.1.0       | Android SDK Build-Tools 19.1     
  build-tools;20.0.0                | 20.0.0       | Android SDK Build-Tools 20
其中,Installed packages显示已安装的包,Available Packages显示可安装包,安装指定的包使用Available Packages里的Path列的名称即可
安装build-tools
$ ./tools/bin/sdkmanager "build-tools;23.0.1"
安装platforms
$ ./tools/bin/sdkmanager "platforms;android-23"
安装support包:
$ ./tools/bin/sdkmanager "extras;android;m2repository"
其他包安装方法类似
安装完成后,需要设置环境变量。打开Jenkins首页 -> 系统管理 -> 系统设置,打开系统设置页面:


找到全局设置,勾选Environment Variables,增加键值对,键:ANDROID_HOME,值:/home/<username>/android-sdk-linux,保存设置。


使用Jenkins构建Android 工程(一)安装Jenkins

环境

操作系统:Parallels Desktop 12.2.0 + Ubuntu 16.04LTS

下载

Jenkins官网,当前最新版本为 Jenkins 2.46.2。可以下载war包部署,在Ubuntu操作系统中也可以通过apt工具安装。

安装

下面以Ubuntu 16.04LTS为例介绍Jenkins安装:
首先添加Jenkins仓库的 key:
$ wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -
然后添加源:
$ sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
安装Jenkins
$ sudo apt update
$ sudo apt install jenkins
安装完成后,jenkins作为服务启动,默认端口号:8080;
在浏览器中打开首页:http://xxx.xxx.xxx.xxx:8080,第一次访问会进入Jenkins管理员设置页面,在文件/var/lib/jenkins/secrets/initialAdminPassword中获取初始化管理员密码:
$ sudo cat /var/lib/jenkins/secrets/initialAdminPassword
将初始管理员密码输入设置页面中,点击继续。
下面就进入了Jenkins自定义设置页面,第一步安装插件,可以点击安装推荐的插件,也可以自己选择。选择完成后,点击安装,等待插件安装完成。
插件安装完成后,进入管理员账号创建页面,输入用户名、密码、电子邮件等信息。
点击完成,创建管理员账号,然后即可开始使用Jenkins了。

2016年10月12日星期三

使用LeakCanary检测Android内存泄漏


LeakCanary是Square开源的Java与Android内存泄漏检测工具:https://github.com/square/leakcanary,当前最新版本:1.6.2。

一、在Android项目中集成与使用

在Android项目中集成与使用LeakCanary相当简单:

1. 添加项目依赖


在构建脚本build.gradle中添加对LeakCanary库的依赖:

dependencies {
    debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.2'
    releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.2'
    testImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.2'
}
可以看到,release及test使用的是no-op的版本,no-op版本中接口都是空实现,因此不影响发布版本的业务逻辑,也不会影响效率。

2. 初始化LeakCanary


在Application中对LeakCanary工具进行初始化:

public class ExampleApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        if (LeakCanary.isInAnalyzerProcess(this)) {
            // LeakCanary会创建单独的进程用于内存堆分析,这里不应该调用我们的初始化代码,直接返回即可
            return;
        }
        LeakCanary.install(this);
        // 程序的初始化代码
    }
}
LeakCanary初始化时会注册系统Activity生命周期监听器,监听所有Activity的onDestroy方法调用,以此分析Activity的内存泄漏:

@TargetApi(14)
public final class ActivityRefWatcher {
        private final ActivityLifecycleCallbacks lifecycleCallbacks = new ActivityLifecycleCallbacks() {
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        }

        public void onActivityStarted(Activity activity) {
        }

        public void onActivityResumed(Activity activity) {
        }

        public void onActivityPaused(Activity activity) {
        }

        public void onActivityStopped(Activity activity) {
        }

        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        }

        public void onActivityDestroyed(Activity activity) {
            ActivityRefWatcher.this.onActivityDestroyed(activity);
        }
    };
    private final Application application;
    private final RefWatcher refWatcher;

    public static void installOnIcsPlus(Application application, RefWatcher refWatcher) {
        if(VERSION.SDK_INT >= 14) {
            ActivityRefWatcher activityRefWatcher = new ActivityRefWatcher(application, refWatcher);
            activityRefWatcher.watchActivities();
        }
    }

    public ActivityRefWatcher(Application application, RefWatcher refWatcher) {
        this.application = (Application)Preconditions.checkNotNull(application, "application");
        this.refWatcher = (RefWatcher)Preconditions.checkNotNull(refWatcher, "refWatcher");
    }

    void onActivityDestroyed(Activity activity) {
        this.refWatcher.watch(activity);
    }

    public void watchActivities() {
        this.stopWatchingActivities();
        this.application.registerActivityLifecycleCallbacks(this.lifecycleCallbacks);
    }

    public void stopWatchingActivities() {
        this.application.unregisterActivityLifecycleCallbacks(this.lifecycleCallbacks);
    }
}

3. 监听其他对象


Android中最常见的内存泄漏就是Context的内存泄漏,包括Activity、BroadcastReceiver、Service等,还有常见的Fragment等的泄漏。LeakCanary初始化时已经添加了所有Activity的监听,不需要我们再额外处理。下面看看其他对象的监听

分析Fragment内存泄漏分析,首先需要获取一个RefWatcher实例的引用:

public class ExampleApplication extends Application {
    private static RefWatcher sRefWatcher;

    @Override
    public void onCreate() {
        super.onCreate();
        if (LeakCanary.isInAnalyzerProcess(this)) {
            // LeakCanary会创建单独的进程用于内存堆分析,这里不应该调用我们的初始化代码,直接返回即可
            return;
        }
        sRefWatcher = LeakCanary.install(this);
        // 程序的初始化代码
    }

    public static void watch(final Object watchReference) {
        if(null != sRefWatcher) {
            sRefWatcher.watch(watchReference);
        }
    }
}
在Fragment的onDestroy中监听:

public class BaseFragment extends Fragment {

    @Override
    public void onDestroy() {
        super.onDestroy();
        ExampleApplication.watch(this);
    }
}
其他对象的监听类似,在将要释放对象时,增加对象的监听:

ExampleApplication.watch(obj);

4. 收集内存泄漏及分析:

项目中集成LeakCanary后,运行debug程序,一段时间后退出程序。桌面上LeakCanary额外创建了一个名为"Leaks"的快捷方式,打开快捷方式可以看到一条条的内存泄漏日志,如下图示例:

点击内存泄漏日志,可以查看内存泄漏详情,以此修复程序内存泄漏。

二、工作原理

  1. LeakCanary中调用RefWatcher.watch()方法会创建一个KeyedWeakReference的弱引用来监控对象
  2. 一段时间后,背景线程会检测这个引用对象是否被回收,如果没有被回收,则主动触发一次GC进行垃圾回收
  3. 如果这个引用对象仍然没有被回收,则dump堆内存到一个.hprof文件中存储到文件系统
  4. LeakCanary会在一个单独的进程中启动 HeapAnalyzerService,这个Service会调用HeapAnalyzer分析内存dump,而HeapAnalyzer使用得是另外一个Square开源工具HAHA来分析Android堆内存的dump文件
  5. HeapAnalyzer根据唯一key来找到堆内存中KeyedWeakReference对象并定位内存泄漏对象的引用
  6. HeapAnalyzer

三. 更多

https://github.com/square/leakcanary
https://github.com/square/leakcanary/wiki/FAQ
https://github.com/square/leakcanary/wiki/Customizing-LeakCanary
http://droidyue.com/blog/2016/03/28/android-leakcanary/index.html

2016年10月8日星期六

安装Groovy环境

Groovy的安装可以参看官网 。可以自己手动下载Groovy压缩包自己配置环境变量,也可以使用sdkman等工具来管理安装,这里记录下安装方法:

一、使用 SDKMAN


SDKMAN的使用可以参看:使用SDKMAN软件管理开发工具SDK

$ sdk install groovy
$ groovy -version
Groovy Version: 2.4.7 JVM: 1.8.0_101 Vendor: Oracle Corporation OS: Mac OS X

二、手动安装


使用SDKMAN安装的Groovy只有二进制程序,不包含源码和文档,这里介绍下手动安装的方法:

1. 首先下载Groovy压缩包,这里我选择了二进制+源码+文档的集成包,当前最新版本2.4.7:https://bintray.com/artifact/download/groovy/maven/apache-groovy-sdk-2.4.7.zip

2. 解压到本地:$HOME/bin/groovy-2.4.7

3. 设置环境变量GROOVY_HOME,ubuntu中~/.bashrc或mac中~/.bash_profile文件中添加:

export GROOVY_HOME=$HOME/bin/groovy-2.4.7
export PATH=$GROOVY_HOME/bin:$PATH

4. 重新打开命令行窗口,查看安装是否正确:

$ groovy -version
Groovy Version: 2.4.7 JVM: 1.8.0_101 Vendor: Oracle Corporation OS: Mac OS X

Android logcat

Log等级 Android log 等级在 android/log.h 中定义如下: typedef   enum   android_LogPriority {    /** For internal use only. */ ANDROID_LOG_UNKNOWN =...