Android 版本更新(適配7.0 xml配置)
阿新 • • 發佈:2018-12-21
版本更新一般分兩種情況:
- 需要更新時跳轉到應用市場或者跳轉到瀏覽器處理
- 另一種情況則是在App內進行更新
第一種沒什麼好說的,本文主要是實現應用內進行更新
App內部更新分以下幾個步驟:
- 檢測App版本
- 下載Apk
- 安裝已下載完成的Apk
下面貼上例項:
1. 檢測App版本
/** * 登入時查詢是否有新版本應用 */ public void queryVersion() { if (!Const.IS_CHECK_UPDATE) return; // 判斷是否進行請求更新 (場景:進入App自動檢測更新) HttpUtil.post(mContext, Const.URL_UPDATE, new TextResponseHandler() { @Override public void onSuccess(String result) { // 解析伺服器返回的版本資訊 JSONObject jsonObject = JSON.parseObject(result); if (Const.JSON_SUCCESS.equals(jsonObject.getString("success"))) { String strResult = jsonObject.getString("isupdate"); if (TextUtils.isEmpty(strResult)) return; UpdateVersion update = JSON.parseObject(strResult, UpdateVersion.class); String edition = update.getEdition(); // 伺服器返回版本資訊 String versionName = AppUtil.getVersionName(mContext); // 當前應用版本號 // 比較兩者 不一致提示更新 if (!versionName.equals(edition)) { // 顯示更新提示 showNoticeDialog(update, versionName); } } } @Override public void onFailure(String message) // 視業務而定 { ... } }); }
2.有新版本時 提示更新
/** * 顯示軟體更新對話方塊 * * @param update 更新介紹 * @param versionName 當前版本名 */ private void showNoticeDialog(final UpdateVersion update, String versionName) { // 構造對話方塊 MaterialDialog.Builder builder = new MaterialDialog.Builder(mContext); builder.title("更新提示"); if ("1".equals(update.getCode())) // 強制更新 builder.content("您當前使用版本會對您的使用帶來不便,請您更新!"); else builder.content("當前版本:" + versionName + "\r\n新版本:" + update.getEdition()); // 非重要更新 builder.positiveText("確定"); builder.negativeText("取消"); //點選事件新增 方式1 builder.onAny(new MaterialDialog.SingleButtonCallback() { @Override public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { if (which == DialogAction.POSITIVE) { dialog.dismiss(); showDownloadProgress(update); // 顯示更新進度 同時進行更新 } else if (which == DialogAction.NEGATIVE) { if ("2".equals(update.getCode()) || "3".equals(update.getCode())) { dialog.dismiss(); }else // 強制更新 如果不進行更新則無法使用當前應用 { dialog.dismiss(); mContext.finish(); System.exit(0); } } } }); MaterialDialog materialDialog = builder.build(); materialDialog.setCancelable(false); materialDialog.show(); }
3.顯示下載進度
/** * 顯示軟體下載提示框 * * @param update 後臺返回更新的資訊 */ private void showDownloadProgress(UpdateVersion update) { String url = update.getUrl(); apkName = url.substring(url.lastIndexOf("/") + 1, url.length()); String apkUrl = Const.URL_HOSTS + url; // 構造軟體下載對話方塊 if (materialDialog == null) { materialDialog = new MaterialDialog.Builder(mContext) .title("版本升級") .content("正在下載安裝包,請稍候") .progress(false, 100, false) .cancelable(false) .show(); } downloadThread(apkUrl); // 下載Apk }
4.下載Apk
/**
* 使用DownloadManager進行下載
*/
private void downloadThread(String apkUrl)
{
downloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(apkUrl));
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, apkName);
//設定顯示在檔案下載Notification(通知欄)中顯示的文字。6.0的手機Description不顯示
request.setTitle(mContext.getString(R.string.app_name));
request.setDescription("新版本給您帶來更優質的體驗!");
request.setMimeType("application/vnd.android.package-archive");
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
request.allowScanningByMediaScanner();
request.setVisibleInDownloadsUi(true);
lastDownloadId = downloadManager.enqueue(request);
downloadObserver = new DownloadChangeObserver(null);
mContext.getContentResolver().registerContentObserver(CONTENT_URI, true, downloadObserver);
}
5.監聽下載進度
class DownloadChangeObserver extends ContentObserver {
DownloadChangeObserver(Handler handler)
{
super(handler);
}
@Override
public void onChange(boolean selfChange)
{
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(lastDownloadId);
DownloadManager dManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
Cursor cursor = null;
try
{
cursor = dManager.query(query);
if (cursor != null && cursor.moveToFirst())
{
final int totalColumn = cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
final int currentColumn = cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
int totalSize = cursor.getInt(totalColumn);
int currentSize = cursor.getInt(currentColumn);
float percent = (float) currentSize / (float) totalSize;
int progress = Math.round(percent * 100);
materialDialog.setProgress(progress);
if (progress == 100)
{
materialDialog.dismiss();
installAPK();
}
}
} finally
{
// 一定不要忘記關閉遊標!!!
if (cursor != null)
{
cursor.close();
}
}
}
}
6.安裝新版Apk
private void installAPK() {
File apkFile =new File
(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), apkName);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
Uri apkUri = FileProvider.getUriForFile(mContext, "com.你的自定義路徑.update.fileprovider", apkFile);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
} else
{
intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
}
mContext.startActivity(intent);
}
7.釋放資源
/**
* 釋放當前資源
*/
public void onDestroy()
{
if (Const.IS_CHECK_UPDATE && downloadManager != null)
{
downloadManager = null;
mContext.getContentResolver().unregisterContentObserver(downloadObserver);
}
}
結束了?No No No ,由於Android系統的不斷完善,尤其是許可權方面,所以在7.0以上的系統需要在manifest中註冊provider
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.你的路徑.update.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
<!-- file_paths -->
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<paths>
<external-path
name="download"
path=""/>
</paths>
</resources>
ok,至此自動App更新功能完成
功能全部程式碼:
public class UpdateManager {
private DownloadChangeObserver downloadObserver;
private long lastDownloadId = 0;
//"content://downloads/my_downloads"必須這樣寫不可更改
private final Uri CONTENT_URI = Uri.parse("content://downloads/my_downloads");
private AlertDialog materialDialog;
private Activity mActivity;
private String apkName;
private DownloadManager downloadManager;
public UpdateManager(Activity activity)
{
this.mActivity = activity;
}
/**
* 登入時查詢是否有新版本應用
*/
public void queryVersion() {
if (!Constants.IS_CHECK_UPDATE) return;
HttpUtil.get(mActivity, Constants.URL_UPDATE, new TextResponseHandler() {
@Override
public void onSuccess(String result)
{
JSONObject jsonObject = JSON.parseObject(result);
if (Constants.JSON_SUCCESS.equals(jsonObject.getString("success")))
{
String strResult = jsonObject.getString("isupdate");
if (TextUtils.isEmpty(strResult)) return;
UpdateVersion update = JSON.parseObject(strResult, UpdateVersion.class);
String edition = update.getEdition();
String versionName = AppUtil.getVersionName(mContext);
String code = update.getCode();
if (!versionName.equals(edition))
{
showNoticeDialog(update, versionName);
}
}
}
@Override
public void onFailure(String message)
{
...
}
});
}
/**
* 顯示軟體更新對話方塊
*
* @param update 更新介紹
* @param versionName 當前版本名
*/
private void showNoticeDialog(final UpdateVersion update, String versionName)
{
// 構造對話方塊
MaterialDialog.Builder builder = new MaterialDialog.Builder(mContext);
builder.title("系統提示");
if ("1".equals(update.getCode())) // 強制更新
builder.content("您當前使用版本會對您的使用帶來不便,請您更新!");
else // 正常更新
builder.content("當前版本:" + versionName + "\r\n新版本:" + update.getEdition());
builder.positiveText("確定");
builder.negativeText("取消");
builder.onAny(new MaterialDialog.SingleButtonCallback()
{
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which)
{
if (which == DialogAction.POSITIVE)
{
dialog.dismiss();
showDownloadProgress(update);
} else if (which == DialogAction.NEGATIVE)
{
if ("2".equals(update.getCode()) || "3".equals(update.getCode()))
{
dialog.dismiss();
}else // 強制更新
{
dialog.dismiss();
mContext.finish();
System.exit(0);
}
}
}
});
MaterialDialog materialDialog = builder.build();
materialDialog.setCancelable(false);
materialDialog.show();
}
/**
* 顯示軟體下載對話方塊
*
* @param update 返回更新資訊
*/
private void showDownloadProgress(UpdateVersion update)
{
String url = update.getUrl();
apkName = url.substring(url.lastIndexOf("/") + 1, url.length());
String apkUrl = Constants.URL_HOSTS + url;
// 構造軟體下載對話方塊
if (materialDialog == null)
{
materialDialog = new MaterialDialog.Builder(mActivity)
.title("版本升級")
.content("正在下載安裝包,請稍候")
.progress(false, 100, false)
.cancelable(false)
.show();
}
// 螢幕常亮
mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
downloadThread(apkUrl); // 下載
}
private void downloadThread(String apkUrl)
{
String directoryDownloads = Environment.DIRECTORY_DOWNLOADS;
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
// ToolUtil.deleteFile(path + "/" + apkName); // 刪除下載的安裝包
downloadManager = (DownloadManager) mActivity.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(apkUrl));
request.setDestinationInExternalPublicDir(directoryDownloads, apkName);
//設定顯示在檔案下載Notification(通知欄)中顯示的文字。6.0的手機Description不顯示
request.setTitle(mActivity.getString(R.string.app_name));
request.setDescription("新版本給您帶來更優質的體驗!");
request.setMimeType("application/vnd.android.package-archive");
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
request.allowScanningByMediaScanner();
request.setVisibleInDownloadsUi(true);
lastDownloadId = downloadManager.enqueue(request);
downloadObserver = new DownloadChangeObserver(null);
mActivity.getContentResolver().registerContentObserver(CONTENT_URI, true, downloadObserver);
}
//用於顯示下載進度
class DownloadChangeObserver extends ContentObserver {
DownloadChangeObserver(Handler handler)
{
super(handler);
}
@Override
public void onChange(boolean selfChange)
{
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(lastDownloadId);
DownloadManager dManager = (DownloadManager) mActivity.getSystemService(Context.DOWNLOAD_SERVICE);
Cursor cursor = null;
try
{
assert dManager != null;
cursor = dManager.query(query);
if (cursor != null && cursor.moveToFirst())
{
//下載的檔案到本地的目錄
String addressDir = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
final int totalColumn = cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
final int currentColumn = cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
int totalSize = cursor.getInt(totalColumn);
int currentSize = cursor.getInt(currentColumn);
float percent = (float) currentSize / (float) totalSize;
int progress = Math.round(percent * 100);
materialDialog.setProgress(progress);
if (progress == 100)
{
materialDialog.dismiss();
installAPK();
}
}
} finally
{
if (cursor != null)
{
cursor.close();
}
}
}
}
/*
// 使用瀏覽器下載
private void openBrowserDown(UpdateVersion update)
{
String apkUrl = Constants.URL_HOSTS + update.getUrl();
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setData(Uri.parse(apkUrl));
mActivity.startActivity(intent);
SystemClock.sleep(1500L);
System.exit(0);
}
*/
private void installAPK()
{
File apkFile =
new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), apkName);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
Uri apkUri = FileProvider.getUriForFile(mActivity, "com.wzy.buytickets.update.fileprovider", apkFile);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
} else
{
intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
}
mActivity.startActivity(intent);
}
/**
* 釋放當前資源
*/
public void onDestroy()
{
if (!Constants.IS_CHECK_UPDATE && downloadManager == null) return;
downloadManager = null;
mActivity.getContentResolver().unregisterContentObserver(downloadObserver);
}
}
使用:
private UpdateManager updateManager; // 更新類
if (updateManager == null) // 初始化
{
updateManager = new UpdateManager(this);
}
updateManager.queryVersion(); // 呼叫(直接呼叫或button點選呼叫)