Windows下搭建基于Jenkins+Git+Gradle的Android持续集成

下载Jenkins


官网下载,如果官网下载存在问题,也可以在本站下载Jenkins

下载Gradle


目前Android Studio支持的是Gradle 2.8版本,因此下载2.8版本的即可。Gradle 2.8,也可以本站下载

安装Tomcat


官方主页Apache Tomcat。Windows下面建议下载32-bit/64-bit Windows Service Installer版本。
DownloadTomcat9

安装Jenkins


将下载的jenkins.war包直接放到tomcat下的webapps目录,启动tomcat,在浏览器输入:http://127.0.0.1:8080/jenkins

安装Git plugin,Gradle plugin,Android Lint Plugin插件


点击Jenkins首页的"Manage Jenkins"链接,如下图:
ManageJenkins

进入设置,点击"Manage Plugins",添加Git plugin,Gradle plugin,Android Lint Plugin

ManagePlugins在打开的页面中,搜索并且安装插件

PluginManagerInstall

系统配置


返回首页,点击" Manage Plugins",然后进入页面中选择Configure System,配置JDK,Gradle,Git的选项。

JenkinsConfigure
设置JDK
SettingJava

SettingJavaManual

新建项目


首页点击"创建一个新任务",如下图:
NewJenkinsJobs
在接下来的页面中,输入工程的名字,并且选择"Freestyle project"

NewJobsCreateSelect
设置Git中源代码的路径,如果是使用SSH证书认证的登陆,则在Credentials中进行配置,如下图:

JenkinsJobAndroidConfigureGitNew

接下来配置触发构建的条件,目前我们设置为每天晚上3点,注意里面输入的是H 3 * * *,每个字符之间都有一个英文的空格。

JenkinsJobAndroidConfigureTrigger

接下来,配置Gralde的编译,在构建项目中选择"Invoke Gradle Script",如下图:
InvokeGradleScript
在选项的Tasks栏目中输入clean build --stacktrace --debug,如下图:

InvokeGradleScriptTasks
接下来,配置构建后操作,一般增加Publish Android Lint results,Archive the artifacts这两项即可,具体的配置参考下图:

InvokeGradleScriptTasksAfterBuild

构建项目


BuildNow

检验构建结果


构建完成以后检查一下,如果在:

下面成功生成了APK文件,则说明配置是成功的。

参考链接


基于Jenkins+git+gradle的android持续集成,jenkinsgradle

TortoiseGit 与 Putty 配置冲突导致 Server refuse our key

TortoiseGitTortoiseSVNGit版本,TortoiseGit用于迁移TortoiseSVNTortoiseGit,一直以来GitWindows平台没有好用GUI客户端,现在TortoiseGit的出现给Windows开发者带来福音

TortoiseGit原本用得好好的,一日安装了Putty后,问题出现了。。

在进行git操作时提示:

TortoiseGit版本信息:

因为TortoiseGit调用了由Putty修改而来的TortoisePLink,因此Putty的配置将会影响TortoiseGit

解决方法,删除注册表中的以下节点即可:

参考链接:


TortoiseGit 与 Putty 配置冲突导致 Server refuse our key

Putty通过SSH无密码登陆Ubuntu12.04

(1)生成公钥/私钥对

注意"-P"后面输入的内容为空的时候代表不需要输入密码。
完成后会在当前用户目录下的.ssh目录下生成id_rsa,id_rsa.pub这两个文件。
(2)拷贝证书到本地机器
.ssh/id_rsa.pub拷贝下来,然后重命名成id_rsa.pub.git也就是Key加上用户名的命名方式,这样在Linux或者执行命令行的时候SSH可以自动进行用户名,密码的对应。
(3)对于Linux复制的id_rsa.pub.git添加到.ssh/authorzied_keys文件里

authorized_keys的权限要是600
(4)对于Windows,则需要把id_rsa这个文件拷贝下来,然后使用TortoiseGit自带的Puttygen转换为被TortoiseGit支持的.ppk文件。

点击"Conversions"菜单中的"Import key"选项,然后导入我们下载到的id_rsa

PuttyKeyGeneratorImportKey

导入后,

SavePPK

