下載更新apk,基本上每個app都需要的功能,來看看吧,肯定有你想要的,以前都是自己寫,近期想藉助第三方的一個庫來做,功能齊全,感覺不錯,記錄使用過程,雖然官方也有使用教程,不過畢竟粗略,網上也能搜到,不過基本都是複製的 首先下載庫,地址改成我們自己的,檢查地址就讓它了,這個根據自己的業務調整,也能 ...
下載更新apk,基本上每個app都需要的功能,來看看吧,肯定有你想要的,以前都是自己寫,近期想藉助第三方的一個庫來做,功能齊全,感覺不錯,記錄使用過程,雖然官方也有使用教程,不過畢竟粗略,網上也能搜到,不過基本都是複製的
首先下載庫,地址改成我們自己的,檢查地址就讓它了,這個根據自己的業務調整,也能自定義
接下來是參數介紹
參數大多數一看就懂,這裡介紹下md5效驗,此欄位為必填欄位,不過有的時候不想效驗,或者測試的時候想先調通了,然後在跟後臺溝通加上效驗,這樣就不能直接gradle配置引用了,得下載源碼,更改裡面的代碼了,不然就得按照文檔說明來
我想很多人都不願意一開始去搞什麼md5效驗,雖然它的demo是可以用的,不過還是得改成自己的才安心,但是改成自己的又會效驗失敗,你不傳又不行,所以沒辦法了,只能改源代碼
info.size欄位是下載大小,這是為了提示框展示作用,可以自己動態獲取
源代碼裡面很多回調,有點繞,不過代碼也就那麼點,找找也就找到了
此處是返回效驗結果,註釋掉代碼,然後return true就行了,命名預設是md5命名
然後還有後臺靜默下載,這裡也提供了靜默下載,然後在狀態欄里顯示進度
直接調用demo的方法就好了
立即下載回調download方法,下載是繼承asynctask下載
然後裡面的彈框比較簡單的alertdialog寫的,我覺得這樣簡單蠻好的,可是現實是殘酷的,很多都是需要自己定製彈框,調用介面獲取數據啊,加樣式啊,都是正常,那麼預設的肯定滿足不了你了,可是它是寫在庫裡面的,要改的話得自己另外寫,然後替換掉它寫的
我是自己寫了個幫助類,把它原來的註釋了
progress也換成了自己了
它原本是在start裡面的,需求如此,只能改
還有一個就是強制更新功能,有的需求強制更新,初始化彈出提示更新框,然後調用介面獲取是否強制更新,如果是就點擊後臺靜默下載,可以正常操作界面,如果否,就彈出下載框下載,而它原本的強制更新不是這樣的,還有靜默下載,是不彈框的,直接就後臺下載了,這裡也好改,把一個判斷註釋掉就好了,找到強制更新判斷的地方
註釋後發現ok了,其它都不用改,下麵的doPrompt方法就是彈框下載,doDownload就是不彈框下載,這裡只是一個判斷,而真正是否靜默下載還是它原來的參數來決定的,所以把這裡改了參數正常傳進去,一切ok
最後就是md5驗證了,把伺服器的md5欄位傳進去,然後把前面註釋的代碼解開,這個要先跟後臺協商好,預設的是 String.format("%1$032x", new Object[]{var5}) ,寬度為32,我這邊伺服器上的是08x,所以要改一下
這裡網上的方法是與運算之類的,親自測了一下,沒有問題
我這裡還是用它預設的解密方法,把寬度改一下就好了,至於format用法也簡單
下麵是列印的日誌信息,看到輸出結果估計也就明白這是怎麼回事了
Log.e("format","08d "+String.format("%1$08d", 120504));
Log.e("format","08x "+String.format("%1$08x", 120504));
Log.e("format","016d "+String.format("%1$016d", 120504));
Log.e("format","016x "+String.format("%1$016x", 120504));
E/format: 08d 00120504
E/format: 08x 0001d6b8
E/format: 016d 0000000000120504
E/format: 016x 000000000001d6b8
運行程式,發現通過
然後不知道到這裡你們發現沒有,就是它初始化的時候會傳入一個checkurl,這裡其實就是你的介面地址,然後它自帶寫了一個網路訪問,再把請求後的數據設置到其中,提供下載操作,看它的下載操作就知道了
1 @Override 2 public void check(ICheckAgent agent, String url) { 3 HttpURLConnection connection = null; 4 try { 5 connection = (HttpURLConnection) new URL(url).openConnection(); 6 connection.setRequestProperty("Accept", "application/json"); 7 8 if (mPostData == null) { 9 connection.setRequestMethod("GET"); 10 connection.connect(); 11 } else { 12 connection.setRequestMethod("POST"); 13 connection.setDoOutput(true); 14 connection.setInstanceFollowRedirects(false); 15 connection.setUseCaches(false); 16 connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 17 connection.setRequestProperty("Content-Length", Integer.toString(mPostData.length)); 18 connection.getOutputStream().write(mPostData); 19 } 20 21 if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { 22 agent.setInfo(UpdateUtil.readString(connection.getInputStream())); 23 } else { 24 agent.setError(new UpdateError(UpdateError.CHECK_HTTP_STATUS, "" + connection.getResponseCode())); 25 } 26 } catch (IOException e) { 27 e.printStackTrace(); 28 agent.setError(new UpdateError(UpdateError.CHECK_NETWORK_IO)); 29 } finally { 30 if (connection != null) { 31 connection.disconnect(); 32 } 33 } 34 }
這就是最外層的check方法,url就是你傳入的checkurl,如果你不傳不用它的,就會出現空指針錯誤,然後在調用 agent.setInfo 設置值到 UpdateAgent 這個類裡面,這個類是具體的下載類了,為什麼講這個
我們自己肯定會有檢查更新的介面,肯定會傳入參數,回調肯定會做邏輯處理,在它裡面這樣實在不方便,它傳入的checkurl添加參數什麼的也得改,不喜歡,所以想把這個檢查更新的功能去掉,只要下載功能,檢查更新我們自己處理
改起來就有點大了,不像前面的那些,小改動,不過看懂了也好改,從最外層開始進入,你需要一個打開方式,外面這多設置調用方法,其實說到底就是傳入回調和數據進入,然後提供檢查更新和下載操作
最外層設置的數據在 UpdateManager 這個類裡面,點進入看就是了,最重要的就是check方法了
1 public void check() { 2 long now = System.currentTimeMillis(); 3 if (now - sLastTime < 3000) { 4 return; 5 } 6 sLastTime = now; 7 8 if (TextUtils.isEmpty(mUrl)) { 9 mUrl = UpdateUtil.toCheckUrl(mContext, sUrl, sChannel); 10 } 11 12 UpdateAgent agent = new UpdateAgent(mContext, mUrl, mIsManual, mIsWifiOnly, mNotifyId,isSilent); 13 if (mOnNotificationDownloadListener != null) { 14 agent.setOnNotificationDownloadListener(mOnNotificationDownloadListener); 15 } 16 if (mOnDownloadListener != null) { 17 agent.setOnDownloadListener(mOnDownloadListener); 18 } 19 if (mOnFailureListener != null) { 20 agent.setOnFailureListener(mOnFailureListener); 21 } 22 if (mChecker != null) { 23 agent.setChecker(mChecker); 24 } else { 25 agent.setChecker(new UpdateChecker(mPostData)); 26 } 27 if (mParser != null) { 28 agent.setParser(mParser); 29 } 30 if (mDownloader != null) { 31 agent.setDownloader(mDownloader); 32 } 33 if (mPrompter != null) { 34 agent.setPrompter(mPrompter); 35 } 36 if (endListener != null){ 37 UpdateAgent.endListener = endListener; 38 } 39 agent.check(); 40 } 41 }
在這個方法裡面可以看到,基本數據都轉移到了 UpdateAgent 這個類裡面去了,但是調試你會發現,你不傳入檢查地址url 通過不了,因為有這麼一段
這也好辦,把裡面的空指針處理下就好了,價格空指針判斷讓它繼續往下走,下麵就到了關鍵的步驟了
進入了這裡了,進入這裡面做什麼,在進去看
1 void doCheck() { 2 new AsyncTask<String, Void, Void>() { 3 @Override 4 protected Void doInBackground(String... params) { 5 if (mChecker == null) { 6 mChecker = new UpdateChecker(); 7 } 8 mChecker.check(UpdateAgent.this, mUrl); 9 return null; 10 } 11 12 @Override 13 protected void onPostExecute(Void aVoid) { 14 doCheckFinish(); 15 } 16 }.execute(); 17 }
一步步進入,發現這裡就是http訪問checkurl了,然後回調返回數據給到 UpdateAgent這個類裡面去
然後發現回到了 UpdateAgent這裡,這裡做更新下載操作,調用的也是外層傳入的數據UpdateInfo,那麼就好辦了,外層的檢查更新介面不要,http訪問去掉,然後因為我們在最外層已經有了 UpdateInfo 這個類了,所以可以直接傳進去,然後就可以跳過檢查這個步驟了
添加一個實體類,這也是它自帶的實體類,生成設置獲取方法
然後在最外層去掉不必要的方法,把實體類提出來直接設置進去
1 UpdateManager.create(context) 2 .setManual(true)// 在設置界面點擊檢查更新 3 .setNotifyId(998)//notify唯一標識 4 .setUserInfo(info) 5 .check();
精簡很多了,接下來就是裡面修改了,前面就說了,check方法裡面是直接傳值的,那我們就不需要回調了,直接傳入進去
1 public void check() { 2 long now = System.currentTimeMillis(); 3 if (now - sLastTime < 3000) { 4 return; 5 } 6 sLastTime = now; 7 8 if (TextUtils.isEmpty(mUrl)) { 9 mUrl = UpdateUtil.toCheckUrl(mContext, sUrl, sChannel); 10 } 11 12 UpdateAgent agent = new UpdateAgent(mContext, mUrl, mIsManual, mIsWifiOnly, mNotifyId); 13 if (mOnNotificationDownloadListener != null) { 14 agent.setOnNotificationDownloadListener(mOnNotificationDownloadListener); 15 } 16 if (mOnDownloadListener != null) { 17 agent.setOnDownloadListener(mOnDownloadListener); 18 } 19 if (mOnFailureListener != null) { 20 agent.setOnFailureListener(mOnFailureListener); 21 } 22 if (mChecker != null) { 23 agent.setChecker(mChecker); 24 } else { 25 agent.setChecker(new UpdateChecker(mPostData)); 26 } 27 if (mParser != null) { 28 agent.setParser(mParser); 29 } 30 if (mDownloader != null) { 31 agent.setDownloader(mDownloader); 32 } 33 if (mPrompter != null) { 34 agent.setPrompter(mPrompter); 35 } 36 if (endListener != null){ 37 UpdateAgent.endListener = endListener; 38 } 39 if (mInfo != null) 40 agent.setInfo(mInfo); 41 agent.check(); 42 } 43 }
當然,這裡上面判斷checkurl地址的還得加個空指針判斷,不然走不下去
然後就是修改關鍵地方了,跳過檢查步驟,直接下載了,因為我們數據都有了,不需要去用它的網路請求了
1 void doCheck() { 2 if (mUrl == null || mUrl.isEmpty()) { 3 // setInfo(); 4 doCheckFinish();//直接下載,不檢查 5 return; 6 } 7 new AsyncTask<String, Void, Void>() { 8 @Override 9 protected Void doInBackground(String... params) { 10 if (mChecker == null) { 11 mChecker = new UpdateChecker(); 12 } 13 mChecker.check(UpdateAgent.this, mUrl); 14 return null; 15 } 16 17 @Override 18 protected void onPostExecute(Void aVoid) { 19 doCheckFinish(); 20 } 21 }.execute(); 22 }
下麵就是它啟動的網路訪問請求,所以我們直接在最上面給它截斷了,然後直接調用下載方法,因為我們在上面已經傳入了 UpdateInfo 實體進入了 UpdateAgent 類裡面, doCheckFinish 方法就在 UpdateAgent裡面,所以什麼都不用改,它就會自動根據參數需求更新下載了
而且這還解決了一個問題,就是你用它自帶的檢查更新會導致網路慢的時候過好久才彈框出來,好像卡住了一樣,而直接跳過這個步驟就沒有這個問題了,直接開始下載,不然只有在它原基礎上加個載入彈框什麼的
到這裡就要結束了,(☄⊙ω⊙)☄