DevOps on Android: 加速 App 從代碼到上線
DevOps 是一個眾所周知的開發方法,其主要目的是自動化軟件交付。事實上,DevOps 的目標是不斷的測試,代碼質量,功能開發,更容易維護版本。因此,DevOps 的一個最終目標是為開發者進行快速,可信賴和自動化發布提供指導,理想化狀態是在這個過程中不牽涉任何人工勞動。這就是所謂的持續交付。我寫這篇文章來證明,我們現在能在 Android 平臺上達成這樣的目標,同時和大家分享一下我的想法和聽取大家的反饋。
持續集成為出發點
想要達到持續交付,持續集成必須是強制的。在安卓平臺上的持續集成已經有一段時間了,為了更清楚的去了解,我們先說一下它的優勢。
安卓平臺必須采用持續集成方法,是的我說過。確實,持續集成有一些在構建 Android App過程中無法發忽略的好處。在我看來,它的優勢在于:
-
自動化構建:不再只是在我的機器,而是在所有的環境。
-
早失敗:一旦代碼提交之后就馬上構建,這樣就保證錯誤能被及早的發現。
-
構建測試:保證每一個測試用例都能正常運行。
-
不斷打包:防止打包過程中的人為錯誤。
-
快速發布:既然我們對于每一次構建都有信心,那么發布就變得簡單了
-
增加信心:最后,我們相信我們的代碼,我們的過程,我們減少不良的驚喜。
一個典型的持續集成過程
首先,我們需要一個集成服務器像Jenkins 或 Travis 。下面的工作是我的標準配置:
-
啟動一個監視代碼推送到我們的代碼倉庫(Jenkins or Travis)完成事件的任務。該任務監視代碼的 dev 分支去自動的編譯、單元測試、打包或者 debug APK .
-
當上面的任務完成之后,另外一個任務就要被啟動了。這個任務主要用來跑集成測試(通過 Espresso 或者 Robotium)。在這個過程中,通過模擬用戶場景和檢查渲染的圖形內容的方式來保證最終的用戶體驗。
-
另外一個任務就是一個每天晚上都會運行的執行代碼質量掃描(例如 Sonarqube )的任務。
-
最后還有一個任務用來檢測一旦代碼倉庫的 master/release 分支有更新就去構建發布的APK包。
看看吧,正如你看見的,這個過程很簡單并且保證能達成我開始所說的優勢。
測試是關鍵
我曾經寫過一篇關于測試的文章( testing on Android )。測試是如此的重要因為它是能夠保證App按照我們所設定的那樣去工作的唯一工具。寫單元測試有很多工具和方法,請明智的去選擇。 此外,確認一下你要在你的應用程序集成的庫。事實上,當你使用的庫有一個良好的單元測試覆蓋率的時候,就更容易測試您的App。一些被認為恰當測試的并且用測試驅動他們的開發的類庫(例如 IMO, OkHttp and Retrofit )。很可能,你將能夠在使用它的時候來測試它。 最后,像 Dagger 庫可以幫助你提高可測試性。事實上,它會迫使你遵循單一職責原則和正確分開你的代碼,從而更容易測試。 一旦你有一個強大的持續集成,讓我們來看看如何提高水平。
持續交付: Level++
舉例來說,在 Captain Train。我們發布每6周一次,我們都非常小心了。 目前每次發布都要做: * 我們有一個測試階段 * 我們支持 4 個區域設置。 * 我們支持 3 種類型的設備(phone, 7 and 9 inches tablets)。 * 我們經常檢查我們的的 Play Store。 * 我們寫發行說明。 * 我們使用部署功能。 * 我們上傳了 72 截圖(6 screenshots * 4 locales * 3 types)
整個過程非常消耗時間,最近我們想,是時候去把這個過程給自動化了。即使我們的最終目標是減少發布時間。這種感覺非常好,去防止人為的犯錯誤以及經常的發布發布。我們能掌握整個過程,這樣讓我們更加有責任心。
但是,坦白的說,安卓開發者不能控制所有的事情,只有 Google 能做到。 例如,它暴露了一個 HTTP API,使開發人員能夠使用 Play 商店控制臺輕松互動。他們也提供了很多語言實現的語言包,例如Java ,Ruby 等。
在這篇文章,我講專注于 Java 語言,因為對于安卓開發者來說,這是最容易的。
編寫你自己的 App 發布工具
讓我們看看如何編寫自己的 App 發布工具來把 APP 發布到 Play Store 。大概有兩個步驟:首先,我們將配置我們的控制臺,使我們的客戶端能夠進行操作,進而我們就會發現其中的 API。最困難的事情經常用谷歌去配置。文檔()可以在這里找到。請注意,這是一個有點過時。 配置 首先,如果沒有做,你必須在谷歌控制臺創建一個新的項目。然后,我們需要啟用 Google Play Android Developer API。
一旦完成,我們必須創建服務帳戶關鍵的憑證:
最后填寫表格,并下載一個 json 格式的憑證。你需要保存三個值:private key id, private key 、 client email. 把 private key 的值保存在 secret.pem 中. 我們正在與開發者控制臺交互......現在讓我們去到第二個控制臺! \ O / 連接到您的控制臺。你必須進入 Settings > API access: 然后,你必須簡單地鏈接您的項目。最后,在 Service accounts,授予權限給你下的 JSON 文件中的的客戶端郵件的client email。
到現在為止,一切都準備好了。 API發現 現在,讓我們深入到 Java 客戶端 API。我們創建了一個單獨的 Java 項目為我們的發布工具,我們添加下面的依賴(Maven的中央倉庫有):
compile 'com.google.apis:google-api-services-androidpublisher: v2-rev20-1.21.0'
下一個步驟是創建一個 AndroidPublisher。首先我們通過提供 transport client, JSON factory,和 private key id 對應的 private key ID,和 client_email 對應的賬戶 ID 來實例化一個 GoogleCredential。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();</pre>AndroidPublisher 對象是Google控制臺的主入口,他有一個 Edit 方法,允許我們編輯控制臺的數據。要開始一個新的版本,你必須以發起插入請求,并存儲它的返回值,你會在每一個后續調用中使用這個返回的 ID。
AndroidPublisher.Edits edits = publisher.edits();AppEdit edit = edits.insert(PACKAGE, null).execute();
String id = edit.getId(); </pre>現在我們將改變我們的控制臺數據,舉例來說改變 listings:
Listings listings = edits.listings();Listing listing = new Listing().
setFullDescription(description). setShortDescription(shortDescription). setTitle(title);listings.update(PACKAGE, id, "en_US", listing).execute(); </pre>
你也可以上傳截圖
Images images = edits.images();FileContent content = new FileContent(PNG_MIME_TYPE, file);
images.upload(PACKAGE, id, "en_US", "phone5", content).execute(); </pre>
最后一個例子,讓我們上傳一個 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(); </pre>我推薦大家使用 API,因為它很完美并且很強大。 最后一步,你必須提交你的版本。事實上,到目前為止,谷歌記錄您所請求的每一個變化,但是它只會保存您提交的變化。我也建議你嘗試提交之前驗證您的更改。
edits.validate(PACKAGE, id).execute(); edits.commit(PACKAGE, id).execute();正如你看見的那樣,開始所獲取的 ID,就像是一個事務ID 一樣。你開始事務之后,通過 insert, update/upload 來處理變化,并且通過 validate 方法驗證 ,通過commit 方法提交。一切都如此簡單。
討論
現在我們可以遵循 devOps 原則,甚至對于安卓開發來說有了比較強大的持續交付能力。在 Captain Train 我們選擇去寫我們自己的發布工具以此來控制重要的每一個步驟。一旦 release 任務執行成功,我們就執行發布工具來發布 App。當然了Jenkin 和 Gradle 也有一些類似的工具可用。
諸如此類的工具能讓你簡單的通過向 master 或者 release 分支推送代碼的方式來發布你的App。這個過程簡單、可信賴、節省時間! 很明顯,這個過程不一定適用于每個團隊/公司/應用程序~ ,這取決于你所在團隊的具體情況。但是,我要強調的是持續交付應該是每一個團隊/公司的目標。一旦達成,它將驅動您走向成功。
原文: http://jeremie-martinez.com/2016/01/14/devops-on-android/
OneAPM Mobile Insight ,監控網絡請求及網絡錯誤,提升用戶留存。訪問OneAPM 官方網站感受更多應用性能優化體驗,想閱讀更多技術文章,請訪問OneAPM 官方技術博客。