1. 程式人生 > >Android app版本升級的一個簡單實現

Android app版本升級的一個簡單實現

夢想會被現實磨滅,希望我能堅持的長久!

1升級原理

build.gradle 中 versionCode 1 , versionName “1.0.0” 是升級的關鍵,versionCode是個int,versionName是個String,其中versionCode每次要升級版本都需要+1,VersionName是給使用者看的,讓使用者知道當前版本。
升級原理:
從伺服器獲取升級資訊,包括versionCode,versionName,升級下載app的地址url,是否強制升級,升級的資訊等,然後通過比較本地app的versionCode,決定是否下載app進行升級。

2一個簡單的升級示例

//獲取versionCode
  public static int getVersionCode(Context context) {
        int version = 0;
        try {
            PackageManager packageManager = context.getPackageManager();
            PackageInfo packInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
            version = packInfo.
versionCode; } catch (Exception e) { e.printStackTrace(); } return version; }
public class UpdateHelper {
    private static final int ALREADY_NEW = 1;
    private static final int SHOWUPDATE = 2;
    private static final int INSTALLUPDATE = 3;

    private
final String savePath = Environment.getExternalStorageDirectory() .getPath() + "/updateload"; private UpdateInfoData mUpdateInfoData; private File mDownloadedFile = null; private final String defaultPackageName = "testapp.apk"; private Context mContext = null; private boolean mShowToast = false; public UpdateHelper(Context context, boolean showToast) { mContext = context; mShowToast = showToast; mUpdateInfoData = new UpdateInfoData("0",0,"0","",""); } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case ALREADY_NEW: if ( mDownloadedFile != null ) { //刪除上次已下載的檔案 if ( mDownloadedFile.exists() ) { if (! mDownloadedFile.delete() ) { mDownloadedFile.deleteOnExit(); } } } if (mShowToast) { Toast.makeText(mContext, "當前已是最新版本.", Toast.LENGTH_SHORT) .show(); } break; case SHOWUPDATE: showUpdateDialog(); break; case INSTALLUPDATE: installUpdate(); break; } } }; public void checkUpdate(final boolean reportResult) { try { new Thread(new Runnable() { @Override public void run() { boolean isNewVersionAvailable = false; if (getServerVersionInfo()) { String lastestVersionCode = "0"; if ( mUpdateInfoData != null ) { if (mUpdateInfoData.getLastestVersionCode() != null) { lastestVersionCode = mUpdateInfoData.getLastestVersionCode(); } if (Integer.parseInt(lastestVersionCode) > UpdateUtil.getVersionCode(mContext)) isNewVersionAvailable = true; } } if (isNewVersionAvailable) { Message msg = new Message(); msg.what = SHOWUPDATE; handler.sendMessage(msg); } else { if (reportResult) { Message msg = new Message(); msg.what = ALREADY_NEW; handler.sendMessage(msg); } } } }).start(); } catch (NumberFormatException e) { e.printStackTrace(); } } public boolean getServerVersionInfo() { //是否有可用版本; //從網路獲取升級資訊 Call<UpdateResultData> call = null ;//ServiceFactory.newApiService().getUpdateInfo(paramsMap); try { Response<UpdateResultData> updateInfoResponse = call.execute(); if (updateInfoResponse != null && updateInfoResponse.isSuccessful()) { UpdateResultData resultData = updateInfoResponse.body(); if(resultData != null && resultData.getErrno() == 0){ UpdateInfoData info = updateInfoResponse.body().getResult(); if (info != null) { mUpdateInfoData = info; }else{ return false; } } } else { return false; } } catch (IOException e) { e.printStackTrace(); return false; } return true; } //可以換成retrofit 下載更簡單 public boolean downloadFile(ProgressDialog pd) { URL url; try { String urlStr = ""; if (mUpdateInfoData != null && mUpdateInfoData.getUrl() != null) { urlStr = mUpdateInfoData.getUrl(); } url = new URL(urlStr); HttpURLConnection conn; conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(10000); pd.setMax(conn.getContentLength()); InputStream is = conn.getInputStream(); String packageName = urlStr.substring(urlStr.lastIndexOf("/")); if (!packageName.endsWith("apk")) { packageName = defaultPackageName; } mDownloadedFile = new File(savePath, packageName); FileOutputStream fos = new FileOutputStream(mDownloadedFile); BufferedInputStream bis = new BufferedInputStream(is); byte[] buffer = new byte[1024]; int len; int total = 0; while ((len = bis.read(buffer)) != -1) { fos.write(buffer, 0, len); total += len; //update progress pd.setProgress(total); } fos.close(); bis.close(); is.close(); return true; } catch (MalformedURLException e) { e.printStackTrace(); return false; } catch (IOException e) { e.printStackTrace(); return false; } } public void InstallAPK(Context context) { if ( context == null ) { return; } Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(this.mDownloadedFile), "application/vnd.android.package-archive"); context.startActivity(intent); } //顯示更新dialog private void showUpdateDialog() { try { Builder builder = new Builder(mContext); builder.setIcon(R.mipmap.ic_launcher); builder.setTitle("發現新版本"); builder.setMessage(mUpdateInfoData.getContent().replaceAll("\\\\n","\n")); builder.setCancelable(false); builder.setPositiveButton( "立即更新", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { final ProgressDialog pd = new ProgressDialog(mContext); try { pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); pd.setCancelable(false); pd.setMessage("正在下載..."); pd.show(); new Thread(new Runnable() { @Override public void run() { boolean isSuccess = downloadFile(pd); if (isSuccess) { pd.dismiss(); Message msg = new Message(); msg.what = INSTALLUPDATE; handler.sendMessage(msg); } else { if (pd != null) { pd.dismiss(); } Toast.makeText(mContext, "下載失敗,請檢查你的網路", Toast.LENGTH_SHORT).show(); } } }).start(); } catch (Exception e) { e.printStackTrace(); } } } ); builder.setNegativeButton( mUpdateInfoData.getForce() == 1 ? "退出應用":"暫不更新", (( dialog, which ) -> { if ( mUpdateInfoData != null ) { if ( mUpdateInfoData.getForce() == 1 ) { Process.killProcess( Process.myPid() ); } else { dialog.dismiss(); } } }) ); AlertDialog dialog = builder.create(); dialog.show(); // dialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(Color.BLUE); // dialog.getButton(DialogInterface.BUTTON_NEGATIVE).setTextColor(Color.BLACK); } catch (Exception e) { e.printStackTrace(); } } private void installUpdate() { InstallAPK(mContext); } public void destroyHelper() { try { handler.removeCallbacksAndMessages(null); handler = null; } catch (Exception e) { e.printStackTrace(); } } }
public class UpdateInfoData implements Serializable {
	private String lastestVersionName;
	// 1 for force, 0 for not.
	private int force;
	private String lastestVersionCode;
	private String url;
	private String content;
	}

在這裡插入圖片描述

點選之後利用ProgressDialog更新下載進度,之後完成安裝。

如果想更好的控制dialog的生命週期,或者自定義升級提示框的樣式,可以利用dialogFragment實現。

3關於強制升級

強制升級的實現方法:
使用者不升級無法使用,要嗎升級要麼退出應用,實現方式彈出的升級提示框沒有取消升級按鈕,或者有不升級按鈕點選之後是退出應用。
一般不需要強制升級這個功能,但是有時由於後端介面升級或者資料結構改變,或者重大功能上線都可能需要強制升級功能,但儘量平穩的升級。