DevOps 是一種廣爲人知的活動,其主要目的是使軟件交付自動化。的確,DevOps 的目標是持續測試、代碼質量、功能開發和更輕鬆地進行維護更新。所以,DevOps 的終極目標之一是讓開發者能夠執行快速可靠、自動化的發佈,理想狀態下,整個流程都不須要人爲操做。這被稱爲持續交付。撰寫本文的目的是展現咱們如今也能在安卓上實現這一目標,同時分享筆者的想法和反饋意見。html
爲了實現持續交付,必須確保強大的持續集成。這已經在安卓環境實行一段時間了,可是爲了清楚起見,我們仍是回顧一下吧。android
首先,任何安卓應用程序都應具有持續集成。是的,筆者就是這個意思。實際上,這爲現代應用程序開發帶來了不可忽視的幾個好處。在筆者看來,最大的優勢是如下幾項:git
構建自動化:告別「可是在個人機器上能夠構建成功」。應用程序在哪裏都能構建。github
儘早試錯:每次推送後都進行構建能夠確保儘早發現錯誤。json
測試持續化:確保測試始終進行api
持續打包:在打包二進制代碼時避免人爲錯誤。性能優化
發佈速度更快:由於咱們對每一步構建都有信心,發佈也變得更加簡單。服務器
信心加強:終於,咱們能夠信任本身的代碼和流程,而且減小意料以外的錯誤。網絡
First, we need an integration server like Jenkins or Travis. The following jobs are my standard configuration:app
首先,咱們須要一個 Jenkins 或者 Travis 那樣的集成服務器。如下做業是筆者的標準配置:
• 一旦源碼存儲庫(Git、SVN等等)中的推送完成,就會開始一個做業。它會查看 dev 分支、編譯代碼、運行單元測試,並打包調試 APK。
• 第一個做業成功完成後,運行下一個做業。它會運行集成測試(經過Espresso 或 Robotium),經過重現場景和檢查圖像內容來確保用戶體驗。你可使用鏈接設備(若是你的 CI 服務器不容易獲取的話,就有些困難)、Genymotion 或隨 Android Studio 2.0 發佈的最新內置模擬器(快去試試吧!)來操做。
• 一個做業會運行代碼測量(舉個例子,經過 Sonarqube)以監測代碼質量。例如,筆者會在天天半夜運行這個做業。
• 最後,在咱們推送 master 分支或發佈分支後運行一個做業。它會編譯代碼,並生成發佈 APK。
好啦!如你所見,操做很是簡單,並且能保證筆者以前列舉的全部優勢。
筆者曾寫過一篇關於安卓測試的文章。測試很是重要,由於它是能自動證實咱們的應用按計劃運行的惟一方法。有不少工具能夠幫咱們寫出優秀的測試代碼,因此要明智地進行選擇。
同時,在選擇集成到應用中的函數庫時要實事求是。實際上,你應該明白若是函數庫的測試覆蓋率較高,測試應用程序就會更輕鬆。他們已經考慮到如何正確測試和經過測試促進開發的問題了(IMO、OkHttp 和 Retrofit 都是很好的範例)。至關於你在使用的同時就進行了測試。
最後,相似 Dagger 的函數庫能夠增長可測試性。實際上,它會迫使你遵守單一職責原則,而且將代碼正確分離,這樣測試就更加容易。
一旦你擁有了強大的持續集成,咱們來看看怎麼升級吧。
舉個例子,在 Captain Train,咱們每6周發佈一個新版本,而且對此很是謹慎。目前:
• We have a beta phase.
• We support 4 locales.
• We support 3 types of device (phone, 7 and 9 inches tablets).
• We always check our Play Store listings.
• We create release notes.
• We use the rollout feature.
• We upload our 72 screenshots (6 screenshots * 4 locales * 3 types)
• We have a wear companion.
這個流程須要花時間,並且不止一點兒。最近,咱們決定是時候嘗試把這個流程自動化了。雖然主要目的是爲了減小發布版本須要的時間,可是若是同時也能避免人爲錯誤,保持各個發佈版本之間的連貫性,就更好了。這也讓咱們擔負了重大的責任,由於開發者控制了整個發佈流程。實際上,市場和傳播團隊也要跟咱們一塊兒看看怎麼將他們的變化集成到發佈版本中去。
可是坦白說……在安卓,開發者並不能控制全部的事情。谷歌能夠。可是,它提供了 HTTP API,使開發者輕易地與谷歌電子商店控制檯互動。他們還提供了各類開發語言的客戶端,例如 Java(這是必須的!)、Phython、Ruby,等等……
在本文中,筆者將主要討論 Java 客戶端,由於這極可能是安卓開發者最瞭解的開發語言。
讓咱們看看如何編寫定製化的谷歌電子市場 publisher。分爲兩步:首先,咱們要配置控制檯,讓客戶端可以操做,而後探索 API。一般跟谷歌創建鏈接時最困難的就是配置……相關文檔能夠在這裏找到。請注意,文檔也許不是最新版的。
首先,若是沒有現成的,你須要在谷歌控制檯新建一個項目。接下來,咱們須要啓用 Google Play Android Developer API
。
Once it is done, we must create a credential of type Service account key:
完成以後,咱們必須建立一個 Service account key
類型的證書:
最後,填寫小表,下載 JSON 格式的證書文件。你須要保存三個值:private_key_id
、private_key
和 client_email
。把 private_key
的值保存到它本身的 secret.pem
文件。
開發者控制檯搞定了……如今咱們來看第二個控制檯吧!
鏈接到你的電子市場控制檯。你須要依次訪問 Settings
> API access
:
接下來,你只須要鏈接你的項目。最後在 Service accounts
,受權你在 JSON 文件的 client_email
處填寫的郵箱地址。
如今好了。一切搞定!
如今讓咱們經過 Java 客戶端訪問接口。咱們在 publisher 上面建立一個單獨的 Java 項目,而且添加如下依賴項(在 maven central 有):
compile 'com.google.apis:google-api-services-androidpublisher:
v2-rev20-1.21.0'
下一步是新建一個 AndroidPublisher
。首先,咱們經過如下信息來實例化 GoogleCredential
:一個客戶端鏈接,一個 JSON factory,一個與 private_key_id
對應的私有關鍵 ID,一個與 client_email
對應的帳戶 ID,ANDROIDPUBLISHER
範圍,以及與 private_key
對應的、包含私有關鍵信息的重要文件。是的,全部這些都須要。
而後,咱們用應用程序包建立一個 AndroidPublisher
例子。
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 是谷歌 API 的主要入口。它有一個 edits 方法,可讓咱們修改想從控制檯獲取的數據。
要開始一個新版本,你必須用 insert 請求來開始,而後保存它的 id,接下來每次調用都會使用該 id。
AndroidPublisher.Edits edits = publisher.edits(); AppEdit edit = edits.insert(PACKAGE, null).execute(); String id = edit.getId();
如今,咱們能夠開始修改控制檯數據了。舉個例子,若是你想修改排名:
Listings listings = edits.listings(); Listing listing = new Listing(). setFullDescription(description). setShortDescription(shortDescription). setTitle(title); listings.update(PACKAGE, id, "en_US", listing).execute();
You can also upload screenshots:
也能夠上傳截圖:
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();
筆者鼓勵你多多探索這個接口。它既強大,又不復雜。
最後一步,你必須提交本身的版本。實際上,谷歌會記錄你的每個更改請求,可是隻有在你提交版本以後,這些更改纔會被保存。筆者同時建議你在提交以前先驗證這些更改。
edits.validate(PACKAGE, id).execute();
edits.commit(PACKAGE, id).execute();
如你所見,你在代碼開頭找回的 id 能夠被當作事務 id。經過調用 insert,update/upload
你的更改以開始事務,validate
以及最終 commit
。很是簡單。
如今,安卓應用程序也能夠呼應 DevOps 活動,擁有強有力的持續交付了。在 Captain Train,咱們選擇編寫本身的 publisher 工具來確保本身控制每一個步驟和重要步驟的字節。一旦發佈任務成功完成,咱們就把它當作一個腳原本運行。不過也有 Jenkins 插件或 Gradle 插件能夠幫你完成這些工做。只是要注意瞭解幕後的運行狀況。畢竟你在處理生產。必須當心謹慎。
這樣的工具和流程讓你只需推送 master 分支便可在生產環境中發佈新版本。既簡單、快捷,又可靠、節約時間。
顯然,在一個應用程序中可行的方法不必定適用於全部的團隊、公司和應用程序。還要依靠你的團隊以及團隊與市場傳播團隊的關係。不過,在此筆者想要總結的是,持續交付應該成爲每一個開發團隊的目標,往這個目標邁進的每一步都是一種勝利。
OneAPM Mobile Insight以真實用戶體驗爲度量標準進行 Crash 分析,監控網絡請求及網絡錯誤,提高用戶留存。訪問 OneAPM 官方網站感覺更多應用性能優化體驗,想閱讀更多技術文章,請訪問 OneAPM 官方技術博客。
本文轉自 OneAPM 官方博客