由于Puttygen的BUG,导致如果直接点击"Save private key",会导致生产的Public key是不正确的,因此,需要先点击"Save public key",保存为文件后,无视这个文件即可。然后接下来点击"Save private key"按钮,保存为.ppk文件,这个PPK文件才是我们需要的。

(5)修改SSHD的配置文件/etc/ssh/sshd_config
找到

这句,然后去掉注释。然后重启SSH服务

(6)修改登录认证文件,把认证信息导入到需要认证的用户目录下的.ssh/authorized_keys文件中。

以上面添加的用户git为例子,通过命令:

可以看到输出如下信息:

从而找到用户git的工作目录在/share目录下面.

因此执行如下命令:

接下来,需要修改authorized_keys的所有者为用户git,否则git无法通过这个文件进行认证。

而对于管理员root而言,我们不需要执行拷贝操作,只需要修改一下SSH的配置文件,并且执行如下命令即可:

(7)Putty设置使用PPK文件进行登陆认证

左侧栏中选择Connection->SSH->Auth:

LoginPPK
然后点击左侧栏中的Session,点击Save保存设置,然后点击Open连接服务器。
SaveSession

(8)登陆时候,还是需要输入用户名的,因为Ubuntu服务器需要根据用户名来核查证书。输入用户名后,直接回车,会发现不需要再输入密码,就直接登陆了。

putty-7

Android:flags:value

最近用到了Android flag的机制,把Android现在所有的flag列出来,供参考。

FLAG_GRANT_READ_URI_PERMISSION 0x00000001
FLAG_GRANT_WRITE_URI_PERMISSION 0x00000002
FLAG_FROM_BACKGROUND 0x00000004
FLAG_DEBUG_LOG_RESOLUTION 0x00000008
FLAG_EXCLUDE_STOPPED_PACKAGES 0x00000010
FLAG_INCLUDE_STOPPED_PACKAGES 0x00000020
FLAG_GRANT_PERSISTABLE_URI_PERMISSION 0x00000040
FLAG_GRANT_PREFIX_URI_PERMISSION 0x00000080
自定义 0x00000x00
自定义 0x00001000
FLAG_ACTIVITY_RETAIN_IN_RECENTS 0x00002000
FLAG_ACTIVITY_TASK_ON_HOME 0x00004000
FLAG_ACTIVITY_CLEAR_TASK 0x00008000
FLAG_ACTIVITY_NO_ANIMATION 0x00010000
FLAG_ACTIVITY_REORDER_TO_FRONT 0x00020000
FLAG_ACTIVITY_NO_USER_ACTION 0x00040000

FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET 0x00080000
FLAG_ACTIVITY_NEW_DOCUMENT 0x00080000

FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY 0x00100000
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 0x00200000
FLAG_ACTIVITY_BROUGHT_TO_FRONT 0x00400000
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 0x00800000
FLAG_ACTIVITY_PREVIOUS_IS_TOP 0x01000000
FLAG_ACTIVITY_FORWARD_RESULT 0x02000000
FLAG_ACTIVITY_CLEAR_TOP 0x04000000

FLAG_ACTIVITY_MULTIPLE_TASK 0x08000000
FLAG_RECEIVER_NO_ABORT 0x08000000

FLAG_RECEIVER_FOREGROUND 0x10000000
FLAG_ACTIVITY_NEW_TASK 0x10000000

FLAG_RECEIVER_REPLACE_PENDING 0x20000000
FLAG_ACTIVITY_SINGLE_TOP 0x20000000

FLAG_RECEIVER_REGISTERED_ONLY 0x40000000
FLAG_ACTIVITY_NO_HISTORY 0x40000000

Gradle build使用buildConfigField设置Log开关

应用场景


通常情况下我们的apps发布后也就是release模式下log是不显示的,debug模式下是显示log的,但是在特殊情况下我们测试release包的时候需要log的时候,就无法使用BuildConfig.DEBUG来达到要求,因为在release模式下自动设置为falsedebug模式下是true,这个时候我们需要自定义可控制的log开关。
Android Studio对应的BuildConfig.java位置

Studio中生成的目录: /app/build/generated/source/buildConfig/ 文件下的产品目录里面,找到想要的包名下会自动生成BuildConfig.java文件。我们可以看看下release模式下该文件的内容:

怎样自定义BuildConfig字段


