分类目录归档:点点滴滴

点点滴滴便是点点和滴滴是也

Unity3D Mecanim 中 Transition 的 Atomic 属性是个什么鬼

我们游戏中一直有一个让我非常恼火的问题,关键是查了已经无数次了,根本尼玛不屌我啊,像我如此这般坚强的程序猿都要拜倒了。谁知前几天再次出现,因为已经把 Log 打得有点天罗地网的意思了,而且还持久化到磁盘 Log 文件上了,这下也不担心查着查着突然被其他的事情打断之后,然后再次回来想查问题的时候发现 Log 已经不见了,尼玛不是说好的要保护第一现场的咩?

不扯淡了,先说这个问题是啥。我们的游戏中,对于战斗 NPC 的动作都加了 AnimationEvent 回调,游戏中很多逻辑都依赖于 AnimationEvent 的回调,例如战斗 NPC 释放了一个技能,那么在这个技能动画刚刚开始播放和即将结束的某个时间点,会分别调用 OnSkillStart 和 OnSkillEnd 这两个 AnimationEvent,在这两个回调函数中会有相应的处理逻辑,例如在 OnSkillStart 中给 NPC 加上霸体的 Buf,在 OnSkillEnd 中将 NPC 的 Buf 取消。我碰到的诡异现象是这样的,NPC 的技能 A 的动画时间长度为 3 秒,OnSkillStart 方法和 OnSkillEnd 方法分别处于整个动画时间轴的 0.2 秒和 2.8 秒,NPC 在 AI 判断确定释放技能 A,在技能 A 动画播放到 0.1 秒的时候,受到了主角的攻击,此时 NPC 应该立即切换到受击状态,开始播放受击动画,但是事实上却不是这样,我们能看到的日志信息如下:

10:34:05.565 AM ya_zhang_tie_qi_jun(Clone)001 TriggerSkill ya_zhang_tie_qi_jun_attack_3

10:34:05.573 AM #Network# GameClient Emit a Message: [Action, Ping]

