Android 實現自動更新及強制更新功能
引言
目的不言而喻,肯定是為了自己版本的迭代更新。想做到版本的完全控制手段還是比較多的。今天我要分享的這個方法是用蒲公英提供的版本查詢介面和版本下載介面來做的。有條件的同學也可以在自己的服務端開這兩個介面。
需求分析
我們要想實現這個自動更新的功能大致分三步:
- 查詢線上版本號,然後拿本地版本號與之對比。
- 若線上版本號比本地版本號大,則下載線上版本號
- 把下載好的版本號安裝,並替換當前舊版本
許可權
根據上面的需求我們可以知道,需要用到的許可權應該有網路許可權、本地檔案寫入許可權,本地檔案讀取許可權。使用網路許可權去獲取線上的版本號,然後下載儲存到本地,安裝的時候再去本地取來。
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
步驟
根據上面的需求,我們一步一步來實現這個功能。首先在APP的入口處去檢測版本號。
ProUtils.canUpdata(this);
在這裡我把檢測方法給封裝到了utils中,這樣用起來也方便。
1,檢測線上版本
public void check() {
//當所用app前版本號
int codeversin = getVersion();
getLineVersion(checkurl, codeversin);
}
這個方法裡面包含了兩步,第一步是去獲取本地版本號,第二步是去獲取線上版本號
獲取本地版本號:
public int getVersion() { PackageInfo pkg; int versionCode = 0; String versionName = ""; try { pkg = activity.getPackageManager().getPackageInfo(activity.getApplication().getPackageName(), 0); versionCode = pkg.versionCode; } catch (PackageManager.NameNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } return versionCode; }
獲取線上版本號:
OkHttpClient okHttpClient = new OkHttpClient(); RequestBody formBody = new FormBody.Builder() .add("_api_key", BuildConfig.PYAPIKEY) .add("appKey", BuildConfig.PYAPPID) .build(); Request request = new Request.Builder() .url(url) .post(formBody) .build(); Call call = okHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { } });
在上面有兩個KEY,這兩個可以都是從蒲公英上取來的。就像引言所說,若有條件可以自己搭建。
版本比較
在上面請求成功後,在response中就會獲取到我們的線上版本號。然後我們拿上一步中獲取到的線上版本號和本地版本號來做對比:
if (lineVersion > nowcodeversin) {
//去彈窗提示使用者
}
這個時候,如果比較的結果是線上版本比較大,則去下載線上版本
提示使用者
我們要給使用者提示的,當然你若想直接下載也可以,只不過為了使用者體驗而已,自己斟酌。
提醒使用者
AlertDialog dialog = new AlertDialog.Builder(activity).setTitle
("Tips").setMessage("Have new version,please update!")
.setNeutralButton("Cancel", new DialogInterface
.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).setNegativeButton("Update", new DialogInterface
.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
pyUtils.downUrl();
}
}).show();
dialog.setCanceledOnTouchOutside(false);//可選
dialog.setCancelable(false);//可選
在這裡我給了使用者兩種選擇,一種是立即更新,一種是稍後再說。點選稍後,那就會在下次再出發的時候再去提醒使用者。點選更新的話,會立刻開始下載應用的新版本。
如果你想強制使用者去更新的話,可以把稍後的選項去掉,順便把
dialog.setCanceledOnTouchOutside(false);//可選,點選dialog其它地方dismiss無效
dialog.setCancelable(false);//可選,點選返回鍵無效
這兩項給加上,使用者就不得不更新了。
下載
上面都做好了,那就下載吧,就是一個檔案下載的方法:
public void downUrl() {
DownloadUtil.get().download(downUrl,activity.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath(), new DownloadUtil.OnDownloadListener() {
@Override
public void onDownloadSuccess(File file) {
LogUtils.e("AutoUpdate","下載完成去安裝");
}
@Override
public void onDownloading(int progress) {
}
@Override
public void onDownloadFailed() {
LogUtils.e("AutoUpdate","下載失敗");
}
});
}
這個下載沒什麼好說的
安裝
下載好之後,我們直接使用系統的方法去安裝即可
////呼叫系統的安裝方法
private void installAPK(File savedFile) {
//呼叫系統的安裝方法
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri data;
// 判斷版本大於等於7.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
// "net.csdn.blog.ruancoder.fileprovider"即是在清單檔案中配置的authorities
data = FileProvider.getUriForFile(activity, "com.thinker.member.bull.android_bull_member.fileprovider", savedFile);
// 給目標應用一個臨時授權
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
LogUtils.e("AutoUpdate","7.0data="+data);
} else {
data = Uri.fromFile(savedFile);
LogUtils.e("AutoUpdate","111data="+data);
}
intent.setDataAndType(data, "application/vnd.android.package-archive");
activity.startActivity(intent);
activity.finish();
}
在這裡需要注意,有個7.0的方法。需要在你的專案清單檔案中配置如下
<!-- 解決apk安裝失敗的問題 -->
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.ligo.anomo.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
然後再資源res中新增xml/file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<paths>
<external-path path="" name="download"/>
</paths>
</resources>
基本就可以了。讀書百卷,不如手寫一遍。自己去試試吧。