在我们的build.gradle里面加入如下代码:


语法为:

上述语法就定义了一个boolean类型的LEO_DEBUG字段,值为true,之后我们就可以在程序中使用BuildConfig.LEO_DEBUG字段来判断我们所处的api环境。例如:

Ubuntu 12.04 系统下设置Tomcat 7服务器上JVM的内存大小

以前都是正常的Tomcat 7服务器,在增加了一个新工程后,无法正常访问,查看日志:

可以看到如下错误信息:

说明Tomcat在增加新工程后,内存不足了。

解决方法如下:

修改/etc/default/tomcat7文件:

找到如下信息:

可以看到,目前限制的内存最大值为128MB,-Xmx128m,调整到256MB后重启Tomcat7。

解决问题。

Node.js源码学习-模块

Node.js底层有三个重要部分

node

libuv 建立事件循环

v8 引擎以及JS/C++对象转换

node提供的模块 fs os net process等

libuv是一个神器,事件循环,适合状态机驱动的架构,单独学习。

v8的请看google的官方API文档。

今天主要看一下node的模块。

 

1.js2c.py

node内置了很多js文件,包括主程序 src/node.js和模块文件lib/*.js。js2py是把每一个js文件都生成一个源码数组,存放在node_natives.h中。

node_native

node_native.h中,每个js文件对应一个数组,源码以const char数组的形式存放。

 

node_native在映射完毕后,变成了这样一个数组。

2.node_javascript.cc

node_javascript.cc include了node_native.h,并提供两个方法:

MainSource(),只有一句

return OneByteString(env->isolate(), node_native, sizeof(node_native) - 1);

返回node_native映射的js文件,即node.js,转换成了一个v8::handle类型。node_native_1

 

 

图:node_native,node.js映射后的数组。

DefineJavaScript(env, target)

将所有js文件映射到Object型的target(不包括node.js)

target->Set(name, source)

综上,node_javascript.cc做了两件事,返回node.js的v8::handle,

返回lib/*.js的Object,{name: v8::handle, name: v8::handle .....}

现在所有js文件都被转换成了v8::handle。

3.node.cc

node.cc是nodejs的main文件,这里我们先认识一个node世界中的风云人物,process。

 

 

在node.cc的CreateEnvironment函数中,process出生了,下面我们从源码看看process是个什么?被赋予了哪些属性?

从上面这段代码可以看出process的原始属性,FunctionTemplate,很明显,是js里的一个function,function的name为process。

现在JS世界中已经多了一个叫process的function,那么它是在哪里成长的呢?

 

在node.cc的LoadEnvironment函数中,

运行MainSource

拿到了node.js的返回f_value,即node.js函数,入参为process的闭包函数,

(function(process) {})

验明正身,执行node.js闭包函数,最后一句做JS的同学看着肯定很眼熟,这不就是

(function(process){}).call(global, process)

 

4.fs.js

这里通过一个fs模块的创建与加载,来展示process呼风唤雨的能力。

首先规规矩矩的加载了几个模块,然后突然出现了binding

Binding在node.cc中实现

主要逻辑为,查看cache中是否有这个模块,如果没有就新建一个。

新建模块:如果存在builtin,则使用nm_context_register_func方法注册到cache中,如果是常量,cache中注册常量,如果是natives,绑定所有lib/*.js。

在fs中,process.binding找到了fs,是一个builtin模块。这个模块在node_file.cc中实现,最后通过NODE_MODULE_CONTEXT_AWARE_BUILTIN注册到builtin。

Binding函数完成了js上调用C++模块。

 

5.node.js

node.js中通过一个NativeModules来管理js模块,

 

process.binding('natives'),将所有内置js模块绑定到_source上。

之后可以通过require方法来拿到这些模块。

先检查cache,如果cache没有,就在process.moduleLoadList中增加一个,然后缓存,执行.

缓存就是把模块放到_cache中,compile函数

通过C++模块contextify运行了这段js。

 

 

IntelliJ IDEA 2016.1建立Strut2工程并使用Tomcat调试

IntelliJ IDEA 2016.1建立Strut2工程的步骤如下:

1.从菜单中选择新建工程:

NewProjectMenu

2.在弹出的窗口中,左侧的列表中,选择"Java",在右侧的"Project SDK"中指明需要的Java SDK的版本,目前要求是1.8版本的,在下面的"Additional Libraries and Frameworks"中找到"Struts 2",并选中,同时选中"Web Application"。

NewStucts2Project

3.点击下面的"Next"按钮。

JavaEnterpriseStruct2ProjectName

4.等待IntelliJ IDEA下载完成必须的插件。点击左侧的"Project"边栏,之后可以到如下界面.

JavaEnterpriseStruct2ProjectView

点击右侧的"Project Stucture"按钮,如下图:

ProjectStuctureButton

修复存在的问题:

ProjectStuctureWindow2

点击后出现的界面如下:

ProjectStuctureWindowStruts2Lib

在弹出的菜单中,选择"Put into /Web-INF/lib"。

ProjectStuctureWindowStruts2LibMenu

配置完成后的界面如下:

ProjectStuctureWindowStruts2LibComplete

点击"OK",关闭窗口。

5.编辑配置信息"Edit Configurations"

EditConfigurations

6.在弹出的界面中点开右侧的"+"符号,也可以点击左侧顶部的"+"号。

RunDebugConfigurations

7.在弹出的界面中,一直下拉,找到"Tomcat Server",点击展开,选择"Local"

RunDebugConfigurationsAddSettings

RunDebugConfigurationsAddSettings

8.下载并安装Tomcat 9

Windows下面,建议安装 "32-bit/64-bit Windows Service Installer"

Tomcat9DownloadPage

9.安装最新的 Java SE Development Kit
目前最新的版本是8u73。保证电脑上面是最新的,如果使用JDK 7的话,会由于Tomcat的版本号太高导致在调试的时候报告如下错误:

这个错误的原因是由于JDK 1.7是默认没有包含JMS服务的,导致Idea通过JMSTomcat通信的时候失败。

10.设置Tomcat Server

RunDebugConfigurationsTomcatServerLocalSettingsFirst

RunDebugConfigurationsTomcatServerLocalSettingsSecond

RunDebugConfigurationsTomcatServerLocalSettings

配置完成后的界面显示如下:

RunDebugConfigurationsTomcatServerLocalSettingsAfterConfigure

此时底部提示"Warning No artificts configured",点击底部的"Fix"按钮。

RunDebugConfigurationsTomcatServerLocalSettingsFixButtonClick

出现的窗口中自动帮我们加入了"Tools:war exploded"项目,点击下面的"Apply"按钮后,点击"OK"关闭设置页面。

RunDebugConfigurationsFix2

11.调试,点击主界面上面的调试图标,即可进入调试,此时会在默认的浏览器上打开网页。

RunDebugConfigurationsTomcatServerLocalSettingsDebug

最后,浏览器上出现如下画面,说明设置成功。

ideaStucts2Complete

12.创建一个简单的Stucts2MVC例子----TimeConvert

(1)先创建一个Model类来存放数据

首先,在src目录上鼠标右击,选择"New"-> "Java Class"并在对话框中输入名字"Tools.Model.TimeConvertStore",点击"OK"。

NewJavaMenu

NewJavaModel

里面的代码如下:

这个Model类的public setget方法允许访问private convertTime字符串属性,Struts 2框架需要将这个对象按照JavaBean方式暴露给View(TimeConvert.jsp)

(2)创建View页面来显示Model类里存储的convertTime .

web目录上鼠标右击,选择"New"-> "File"并在对话框中输入名字"TimeConvert.jsp",点击"OK"新建一个TimeConvert.jspjsp页面.

NewJSPMenu

NewJSPWindow

代码如下:

页面中的taglib告诉Servlet容器这个页面将使用Struts 2tags并且将它们用s来表示。
s:propertytag标签返回调用TimeConvertAction controller classgetTimeConvertStore方法后的值。这个方法返回一个TimeConvertStore对象。在TimeConvertStore加上了.convertTime后,就可以告诉Struts 2框架将调用TimeConvertStoregetConvertTime方法。TimeConvertStoregetConvertTime方法返回一个字符串,然后这个字符串将被s:property标签显示。

(3)创建一个ActionTimeConvertAction.java作为Controller.
src目录上鼠标右击,选择"New"->"Java Class"并在对话框中输入名字"Tools.Controller.TimeConvertAction",点击"OK".

NewJavaMenu

NewJSPActionWindow

代码如下:

(4)增加struts配置到struts.xml文件中
建立映射关系,将TimeConvertAction类(Controller)和TimeConvert.jsp(View)映射在一起。映射后,Struts 2框架就能够知道哪个类将响应用户的actionthe URL),这个类的哪个方法将被调用,哪个View能够得到这个方法的返回String结果。

(5)在index.jsp中增加链接

首先在jsp页面顶部增加taglib说明

然后在body标签后增加p标签

修改后的代码如下:

点击调试后,运行效果如下图:

TimeConvertIndex

点击超链接后显示如下:

TimeConvertAction

13.增加多语言支持i18n

需要注意的是,对于index.jsp中读取全局配置文件,需要先增加Spring框架,否则是无法通过在struts.xml中增加

来实现的。如下图所示:

struts.custom.i18n.resources

在跟"TimeConvertAction.java"相同的目录下面建立英文语言文件TimeConvertAction_en.properties,中文语言文件TimeConvertAction_zh.properties,注意,中文只能是Unicode编码的格式,否则会出现乱码。格式类似\u65f6\u95f4\u8f6c\u6362这样的格式。
Struts2i18n
其中TimeConvertAction_en.properties中的内容如下:

TimeConvertAction_cn.properties中的内容如下:

然后修改TimeConvert.jsp,在Title中引用我们定义的语言。修改

为:

修改后的TimeConvert.jsp文件如下:

点击调试后,打开的页面中,会看到网页的Title变成了中文的"时间转换"。

14.Strut2增加对Json的支持

默认情况下Struts2不支持直接返回JSON,比较方便的方式是使用struts2-json-plugin来支持。

(1)增加spring框架,由于struts2-json-plugin需要调用spring框架,因此需要增加spring框架。右击工程,选择"Add Framework Support..."。

AddFrameworkSupport

在弹出的窗口中,选择"Spring","Spring MVC"两项,同时在点击"Spring"的时候,勾选"Create emtpy spring-config.xml"。

SpringSelectOptions

然后点击"OK",等待需要的Jar包下载完成。成功下载完成后,可以在lib目录下看到非常多的Jar文件被添加进来了。在web目录下的WEB-INF目录下多出来了applicationContext.xml,dispatcher-servlet.xml这两个文件。SpringFrameworkAddComplete

SpringFrameworkAddCompleteWebInf

完成后点击界面上侧的"Project Structure"图标,解决提示的Jar包导出问题。

SpringFrameworkProjectStructure

SpringFrameworkFix

都选择第一项"Add 'xxxxxxxxxxx' to the artifact".

SpringFrameworkFixMenu

(2)确认项目使用的Struts2的版本。点击界面上侧的"Project Structure"图标

SpringFrameworkProjectStructure

StrutsVersion2-2.3.20.1

从上图可以看到我们的Struts2的版本是2.3.20.1

(3)手工去下载struts2-json-plugin插件,选择与我们的Struts2的版本相同的版本的插件。之所以需要手工下载而不是要求IntelliJ IDEA Maven中自动下载原因在于,由于我们建立项目的时候没有使用Maven,因此我们项目Lib目录下的Struts2Jar包是没有带版本号的。而如果要求Maven自动下载的话,会由于找不到带版本号的Struts2Jar包,而自动引入一堆的带版本号的Struts2Jar包。导致Struts2Jar包出现两份,一份是有版本号的,一份是我们现在的样子。导致无法编译通过,因此还是手工引入即可。

由于我们的Struts2的版本是2.3.20.1,因此,我们下载2.3.20.1版本的struts2-json-plugin.Struts2JSONPlugin

下载完成后放到项目的lib目录下,然后右击struts2-json-plugin-2.3.20.1.jar,选择"Add As Library".

AddasLibrary

AddasLibraryWindow

点击OK后关闭。

继续点击界面右上侧的"Project Structure"图标

SpringFrameworkProjectStructure

AddStruts2-json-plugin-2.3.20.1totheartifact

修改src目录下的struts.xml。调整部分如下图所示。

ActionJsonResp

action的返回类型为json时的可配置参数详解:

15.参考链接