DevOps on Android: 加速 App 從代碼到上線

DevOps 是一個眾所周知的開發(fā)方法装哆,其主要目的是自動化軟件交付。事實上定嗓,DevOps 的目標(biāo)是不斷的測試蜕琴,代碼質(zhì)量,功能開發(fā)宵溅,更容易維護版本凌简。因此,DevOps 的一個最終目標(biāo)是為開發(fā)者進行快速恃逻,可信賴和自動化發(fā)布提供指導(dǎo)雏搂,理想化狀態(tài)是在這個過程中不牽涉任何人工勞動。這就是所謂的持續(xù)交付寇损。我寫這篇文章來證明凸郑,我們現(xiàn)在能在 Android 平臺上達成這樣的目標(biāo),同時和大家分享一下我的想法和聽取大家的反饋矛市。

持續(xù)集成為出發(fā)點

想要達到持續(xù)交付芙沥,持續(xù)集成必須是強制的。在安卓平臺上的持續(xù)集成已經(jīng)有一段時間了浊吏,為了更清楚的去了解而昨,我們先說一下它的優(yōu)勢。

安卓平臺必須采用持續(xù)集成方法卿捎,是的我說過配紫。確實,持續(xù)集成有一些在構(gòu)建 Android App過程中無法發(fā)忽略的好處午阵。在我看來躺孝,它的優(yōu)勢在于:

  • 自動化構(gòu)建:不再只是在我的機器享扔,而是在所有的環(huán)境。

  • 早失斨才邸:一旦代碼提交之后就馬上構(gòu)建惧眠,這樣就保證錯誤能被及早的發(fā)現(xiàn)。

  • 構(gòu)建測試:保證每一個測試用例都能正常運行于个。

  • 不斷打包:防止打包過程中的人為錯誤氛魁。

  • 快速發(fā)布:既然我們對于每一次構(gòu)建都有信心,那么發(fā)布就變得簡單了

  • 增加信心:最后厅篓,我們相信我們的代碼秀存,我們的過程,我們減少不良的驚喜羽氮。

一個典型的持續(xù)集成過程

首先或链,我們需要一個集成服務(wù)器像Jenkins 或 Travis 。下面的工作是我的標(biāo)準配置:

  • 啟動一個監(jiān)視代碼推送到我們的代碼倉庫(Jenkins or Travis)完成事件的任務(wù)档押。該任務(wù)監(jiān)視代碼的 dev 分支去自動的編譯澳盐、單元測試、打包或者 debug APK .

  • 當(dāng)上面的任務(wù)完成之后令宿,另外一個任務(wù)就要被啟動了叼耙。這個任務(wù)主要用來跑集成測試(通過 Espresso 或者 Robotium)。在這個過程中粒没,通過模擬用戶場景和檢查渲染的圖形內(nèi)容的方式來保證最終的用戶體驗筛婉。

  • 另外一個任務(wù)就是一個每天晚上都會運行的執(zhí)行代碼質(zhì)量掃描(例如 Sonarqube )的任務(wù)。

  • 最后還有一個任務(wù)用來檢測一旦代碼倉庫的 master/release 分支有更新就去構(gòu)建發(fā)布的APK包革娄。

看看吧倾贰,正如你看見的,這個過程很簡單并且保證能達成我開始所說的優(yōu)勢拦惋。

測試是關(guān)鍵

我曾經(jīng)寫過一篇關(guān)于測試的文章(testing on Android)匆浙。測試是如此的重要因為它是能夠保證App按照我們所設(shè)定的那樣去工作的唯一工具。寫單元測試有很多工具和方法厕妖,請明智的去選擇首尼。
此外,確認一下你要在你的應(yīng)用程序集成的庫言秸。事實上软能,當(dāng)你使用的庫有一個良好的單元測試覆蓋率的時候,就更容易測試您的App举畸。一些被認為恰當(dāng)測試的并且用測試驅(qū)動他們的開發(fā)的類庫(例如 IMO, OkHttp and Retrofit )查排。很可能,你將能夠在使用它的時候來測試它抄沮。
最后跋核,像 Dagger 庫可以幫助你提高可測試性岖瑰。事實上,它會迫使你遵循單一職責(zé)原則和正確分開你的代碼砂代,從而更容易測試蹋订。
一旦你有一個強大的持續(xù)集成,讓我們來看看如何提高水平刻伊。

持續(xù)交付: Level++

舉例來說露戒,在 Captain Train。我們發(fā)布每6周一次捶箱,我們都非常小心了智什。 目前每次發(fā)布都要做:

  • 我們有一個測試階段
  • 我們支持 4 個區(qū)域設(shè)置。
  • 我們支持 3 種類型的設(shè)備(phone, 7 and 9 inches tablets)讼呢。
  • 我們經(jīng)常檢查我們的的 Play Store撩鹿。
  • 我們寫發(fā)行說明。
  • 我們使用部署功能悦屏。
  • 我們上傳了 72 截圖(6 screenshots * 4 locales * 3 types)

