1. 程式人生 > >Android開發中應用版本更新功能

Android開發中應用版本更新功能

前言

本文將講解app的升級與更新。一般而言使用者使用App的時候升級提醒有兩種方式獲得:

  • 一種是通過應用市場 獲取
  • 一種是開啟應用之後提醒使用者更新升級

而更新操作一般是在使用者點選了升級按鈕之後開始執行的,這裡的升級操作也分為兩種形式:

  • 一般升級
  • 強制升級

app升級操作:

  • 應用市場的app升級

在App Store中升級需要為App Store上傳新版App,我們在新版本完成之後都會上傳到App Store中,在稽核完成之後就相當於完成了這個應用市場的釋出了,也就是釋出上線了。這時候如果使用者安裝了這個應用市場,那麼就能看到我們的App有新版本的升級提醒了。

  • 應用內升級

除了可以在應用市場升級,我們還可以在應用內升級,在應用內升級主要是通過呼叫伺服器端介面獲取應用的升級資訊,然後通過獲取的伺服器升級應用資訊與本地的App版本比對,若伺服器下發的最新的App版本高於本地的版本號,則說明有新版本釋出,那麼我們就可以執行更新操作了,否則忽略掉即可。

顯然應用市場提醒的升級不是我們的重點,本篇主要是對於app升級的場景來進行不同角度的實現,便於以後開發過程中直接拿去用就ok了。

伺服器端:

  • 服務端提供一個介面,或者網址,這裡提供一個網址如下:
http://192.168.191.1:8081/update
  • 1
  • 1

一般作為一個

安卓程式設計師要測試還得寫一個服務端(醉了),這裡我就使用nodejs來搞一個本地的伺服器來測試下app的版本更新檢驗。

  • 根據請求的結果,我這裡就寫一個簡單的json
{"data":{
  "appname": "hoolay.apk",
  "serverVersion": "1.0.2",
  "serverFlag": "1",
  "lastForce" : "1",
  "updateurl": "http://releases.b0.upaiyun.com/hoolay.apk",
  "upgradeinfo": "V1.0.2版本更新,你想不想要試一下哈!!!"
},
  "error_code"
:"200","error_msg" :"蛋疼的認識"}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

然後我電腦上是裝了webstrom的,沒有裝也沒有關係但是必須有nodejs,現在都自帶了express,表示並沒有學過,所以簡單的寫個express_demo.js:

var express = require('express');
var app = express();
var fs = require("fs");
//此處設定為get請求,app裡面直接寫 (本機ip:8081/update)
app.get('/update', function (req, res) {//http://127.0.0.1:8081/update
    fs.readFile( __dirname + "/" + "version.json", 'utf8', function (err, data) {//讀取相同目錄下的version.json檔案
        console.log( data );//列印json資料
        res.end( data );//把json資料response回去
    });
})
var server = app.listen(8081, function () {//埠我這裡寫的是8081
    var host = server.address().address
    var port = server.address().port
    console.log("應用例項,訪問地址為 http://%s:%s", host, port)

})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

有webstrom的直接選中檔案run就ok了,沒有直接 node express_demo.js,可以直接瀏覽器開啟:http://127.0.0.1:8081/update

  • 效果如下:

這裡寫圖片描述

上圖為開啟瀏覽器後的顯示結果。

這裡寫圖片描述

上圖為webstrom的終端顯示結果。

客戶端需要實現:

我們知道不同的需求有不同的操作方法和介面顯示:

  1. 從是否為app內部下載還是通知欄更新:

    • app內下載更新

    這時我們必須等下載安裝完全後才能進行操作,效果是這樣的:

    這裡寫圖片描述

    • 通知欄下載更新

    這種情況是不在應用內更新,放在通知欄並不會影響當前app的使用,效果是這樣的:

  2. app更新分3種:強制更新,推薦更新,無需更新

    • 強制更新

      這裡寫圖片描述

    • 推薦更新

      這裡寫圖片描述

    • 無需更新

      這裡寫圖片描述

具體思路:

  1. 實現bean用於對接後端介面實現app的更新(不寫網路請求模擬本地資料也需要這個模型)
  2. 使用retrofit來請求版本更新介面
  3. 下載apk我們分別使用DownloadManager和普通的httpurlconnection
  4. 通過BroadcastReceiver來監聽是否下載完成

準備bean

首先我們要去解析服務端給的json,那麼我們就要來建立一個bean類了,這裡是嚴格根據json檔案的格式來的:

package com.losileeya.appupdate.bean;
/**
 * User: Losileeya ([email protected])
 * Date: 2016-09-27
 * Time: 11:20
 * 類描述:版本更新的實體與你伺服器的欄位相匹配
 * @version :
 */