10:34:05.667 AM Player OnSkillStart: player_female_suplex_back
10:34:05.792 AM Player OnSkillTrigger (player_female_suplex_back#0)
10:34:05.799 AM ya_zhang_tie_qi_jun(Clone)001 OnHookAttackHit by Player with player_female_suplex_back#0
10:34:05.803 AM ya_zhang_tie_qi_jun(Clone)001 Hit to Hooking from None
10:34:05.817 AM ya_zhang_tie_qi_jun(Clone)001 OnSkillStart: ya_zhang_tie_qi_jun_attack_3
10:34:06.297 AM GameClient Received a Message: [Action, Ping]

10:34:06.338 AM Player OnSkillTrigger (player_female_suplex_back#1)
10:34:06.345 AM ya_zhang_tie_qi_jun(Clone)001 OnSuplexAttackHit by Player with player_female_suplex_back#1
10:34:06.352 AM ya_zhang_tie_qi_jun(Clone)001 is SuperArmored, cannot be Suplex
10:34:06.359 AM ya_zhang_tie_qi_jun(Clone)001 ApplySuperArmoredFX
10:34:06.744 AM ya_zhang_tie_qi_jun(Clone)001 CancelSuperArmoredFX
10:34:06.859 AM Player OnSkillEnd: player_female_suplex_back
10:34:08.589 AM #Network# GameClient Emit a Message: [Action, Ping]

从日志里头看到的信息就是这个牙帐铁骑军已经释放了一个技能,但是在其技能动画播放到 OnSkillStart 的时间点时,已经被主角攻击了,此时其并未立即切换到受击状态,而是继续播放其技能动画并且触发了 OnSkillStart 的回调。所以游戏的逻辑就出问题了,NPC 因为触发了 OnSkillStart 回调进入霸体状态了,然后主角后续的所有攻击都无法让 NPC 做出相应的受击动作了,关键是这个 NPC 在回调了 OnSkillStart 函数进入霸体之后呢,还是会进入到对应的受击状态,这下就奇了怪了。你要么就不进入受击状态呗,要么就别触发霸体啊,这不是要疯吗。

最后仔细分析排查,知道了这个问题是因为 OnSkillStart 的触发时间点处于动画过渡的时间区间内,也就是说 NPC 从 Idle 状态进入到技能 Attack_3 的状态时间长为 0.3 秒,并且这个动画的过渡 Atomic 属性为 True。问题就这么来了,NPC 在从 Idle 状态时释放技能 Attack_3,动画从 Idle 切换到 Attack_3,动画切换到 0.1 秒的时候,受到了主角的攻击,NPC 的整个 AnimatorController 状态图中,受击状态都是直接从 Any State 跳转过去的。按理来说就应该在任意状态下都能切换到受击状态才对啊,为啥动画还会继续往后播放呢,直到 OnSkillStart 回调完了之后再切换到受击状态呢?

最终发现了就是这个 Atomic 属性给闹的,这个 Atomic 属性的字面意思已经很清楚了,那就是当它为 True 的时候,这个过渡是原子的,也就是说只要进入了这个过渡,那么这个过渡就一定会播放完成,不论是发生任何情况这个过渡都会播放完成,而刚好我们的这个 OnSkillStart 回调函数所处的时间点就在这个过渡时间段里头,所以就出现了,虽然最终 NPC 还是进入了受击状态,但是在进入受击状态之前因为已经回调了 OnSkillStart 函数,所以导致逻辑上出现了错误。

这个问题呢,有两个解决方法:

  1. 取消所有的动画状态切换之间的过渡时间,让动画之间的切换不再有过渡的过程,都是直接切换,这样就可以避免出现过渡的时候触发 AnimationEvent 了;
  2. 将牙帐铁骑军的 AnimatorController 中从 Idle 到 Attack_3 状态的 Transition 的 Atomic 选项取消,允许该 Transition 被打断,这个解决方法看上去更有技术含量一些,也更符合我们设计意图,当我们不论处于一种什么状态的时候,受击之后就应该立刻切换到某个受击状态下,这个从语义上也很能说得通,对伐?

我是怎么科学上网的

最近碰到不少朋友问我怎么科学上网,刚好自己也有一些科学上网的经验,记录一下吧。

从 2008 年开始,我真正开始学会使用互联网,那个时候 Twitter 也才刚刚兴起,国内还有饭否和叽歪这样的追随者。刚开始 Twitter 是可以正常访问的,但是后来逐渐就不能访问了,为了追随国际潮流,作为程序员的我们,当然得想办法了。那个时候网络上有各种各样的免费代理以及 Twitter 的第三方服务,找一个还算稳定的代理或者直接使用某个第三方的服务就好了。但是好景不长,GFW 越来越牛逼,众多代理倒下了,那些第三方服务作者前期对 Twitter 疯狂的热情也慢慢消融了,Twitter 对于 API 的政策也慢慢缩紧了,终于有一天我发现了一个叫 Puff 的服务,当然也是在 Twitter 上发现的。

Puff 是我第一次花钱购买的一个科学上网服务,Puff 最开始是有提供免费版本的,我在持续使用了近半年免费版本之后,毕业开始上班了。我工作的第一家公司『北京超图软件股份有限公司』针对研发中心的所有小伙伴们都做了访问外网的限制,所有的工作机器都是无法连接外网的,那个时候自己还住在公司集体宿舍,也木有自己的电脑,所以差不多有半年的时间里头,很少能有机会接触到互联网,作为一个对世界充满了爱的少年,我们肯定是无法忍受的。所以我忍痛向朋友借了 5000 块钱,自己再刷信用卡刷了 2500,耗资 7500 购买了一台当时很牛逼的 ThinkPad T400,从此非工作时间我就可以拿着我的电脑在办公区使用 Wi-Fi 网络畅游互联网了,感谢借钱给我的同学!就在我购买电脑之后,我购买了人生中的第一个正版软件『Nod32』为期 1 年半的服务,从此开始了自己数字消费之路。在我离开『超图』加入『喜讯』之后的第一个月,我购买了 Puff 的商业版。Puff 有个特性让我很感动,因为那时候自己每天都是在 Ubuntu 下进行开发,所以有跨平台的需求,Puff 可以在 Wine 的托管下非常好的运作,这样我就可以在家里和办公室都顺畅地使用 Puff 了。其实这一年使用 Puff 的主要需求也就是上上 Twitter,看看别人每天都在刷什么,看看自己能不能跟上潮流,就这么 Puff 帮助了我科学上网了一年时间。

AWS EC2 + SSH 在 Puff 服务到期之际非常及时的补上了缺,当时 AWS 在做活动,免费赠送 1 年的 EC2 服务时间,办公室里头 4 只程序猿果断掏出信用卡绑定上,免费的优质服务必须体验一下嘛。当时选择的是旧金山机房,貌似还不错,刚刚好当时自己的这个博客站点所托管的主机服务器也要到期了,所以正好把博客也迁移到了 EC2 上(这个要感谢我们的振警梁同学),EC2 的稳定让我这一年几乎从未因为无法科学上网而发愁,简简单单『ssh -CfNg -D 127.0.0.1:7070 [your_user_name]@[your_host_name_or_ip_address]』一句话,配合浏览器 Firefox 的 AutoProxy + gfwlist 简直就是倚天屠龙啊,感谢 AWS 免费提供了一年高效稳定的服务。

免费的午餐抵不了成天的肚饿啊,EC2 到期之后,跟同事一起合租了一个 VPS,把大家自己的博客站点都挂上去之后,平时依然当做科学上网工具来使用,但是试过了多个 VPS,稳定性都实在无法跟 EC2 相提并论,多方寻觅,最后选择了一个 42 区的 VPS,价格也合适,刚刚使用的一段时间也很不错,不过后期经常宕机的毛病,让我们实在无法继续忍受。最终我们把 VPS 迁移到了一个 SSD Cloud VPS 平台了,就是现在持续在使用的 Digital Ocean,我们选择的是最基础的套餐,20G SSD Disk,512M RAM,1TB Transfer,每个月$5,一年下来不到 400 人民币,还算划算,也还算稳定,重启机器也很方便。在购买 Digital Ocean 的服务之前,因为无法忍受其他 VPS 龟速的网络以及各种宕机的问题。我已经购买了 VPN Tech 的服务,这家 VPN 的网速还是相当不错的,配置也简单,可以直接使用域名进行连接设置,区分了各大地区,还区分了下载服务器,在提供付费 VIP 服务的同时,也提供了免费的试用服务。如果家里的网络稳定的话,看 Youtube 视频完全不是问题,而且最多支持 5 台设备同时在线,对于有多设备需求的人来说非常合适,其实这一个帐号都完全能够支撑一家子人使用了。

持续了使用了 VPN Tech 的服务之后,因为一直都是使用 v.avpn.us 这个域名进行连接,而有时候就是会连不上,最后发现使用 hk.avpn.us 连接会更快也更稳定,但是偶尔还是会出现掉线或者偶尔出现无法连接上 VPN 服务器的情况,而通常自己想用 VPN 的时候已经是比较着急的时候了,这么折腾几回之后,也尝试了一家香港的 VPN 服务 Green 网络加速器 ,网速非常强劲,稳定性也非常不错,只是我只用了一个月,因为对同时连接设备数限制太多,我又通常需要在我的电脑和手机上同时使用,不太适合我。

连续使用了两年多的 VPN 服务,感觉也还可以,但是总会出现一些不如人意的事情。其实我们自己现在使用的 VPS 上也有搭建 VPN 服务,偶尔也会使用一下,但是也偶尔会出现无法连接的情况,当然也可以使用 SSH 的方式,还是那句话,太折腾又时有不如人意的事情发生。折腾这些事情呢又总是很费时间,而且很容易让人心情不好,特别是在你需要科学上网的时候,喀给你来那么一下,你能舒服吗?

所以,我把目光投向了更专业的一些服务,当然价格也稍微贵一些,类似于『曲径』和『轻云』(貌似已经被墙了),最终我选择了 MacTalk 一直推荐的曲径,正所谓『曲径通幽处』我想你懂的,别想歪了啊。曲径这类服务其实本质上就是一个 Http/Https 代理,配合 PAC(Proxy Auto-Config) 文件进行分流,让你需要科学上网的时候通过曲径的服务器进行加密访问,不需要科学上网的时候直接访问,这样一来也不再需要担心流量问题(我每天都用 Spotify 听音乐,流量都能足够),而且配置极其简单,移动设备配置也非常方便。只是目前 Android 设备需要有 Root 权限才可以使用曲径的服务,这个让我感觉还是蛮蛋疼的,其他的都还好。当然曲径不能帮你解决所有的问题,她只能帮你解决使用系统默认代理设置,或者可以手动设定 Http/Https 代理的软件科学上网的问题,比如某些软件不提供代理设置方式又不使用系统默认的代理设置,这个时候 VPN 还是有作用的。

科学上网是一个渴望自由访问互联网内容的程序员的必修课,修这么课的同时就能让我了解到很多技术上的东西,也拓展了视野,最终成为了一个可以随时随地自由访问互联网的人。对此,我很开心,很感谢这些为我们提供各种科学上网服务的人们所做的各种努力。

谈谈理想吧

离开校园快 5 年了,记得还在学校的时候,我们不时地会畅想一下未来,虽未必在谈理想,起码也算是年少时美好的憧憬吧。

曾经跟宿舍好友们,坐在学校旁边小吃街的小餐馆里头,喝着冰啤酒,吃着长沙火辣的家常菜,不少个夜晚,跟不同面孔的同学,纷纷表达过自己对未来的各种憧憬,也有对未来未知的一些恐慌。

如今,回头看看,还是蛮有意思的。曾经讨厌写程序的 GM 在毕业之后加入南方测绘公司某旗下子公司,在两年之内成为了研发部门的中坚力量,每日与代码厮磨。我们最可爱的班长– 猪头,在成功完成了保送的硕士研究生学业之后,如愿以偿地回到了福建厦门,虽然离他回到老家罗源还有一点距离,但是也算是圆满了。我们的亢芬同学,更是在一年之内终于成功嫁给了一个好老公,成为了光荣的军属。赵姐和赵胖的爱情结晶更是健健康康地来到我们身边,虎头虎脑的甚是可爱。偶像思麦如愿以偿地成为了自己一心想成为的游戏开发者,不知到偶像现在是否依然热爱和享受着制作游戏的那份快感。老比终于打破了这四年来我们一直的疑惑,选择了离开 GameLoft 前往深圳再次创业去也。刘琪最终没能持续做游戏,与我在喜讯相伴两年之余后,离开加入了 Tencent 大家庭,工作之余从未放弃为我国 GIS 行业的互联网化做着实际的工作和思想上的探索。而我,依然还在喜讯这个集体中,辛苦并坚持着。

曾经很多次跟同学聊天,有大学的同学,也有高中的同学,甚至老家的发小,都曾经问过我类似的问题,你们怎么这么辛苦?都这么些年了,你图什么,得到了什么?

首先,我在喜讯这几年确实很辛苦,工作时长平均每周 70 个小时以上,这没有什么值得炫耀的,说句难听的话,这说起来都是泪啊。
其次,我在喜讯这几年,目前得到了所有我应该得到的,公司给予我的跟我为公司做的,我认为是对等的,甚至公司给予我的多于我目前所创造的,未来会更加平衡一些。
最后,我图什么,其实我也不是特别清楚自己图的是什么,只是这一路走来,自然而然就成了现在的状态。

回到标题,谈谈理想。

在我们曾经年轻的日子里(貌似我现在也还没老哦),我们都曾美好地憧憬过未来,寄予美妙的幻想。我也曾多次问过自己,我的理想是什么?回过头看自己这 26 年里,自己一直想做的事情,貌似除了写作还真没有什么其他的想法。

在自己还是个小孩子的时候,就曾经梦想自己有一天能著书立作给别人看,除了这个一直保存在内心的小愿望,还有就是有一颗较为强烈的成为有钱人的原始欲望的心。也许是因为从小,家中家境一直不算好,在老家父母二人就是普通的农民,只是父亲自己年轻时候比较愿意学,也确实学过几年木工,所以父亲在老家还算是有一技之长的木匠,家中有我和弟弟两个孩子,父母辛苦大半辈子还算顺利地让我俩都大学毕业了。但是家境并没有因为我和弟弟二人的毕业加入工作之后顿时好转起来,只是已经不再像之前那么捉襟见肘了。正是出于对现实生活很多不确定因素的恐慌,以及多年来看着父母因为物质条件从未能真正地享受属于他们自己的生活,即便如今,二老在家依然劳作,说是趁着自己还能干得动,需要给我们攒点钱,能给我们减轻一点负担算一点。当我每次听到父母这番话时,作为长子长孙的我,我只有一个想法,我要让这个家庭不再那么穷。穷是一个很搞笑的字,看起来就像一个人在天底下,很用力的干活。穷人的姿态也许就是这般吧,我的爷辈,父辈,包括我自己,也许都会一直在天底下以这种姿态长时间地存在着。

不过,我跟我父亲一样,我们相信只要自己努力付出,总会有所回报,我的父母通过自己勤劳的双手,将我跟我弟弟送入大学,而且从未让我和我弟弟在生活上感觉到非常的困窘,他们真的很了不起。我想我起码应该在我父母给我创造的基础上,延续我父母的成就吧,也就是确保我能给我的后辈一个更好些的基础。多么原始和简单的欲望,纯粹就是出于本能的欲望。但是,不可否认的是这个欲望支撑了我很久,直到现在这个依然是我愿意付出我所有努力来达成的首要目的。

作为小学生的我,初中生的我,高中生的我,大学生的我,从未想过自己将来会成为科学家,警察,军人等等,唯独曾经梦想过的就是成为一个可以写作给很多人看的人。如今作为一个程序员的我,过得也非常开心。我有一个非常理解我的女友,有一个非常支持我的家庭,有一份我觉得满意的工作,有一群我觉得可以托付的同伴,真的很难得。

理想很多的时候感觉像是奢侈品,可望而不可及。跟身边很多的人都聊过类似的问题,大部分人的第一反应是“哪儿来的理想啊?”,大家普遍都会谈到很多现实的问题,然后最终得出一个结论就是自己即便是有理想,那都是空想。其实从侧面来看,其实每个人都是有理想的,只是大家通常认为因为现实的各种压力,我们已经没有机会实现自己的理想了。当然我也不能免俗,我也经常这么认为,认为自己不可能实现理想,甚至都认为自己根本就没有理想。只是在随着社会大流,一步一步地走到今天,成为一个社会最基层的建设者,默默地在自己的岗位上发光发亮,兴许会被人发现,当做一颗璀璨明星,兴许就如此慢慢黯淡下来。

现实诚然如此,在成长的路上,我们看到了很多风景,总是梦想有一天自己也能如此享受此般美好,殊不知时间的美好就只有那么多,人人都想拥有,谈何容易。所以我们说要奋斗,只有奋斗才能改变自己的命运,才能让自己站到人生的塔尖,看到更多更美的风景。于是,就有了很多个奋斗之后享受成功喜悦的梦。我自己也有过这样的梦,很直接很直接的梦,梦想有一天自己所在的创业公司能上市,自己作为初创团队的一员,在公司上市之际直接晋升到塔尖。WTF,多美美妙的一刻啊,此时站在塔尖望着下面还在为我此时享受的这一刻奋斗的人们,多么的惬意啊。

成功变成了我们的梦,我们的理想呢?我想即便到了那一时刻,其实离我儿时唯一的理想还是很远,我完成了自己的一个期望也完成了一个作为家族长子所背负的期望。也许那个时候我也会很快乐,可是谁知道呢。

在喜讯创业已经 3 年有余了,成功的影子慢慢显现,但是能否最终成真没有人能说得清。只有靠自己的努力,靠一众兄弟姐妹们的努力,兴许可以成功。喜讯的成功是不是我的理想?我想在目前的阶段里,这肯定算是我的一个很重要的目标,但是远谈不上理想。创业成功对于有些人来说是理想,对于我而言是手段,这是我摆脱经济困境的唯一手段,我为此会付出所有我能付出的东西。获得成功能让自己获得经济自由,是否我就会开始寻找儿时的理想呢?其实我也不知道,儿时的理想如果真的有如此强烈的话,也许我现在已经开始朝着这个方向前进了,可是我没有。

所以有的时候我就在想,其实理想可能真的跟初恋很像。很刻骨铭心,但未必会是最终的相守,她永远会占据你内心的某个角落,偶尔还会跳出来给你带来一阵阵的瘙痒,让你阵阵地感怀。时间一过,所有一切如常。

也许我真的没有什么理想,有的还就是短时间之内的各种目标,结婚,生子,赚钱,养家,等等。坚持自己有一个理想,无非是想偶尔能让自己显得不是那么的俗不可耐,给自己脆弱而又自负的内心些许救赎性的安慰。告诉自己,这些丑陋的社会现实,这些完全不能理解我的人们,他们不知道我内心想要的是什么,我做不好这个事情其实是因为我的理想根本就不是做这个事情,我要做的是更美好更高尚的事情。多美好的理由啊,还是允许像我这般渺小的人类拥有如此可笑的理由吧。

放下那个远大而崇高的理想吧,回到地球上来,为现在能努力做到的事情多尽一份心,多出一点力,踏实走每一步路,也许哪天真的会跟那个理想再次重逢,就跟结婚多年以后与初恋重逢那种释然的感觉,两者相视而会心一笑。

来喜讯三年了

刚刚来喜讯的时候,老大跟我聊得很多,差不多每周都会有一次独立的对话,会聊的事情会比较宽泛,包括如何做产品,技术人员如何成长,跟设计人员如何配合,如何跟家人相处,如何做好一个朋友等等。其中经常出现的一个话题是关于个人职业规划与成长的,有一句话是这样的“三年一个坎,五年一个坎,十年一个坎”。大体的意思就是,当我们开始进入职业岗位上,三年时间会是一个阶段,五年又是一个阶段,十年呢又是另一个阶段。

我来喜讯已经三年了,再此之前我在超图待了一年的时间,也就是说我的三年这个坎是在喜讯度过的,如今已经是在喜讯的第四个年头了。

==== 时隔一周继续开始写 ====

在喜讯待的这三年里头,学到了很多的东西,技术上的大部分都是靠自己一点点摸索尝试,也有很多是跟同事们一起讨论争执中明白的,关于产品和项目的,大部分都是老大手把手教的,慢慢地开始需要承担一些项目管理和产品设计上的工作。

在这三年里头,做了几个项目,黄金矿工喜讯特别版,喜讯天天,画说,MARK,铁血战神。带了 3 位小兄弟,但是目前 3 位小兄弟均已离开了。目前项目中程序有 4 个客户端程序,1 个服务端程序,客户端程序这边由我来推动,整个项目包括美术组与程序组这边的协调,策划和运营与程序这边的沟通,我也多少有些参与。

目前碰到了最大的问题就是我还没有学会如何在项目管理和程序开发中找到一个平衡点,在自己不愿意放弃程序开发的前提下,自己总会陷入到技术问题的解决和执行中,时常会忽略了项目中各种节点的确认和资源的协调,项目成员会出现工作量不平衡,经常出现大家在等某个资源而没有事情做,某些人又积压着过多的工作。

做个记录吧!

CentOS 64 位机器安装配置 Jenkins 集成编译 Android 项目

之前一直想在公司搭建一个集成编译的环境,一直没能成行,这次终于着手去做了,发现之前的 Hudson 已经演变成了如今的 Jenkins,关于 Oracle 跟各个开源社区以及其他厂商的一些关于商标的纷争真的很有意思,我觉得未来有可能的话,真的可以专门写一些关于这个话题的东西。具体可以参考 wikipedia 上的 介绍

因为 Jenkins 是基于 Java Servlet 实现的,所以需要依赖于某个 Servlet Container 来运行,我选择的是 Apache Tomcat。Tomcat 也是基于 Java 实现的,那么开始第一步吧。

第一步 安装 SDK

自行下载 JDK,安装配置环境变量,如下:
[bash light=”true”]
export JAVA_HOME=/usr/local/jdk1.6.0_29
export PATH=$JAVA_HOME/bin:$PATH
export CLASS_PATH=$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:.
[/bash]

第二步 安装配置 Tomcat

下载 tomcat 安装包,直接解压,配置环境变量:
[bash light=”true”]
export CATALINA_HOME=/root/apache-tomcat-7.0.33
[/bash]
在 CentOS 的/etc/sysconfig/iptables 配置文件中加入规则:

通过$CATALINA_HOME/bin/startup.sh 启动 tomcat,找个浏览器试试能否访问,http://your_centos_server_ip:8080

确认 tomcat 能正常访问之后,开始第三步

第三步 安装配置 Jenkins

Jenkins 的主页 下载 Jenkins 的 war 文件,将该文件拷贝至$CATALINA_HOME/webapps 目录下,tomcat 会自动将 war 文件解压并部署,找个浏览器试试能否访问这个地址 http://your_centos_server_ip:8080/jenkins,如果可以的话那么 Jenkins 就算是部署好了。

第四步 配置 Android SDK 和 NDK 环境

这一步可能会稍微多一些,可以参考我的这篇文章,CentOS 64 位机器配置 Android SDK 和 NDK 环境

第五步 创建一个 Jenkins 的 Job

完全按照 Jenkins 的提示和帮助一步步进行下午,非常简单。

  1. 给 Project 设置名称
  2. 配置获取最新代码的方式,Jenkins 目前自带了 CVS 和 SVN 的插件,如果你的代码是通过 git 来管理的,只需要安装一个 git 的插件即可,Jenkins 有非常丰富的插件,Jenkins => Manage Jenkins => Manage Plugins,进入插件管理页面,打开 Available 的 Tab 页面,在 Filter 中输入 git,然后找到 Jenkins GIT plugin,勾选前面的复选框,之后点击页面下方的 Download now and install after restart,让它自己安装然后重启吧,重启之后就可以配置通过 git 来获取代码了
  3. 设置编译触发器规则,应该是完全和 Linux cron 的规则一致,可以 google 之。
  4. 配置如何编译方法,在服务器上我们肯定是脱离 ADT 环境的,通常我们会使用 Ant 来进行编译,自行下载并配置 Ant 的环境变量,确保 ant 命令可以正常使用
  5. 先通过 android 命令更新当前需要编译的项目,确保 ant 能找到正确的 sdk 路径和其他的配置,需要编译 release 包的话,可以在 project.properties 中配置好用于签名的 keystore 文件,具体可以参考 这篇文章 ,然后在 Jenkins 中配置 shell 中输入 android update project -p $WORKSPACE -n 工程名 -t 编译目标
  6. 配置 Ant 编译目标为 release
  7. 点击 Save 之后,回到 Job 的首页面,点击 Build Now,开始编译吧。可以通过查看 Console Output 来看所有编译的输出信息,有错就一一排查吧。