整個過程非常消耗時間,最近我們想键思,是時候去把這個過程給自動化了础爬。即使我們的最終目標(biāo)是減少發(fā)布時間。這種感覺非常好吼鳞,去防止人為的犯錯誤以及經(jīng)常的發(fā)布發(fā)布看蚜。我們能掌握整個過程,這樣讓我們更加有責(zé)任心赔桌。

但是供炎,坦白的說,安卓開發(fā)者不能控制所有的事情疾党,只有 Google 能做到音诫。
例如,它暴露了一個 HTTP API雪位,使開發(fā)人員能夠使用 Play 商店控制臺輕松互動竭钝。他們也提供了很多語言實現(xiàn)的語言包,例如Java 雹洗,Ruby 等香罐。

在這篇文章,我講專注于 Java 語言时肿,因為對于安卓開發(fā)者來說庇茫,這是最容易的。

編寫你自己的 App 發(fā)布工具

讓我們看看如何編寫自己的 App 發(fā)布工具來把 APP 發(fā)布到 Play Store 螃成。大概有兩個步驟:首先旦签,我們將配置我們的控制臺查坪,使我們的客戶端能夠進行操作,進而我們就會發(fā)現(xiàn)其中的 API顷霹。最困難的事情經(jīng)常用谷歌去配置咪惠。文檔()可以在這里找到。請注意淋淀,這是一個有點過時遥昧。
配置
首先,如果沒有做朵纷,你必須在谷歌控制臺創(chuàng)建一個新的項目炭臭。然后,我們需要啟用 Google Play Android Developer API袍辞。

一旦完成鞋仍,我們必須創(chuàng)建服務(wù)帳戶關(guān)鍵的憑證:

最后填寫表格,并下載一個 json 格式的憑證搅吁。你需要保存三個值:private_key_id, private_key 威创、 client_email. 把 private_key 的值保存在 secret.pem 中.
我們正在與開發(fā)者控制臺交互......現(xiàn)在讓我們?nèi)サ降诙€控制臺! \ O /
連接到您的控制臺谎懦。你必須進入 Settings > API access:



然后肚豺,你必須簡單地鏈接您的項目。最后界拦,在 Service accounts吸申,授予權(quán)限給你下的 JSON 文件中的的客戶端郵件的client_email。

到現(xiàn)在為止享甸,一切都準備好了截碴。
API發(fā)現(xiàn)
現(xiàn)在,讓我們深入到 Java 客戶端 API蛉威。我們創(chuàng)建了一個單獨的 Java 項目為我們的發(fā)布工具日丹,我們添加下面的依賴(Maven的中央倉庫有):

compile 'com.google.apis:google-api-services-androidpublisher:
         v2-rev20-1.21.0'

下一個步驟是創(chuàng)建一個 AndroidPublisher。首先我們通過提供 transport client, JSON factory瓷翻,和 private_key_id 對應(yīng)的 private key ID聚凹,和 client_email 對應(yīng)的賬戶 ID 來實例化一個 GoogleCredential。ANDROIDPUBLISHER 是一個包含了私鑰的關(guān)鍵文件齐帚。

http = GoogleNetHttpTransport.newTrustedTransport();
json = JacksonFactory.getDefaultInstance();

Set<String> scopes =
      Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER);

GoogleCredential credential = new GoogleCredential.Builder().
                setTransport(http).
                setJsonFactory(json).
                setServiceAccountPrivateKeyId(KEY_ID).
                setServiceAccountId(SERVICE_ACCOUNT_EMAIL).
                setServiceAccountScopes(scopes).
                setServiceAccountPrivateKeyFromPemFile(secretFile).
                build();

publisher = new AndroidPublisher.Builder(http, json, credential).
                setApplicationName(PACKAGE).
                build();

AndroidPublisher 對象是Google控制臺的主入口笼恰,他有一個 Edit 方法亩钟,允許我們編輯控制臺的數(shù)據(jù)。
要開始一個新的版本,你必須以發(fā)起插入請求长踊,并存儲它的返回值位喂,你會在每一個后續(xù)調(diào)用中使用這個返回的 ID。

AndroidPublisher.Edits edits = publisher.edits();

AppEdit edit = edits.insert(PACKAGE, null).execute();
String id = edit.getId();

現(xiàn)在我們將改變我們的控制臺數(shù)據(jù),舉例來說改變 listings:

Listings listings = edits.listings();

Listing listing = new Listing().
                        setFullDescription(description).
                        setShortDescription(shortDescription).
                        setTitle(title);

listings.update(PACKAGE, id, "en_US", listing).execute();

你也可以上傳截圖

Images images = edits.images();

FileContent content = new FileContent(PNG_MIME_TYPE, file);

images.upload(PACKAGE, id, "en_US", "phone5", content).execute();

最后一個例子拴签,讓我們上傳一個 APK

// APK upload
Apks apks = edits.apks();
FileContent apkContent = new FileContent(APK_MIME_TYPE, apkFile);
Apk apk = apks.upload(PACKAGE, id, apkContent).execute();
int version = apk.getVersionCode();

// Assign APK to Track
Tracks tracks = edits.tracks();
List<Integer> versions = Collections.singletonList(version)
Track track = new Track().setVersionCodes(versions);
tracks.update(PACKAGE, id, "production", track).execute();