public class UpdateAppInfo  {
    public UpdateInfo data; // 資訊
    public Integer error_code; // 錯誤程式碼
    public String error_msg; // 錯誤資訊
    public static class UpdateInfo{
        // app名字
        public String appname;
        //伺服器版本
        public String serverVersion;
        //伺服器標誌
        public String serverFlag;
        //強制升級
        public String lastForce;
        //app最新版本地址
        public String updateurl;
        //升級資訊
        public String upgradeinfo;
        get...
        set...
    }
        get...
        set...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

網路介面的實現

這裡使用retrofit和rxjava來練筆

先加入 依賴

  compile 'io.reactivex:rxandroid:1.1.0' // RxAndroid
  compile 'io.reactivex:rxjava:1.1.0' // 推薦同時載入RxJava

  compile 'com.squareup.retrofit:retrofit:2.0.0-beta2' // Retrofit網路處理
  compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2' // Retrofit的rx解析庫
  compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2' // Retrofit的gson庫
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

接下來網路介面的定製:

public interface ApiService {
    //實際開發過程可能的介面方式
     @GET("update")
    Observable<UpdateAppInfo> getUpdateInfo(@Query("appname") String   appname, @Query("serverVersion") String appVersion);
    //以下方便版本更新介面測試
    @GET("update")
    Observable<UpdateAppInfo> getUpdateInfo();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

通過工廠模式來建立ApiService :

public class ServiceFactory {
    private static final String BASEURL="http://192.168.191.1:8081/";
    public static <T> T createServiceFrom(final Class<T> serviceClass) {
        Retrofit adapter = new Retrofit.Builder()
                .baseUrl(BASEURL)
             .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 新增Rx介面卡
                .addConverterFactory(GsonConverterFactory.create()) // 新增Gson轉換器
                .build();
        return adapter.create(serviceClass);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

版本檢測介面的使用:

 /**
     * 檢查更新
     */
    @SuppressWarnings("unused")
    public static void checkUpdate(String appCode, String curVersion,final CheckCallBack updateCallback) {
     ApiService apiService=   ServiceFactory.createServiceFrom(ApiService.class);
        apiService.getUpdateInfo()//測試使用
                //   .apiService.getUpdateInfo(appCode, curVersion)//開發過程中可能使用的
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<UpdateAppInfo>() {
                    @Override
                    public void onCompleted() {
                    }
                    @Override
                    public void onError(Throwable e) {
                    }
                    @Override
                    public void onNext(UpdateAppInfo updateAppInfo) {
                        if (updateAppInfo.error_code == 0 || updateAppInfo.data == null ||
                                updateAppInfo.data.updateurl == null) {
                            updateCallback.onError(); // 失敗
                        } else {
                            updateCallback.onSuccess(updateAppInfo);
                        }
                    }
                });
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

附上結果回撥監聽:

  public interface CheckCallBack{//檢測成功或者失敗的相關介面
        void onSuccess(UpdateAppInfo updateInfo);
        void onError();
    }
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

具體使用介面的處理:

 //網路檢查版本是否需要更新
        CheckUpdateUtils.checkUpdate("apk", "1.0.0", new CheckUpdateUtils.CheckCallBack() {
            @Override
            public void onSuccess(UpdateAppInfo updateInfo) {
               String isForce=updateInfo.data.getLastForce();//是否需要強制更新
               String downUrl= updateInfo.data.getUpdateurl();//apk下載地址
               String updateinfo = updateInfo.data.getUpgradeinfo();//apk更新詳情
               String appName = updateInfo.data.getAppname();
                if(isForce.equals("1")&& !TextUtils.isEmpty(updateinfo)){//強制更新
                    forceUpdate(MainActivity.this,appName,downUrl,updateinfo);
                }else{//非強制更新
                    //正常升級
    normalUpdate(MainActivity.this,appName,downUrl,updateinfo);
                }
            }
            @Override
            public void onError() {
                noneUpdate(MainActivity.this);
            }
        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

實在不想寫網路也好,直接使用假想資料做相關操作如下:

  UpdateAppInfo.UpdateInfo  info =new UpdateAppInfo.UpdateInfo();
             info.setLastForce("1");
        info.setAppname("我日你");
        info.setUpgradeinfo("whejjefjhrherkjreghgrjrgjjhrh");
       info.setUpdateurl("http://releases.b0.upaiyun.com/hoolay.apk");
        if(info.getLastForce().equals("1")){//強制更新      forceUpdate(MainActivity.this,info.getAppname(),info.getUpdateurl(),info.getUpgradeinfo());
                }else{//非強制更新
                    //正常升級   normalUpdate(MainActivity.this,info.getAppname(),info.getUpdateurl(),info.getUpgradeinfo());
                }
  • 1
  • 2
  • 3
  • 4