Android apk的維護與升級

我們發佈了一個新的應用後,由於發佈的應用並不完美,可能會出現一些bug,而且爲了與時俱進,添加一些新的功能,就需要開發人員對其進行維護與升級。那麼,發佈後的apk被下載到用戶的手機上之後,開發人員該如何對其進行後續的操作呢?

爲了對舊應用進行維護與升級,首先我們要在用戶的手機中找到舊應用。那麼,我們該如何在Android系統中精確定位到我們的應用呢?

Android的應用程序在Android系統中具有唯一標識,即包名(package),可以在AndroidManifest文件中進行設置。但要注意,應用程序的源文件一定要在包名所指向的路徑中。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.XXX.XXX.XXX">

Java的包的命名規範中,包一般採用反寫域名命名規則,即com.xx.xxx.xxxx形式,且全部使用小寫字母。

一級包名爲com,二級包名爲xx(一般爲公司或個人域名),三級包名根據應用進行命名,四級包名爲功能模塊名。如:com.tencent.qq.activitys,這樣具備較高可讀性,一看就知道是騰訊公司QQ軟件中存放activity的包。
下面是一些常見的包的組織方式的命名。


com.example.app.activitys 用來組織Activity類
com.example.app.base 基礎共享的類,如多個Activity共享的
BaseActivity或整個應用共享的MyApplication類
com.example.app.adapter 項目中用到的適配器類
com.example.app.view 自定義的View,如常用的TitleBarView
com.example.app.util 工具類,如HttpUtil,ImageUtil,FileUtil
com.example.app.db 數據庫類,如DataBaseHelper,MessageDB
com.example.app.service 服務類,如GetMsgService
com.example.app.constant 常量類
com.example.app.domain/modle/entity 元素實體類,如對應註冊用戶信息的User類,
對應聊天信息的TextMessage類
com.example.app.broadcast 廣播服務類

在自己開發應用時,一定要保證包的名字的不同,這樣Android系統便不會混淆。否則,先安裝的app將被後安裝的app所覆蓋。

但是,Android系統的開發者無窮無數,每個開發者都無法保證自己開發的應用的包名不會和其它開發者開發的應用重複。於是,Android系統在包名識別之外,還添加了簽名

識別。

簽名之前首先要創建一個密鑰庫,設置密鑰庫的位置和密碼,之後填寫密鑰庫的信息,並在密鑰庫中設置密鑰。最後,使用密鑰就可以生成帶簽名的apk文件了。


在IntelliJ IDEA中,依次點擊Build->Generate Signed APK,按照提示進行操作即可。

添加了簽名之後的應用被安裝之後,再次安裝相同包名的應用之時,Android系統便會提出詢問,是否刪除之前安裝的應用,而不會簡單的覆蓋。只有當包名和簽名均相同時,Android系統纔會將舊的應用用新的應用覆蓋掉。


使用了簽名和包名,我們的應用程序在Android系統中便可以變得獨一無二了。



瞭解了簽名和包名之後,想要對我們的應用程序進行升級就簡單多了。我們只要重新發布一款包名和簽名均與舊的應用一致的新應用,通知用戶下載,便可以將舊應用覆蓋掉,實現應用的升級。

app升級操作分爲兩種:

  • App Store升級

在App Store中升級需要爲App Store上傳新版App,我們在新版本完成之後都會上傳到App Store中,不同的應用市場審覈的時間不同,一般除了第一次上傳時間較長之外,其餘的審覈都是挺快的,一般不會超過半天(不排除例外情況),在審覈完成之後就相當於完成了這個應用市場的發佈了,也就是發佈上線了。這時候如果用戶安裝了這個應用市場,那麼就能看到我們的App有新版本的升級提醒了。

  • 應用內升級

除了可以在應用市場升級,我們還可以在應用內升級,在應用內升級主要是通過調用服務器端接口獲取應用的升級信息,然後通過獲取的服務器升級應用信息與本地的App版本比對,若服務器下發的最新的App版本高於本地的版本號,則說明有新版本發佈,那麼我們就可以執行更新操作了,否則忽略掉即可。


Android應用程序的版本標識分爲版本名(versionname)與版本號(versioncode),在AndroidManifest文件中進行設置。注意,當使用gradle框架時,在build.gradle文件中,同樣可以設置app的版本名與版本號,當兩個文件的設置發生衝突時,將默認使用build.gradle文件中的設置。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          android:versionCode="2"
          android:versionName="1.1"
          package="com.XX.XXX.XXXX">


在應用程序中,可以通過PackageManager來獲得包的版本信息。
/**
     * 獲取版本號
     * @return 當前應用的版本號
     */
    public String getVersion() {
        try {
            PackageManager manager = this.getPackageManager();
            PackageInfo info = manager.getPackageInfo(this.getPackageName(), 0);;
            return info.versionName + info.versionCode;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


之後將版本名和版本號與服務器最新版本的版本名和版本號進行比較,確認是否需要更新即可。


我們開發的應用程序難免會出現bug,但在每次出現bug時,都選擇重新打包上線,自然不是一個好選擇,這會嚴重影響用戶的體驗。有沒有一種可以以補丁的形式發佈,無需重新下載安裝即可修復bug的方法?答案是肯定的。這就是Android的熱修復。下面將分析一下熱修復的原理,幾大開源框架,以及熱修復的使用。

下面的文字參考自 一片楓葉的專欄


熱修復的原理主要有以下兩種:


1.通過更改dex文件的加載順序實現熱修復,其核心原理就是通過更改含有bug的dex文件的加載順序。在dex的加載中,若以找到方法則不會繼續查找,所以如果能讓修復之後的方法在含有bug的方法之前加載就能達到修復bug的目的。此種方法在修復bug完成後,需要重啓app。


2.通過Native替換方法指針的方式實現熱修復。相比於第一種的在Java層實現,此種方法主要在Native層實現,且不需要對app進行重啓。針對此方法,目前主要有阿里開源的兩個熱修復框架:DexpostAndFix

最終我們App的熱修復方案選擇的是AndFix,原因有三:
(1)AndFix支持Android2.3-6.0,所以在機型上的是適配上是沒問題的;
(2)AndFix是由阿里開源的,並且持續維護中,目前不少公司已經使用其作爲自身App的熱修復方案;
(3)通過修改Dex加載順序的方式實現熱修復需要重新啓動App,並且相應的開源框架多多少少存在着問題,沒有持續的維護;

因此我們最終選擇了AndFix作爲我們的開源方案。具體的AndFix集成方式可參考github中AndFix的介紹

這裏簡單介紹一下具體的繼承流程
(1)在App的Application的onCreate方法中執行AndFix的初始化操作;
(2)判斷服務器端是否有可更新的熱修復差異包
(3)若無則直接退出,若有則下載並執行修復動作
(4)修復完成之後刪除下載的補丁差異包
(5)在判斷服務器端是否有可更新的補丁包的時候可添加灰度,如版本,渠道,用戶等,實現對補丁包定製化的修復

另外需要說明的是:若一個版本中存在着多個bug,則一般的都是讓後一個補丁包覆蓋前一個補丁包,並刪除前一個補丁包,簡單來說就是對於每一個版本至多有一個補丁包。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章