// Update APK listing
Apklistings apklistings = edits.apklistings();
ApkListing whatsnew = new ApkListing().setRecentChanges(changes);
apklistings.update(PACKAGE, id, version, "en_US", whatsnew).execute();

我推薦大家使用 API,因為它很完美并且很強大旗们。
最后一步蚓哩,你必須提交你的版本。事實上上渴,到目前為止岸梨,谷歌記錄您所請求的每一個變化,但是它只會保存您提交的變化稠氮。我也建議你嘗試提交之前驗證您的更改曹阔。

edits.validate(PACKAGE, id).execute();
edits.commit(PACKAGE, id).execute();

正如你看見的那樣,開始所獲取的 ID隔披,就像是一個事務(wù)ID 一樣赃份。你開始事務(wù)之后,通過 insert, update/upload 來處理變化奢米,并且通過 validate 方法驗證 抓韩,通過commit 方法提交。一切都如此簡單鬓长。

討論

現(xiàn)在我們可以遵循 devOps 原則园蝠,甚至對于安卓開發(fā)來說有了比較強大的持續(xù)交付能力。在 Captain Train 我們選擇去寫我們自己的發(fā)布工具以此來控制重要的每一個步驟痢士。一旦 release 任務(wù)執(zhí)行成功,我們就執(zhí)行發(fā)布工具來發(fā)布 App茂装。當(dāng)然了Jenkin 和 Gradle 也有一些類似的工具可用怠蹂。

諸如此類的工具能讓你簡單的通過向 master 或者 release 分支推送代碼的方式來發(fā)布你的App。這個過程簡單少态、可信賴城侧、節(jié)省時間!
很明顯彼妻,這個過程不一定適用于每個團隊/公司/應(yīng)用程序~ ,這取決于你所在團隊的具體情況嫌佑。但是,我要強調(diào)的是持續(xù)交付應(yīng)該是每一個團隊/公司的目標(biāo)侨歉。一旦達成屋摇,它將驅(qū)動您走向成功。

原文:http://jeremie-martinez.com/2016/01/14/devops-on-android/

OneAPM Mobile Insight 幽邓,監(jiān)控網(wǎng)絡(luò)請求及網(wǎng)絡(luò)錯誤炮温,提升用戶留存。訪問 OneAPM 官方網(wǎng)站感受更多應(yīng)用性能優(yōu)化體驗牵舵,想閱讀更多技術(shù)文章柒啤,請訪問 OneAPM 官方技術(shù)博客倦挂。
本文轉(zhuǎn)自 OneAPM 官方博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市担巩,隨后出現(xiàn)的幾起案子方援,更是在濱河造成了極大的恐慌,老刑警劉巖涛癌,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件犯戏,死亡現(xiàn)場離奇詭異,居然都是意外死亡祖很,警方通過查閱死者的電腦和手機笛丙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來假颇,“玉大人胚鸯,你說我怎么就攤上這事”考Γ” “怎么了姜钳?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長形耗。 經(jīng)常有香客問我哥桥,道長,這世上最難降的妖魔是什么激涤? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任拟糕,我火速辦了婚禮,結(jié)果婚禮上倦踢,老公的妹妹穿的比我還像新娘送滞。我一直安慰自己,他們只是感情好辱挥,可當(dāng)我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布犁嗅。 她就那樣靜靜地躺著,像睡著了一般晤碘。 火紅的嫁衣襯著肌膚如雪褂微。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天园爷,我揣著相機與錄音宠蚂,去河邊找鬼。 笑死腮介,一個胖子當(dāng)著我的面吹牛肥矢,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼甘改,長吁一口氣:“原來是場噩夢啊……” “哼旅东!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起十艾,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤抵代,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后忘嫉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荤牍,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年庆冕,在試婚紗的時候發(fā)現(xiàn)自己被綠了康吵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡访递,死狀恐怖晦嵌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拷姿,我是刑警寧澤惭载,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站响巢,受9級特大地震影響描滔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜踪古,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一含长、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧伏穆,春花似錦茎芋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽涛酗。三九已至铡原,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間商叹,已是汗流浹背燕刻。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留剖笙,地道東北人卵洗。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親过蹂。 傳聞我的和親對象是個殘疾皇子十绑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,183評論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)酷勺,斷路器本橙,智...
    卡卡羅2017閱讀 134,669評論 18 139
  • DevOps 是一種廣為人知的活動,其主要目的是使軟件交付自動化脆诉。的確甚亭,DevOps 的目標(biāo)是持續(xù)測試、代碼質(zhì)量击胜、...
    OneAPM閱讀 1,230評論 0 3
  • 剛剛過去的周末偶摔,有24小時的時間值得記錄暇唾。 24小時,是兩個12小時啰挪。兩個12小時分別分布在兩天的時間里信不。第一個1...
    梅洛的聽雨軒閱讀 370評論 2 3
  • 在認知中有兩個認知因素,吸煙有害健康(Y)及我不吸煙(X) 吸煙有害健康(Y)我不吸煙(X)吸煙有害健康(Y)我吸...
    世界外面不安靜閱讀 265評論 0 0