manifest–>[Android..."/>
溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Android應(yīng)用更新之自動(dòng)檢測版本及自動(dòng)升級(jí)

發(fā)布時(shí)間:2020-09-20 03:45:53 來源:腳本之家 閱讀:397 作者:流水潺媛 欄目:移動(dòng)開發(fā)

本文為大家分享了Android自動(dòng)檢測版本及自動(dòng)升級(jí)的具體代碼,供大家參考,具體內(nèi)容如下

步驟:

1.檢測當(dāng)前版本的信息AndroidManifest.xml–>manifest–>[Android]

2.從服務(wù)器獲取版本號(hào)(版本號(hào)存在于xml文件中)并與當(dāng)前檢測到的版本進(jìn)行匹配,如果不匹配,提示用戶進(jìn)行升級(jí),如果匹配則進(jìn)入程序主界面。(demo中假設(shè)需要更新)

3.當(dāng)提示用戶進(jìn)行版本升級(jí)時(shí),如果用戶點(diǎn)擊了“更新”,系統(tǒng)將自動(dòng)從服務(wù)器上下載安裝包并進(jìn)行自動(dòng)升級(jí),如果點(diǎn)擊取消將進(jìn)入程序主界面。

效果圖如下:

Android應(yīng)用更新之自動(dòng)檢測版本及自動(dòng)升級(jí)
Android應(yīng)用更新之自動(dòng)檢測版本及自動(dòng)升級(jí)

Android應(yīng)用更新之自動(dòng)檢測版本及自動(dòng)升級(jí)

Android應(yīng)用更新之自動(dòng)檢測版本及自動(dòng)升級(jí)

下面介紹一下代碼的實(shí)現(xiàn):

1.獲取應(yīng)用的當(dāng)前版本號(hào),我是封裝了一個(gè)工具類來獲取

 // 獲取本版本號(hào),是否更新
  int vision = Tools.getVersion(this);

獲取當(dāng)前版本號(hào)工具類:

public class Tools {
 /**
  * 檢查是否存在SDCard
  *
  * @return
  */
 public static boolean hasSdcard() {
  String state = Environment.getExternalStorageState();
  if (state.equals(Environment.MEDIA_MOUNTED)) {
   return true;
  } else {
   return false;
  }
 }

 /**
  * 2 * 獲取版本號(hào) 3 * @return 當(dāng)前應(yīng)用的版本號(hào) 4
  */
 public static int getVersion(Context context) {
  try {
   PackageManager manager = context.getPackageManager();
   PackageInfo info = manager.getPackageInfo(context.getPackageName(),
     0);
   String version = info.versionName;
   int versioncode = info.versionCode;
   return versioncode;
  } catch (Exception e) {
   e.printStackTrace();
  }
  return 0;
 }

}

2.獲取服務(wù)器版本號(hào),是否要更新(此處就是簡單的網(wǎng)絡(luò)請(qǐng)求拿到需要的數(shù)據(jù)即可,我是寫了固定值)

 // 獲取更新版本號(hào)
 private void getVersion(final int vision) {
//   {"data":{"content":"其他bug修復(fù)。","id":"2","api_key":"android",
//   // "version":"2.1"},"msg":"獲取成功","status":1}
  String data = "";
  //網(wǎng)絡(luò)請(qǐng)求獲取當(dāng)前版本號(hào)和下載鏈接
  //實(shí)際操作是從服務(wù)器獲取
  //demo寫死了

  String newversion = "2.1";//更新新的版本號(hào)
  String content = "\n" +
    "就不告訴你我們更新了什么-。-\n" +
    "\n" +
    "----------萬能的分割線-----------\n" +
    "\n" +
    "(ㄒoㄒ) 被老板打了一頓,還是來告訴你吧:\n" +

    "1.下架商品誤買了?恩。。。我搞了點(diǎn)小動(dòng)作就不會(huì)出現(xiàn)了\n" +
    "2.側(cè)邊欄、彈框優(yōu)化 —— 這個(gè)你自己去探索吧,總得留點(diǎn)懸念嘛-。-\n";//更新內(nèi)容
  String url = "http://openbox.mobilem.#/index/d/sid/3429345";//安裝包下載地址

  double newversioncode = Double
    .parseDouble(newversion);
  int cc = (int) (newversioncode);

  System.out.println(newversion + "v" + vision + ",,"
    + cc);
  if (cc != vision) {
   if (vision < cc) {
    System.out.println(newversion + "v"
      + vision);
    // 版本號(hào)不同
    ShowDialog(vision, newversion, content, url);
   }
  }
 }

3.接下來就是下載文件了

(1) 顯示下載
此處用的是自定義按鈕:

 /**
  * 升級(jí)系統(tǒng)
  *
  * @param content
  * @param url
  */
 private void ShowDialog(int vision, String newversion, String content,
       final String url) {
  final MaterialDialog dialog = new MaterialDialog(this);
  dialog.content(content).btnText("取消", "更新").title("版本更新 ")
    .titleTextSize(15f).show();
  dialog.setCanceledOnTouchOutside(false);
  dialog.setOnBtnClickL(new OnBtnClickL() {// left btn click listener
   @Override
   public void onBtnClick() {
    dialog.dismiss();
   }
  }, new OnBtnClickL() {// right btn click listener

   @Override
   public void onBtnClick() {
    dialog.dismiss();
    // pBar = new ProgressDialog(MainActivity.this,
    // R.style.dialog);
    pBar = new CommonProgressDialog(MainActivity.this);
    pBar.setCanceledOnTouchOutside(false);
    pBar.setTitle("正在下載");
    pBar.setCustomTitle(LayoutInflater.from(
      MainActivity.this).inflate(
      R.layout.title_dialog, null));
    pBar.setMessage("正在下載");
    pBar.setIndeterminate(true);
    pBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    pBar.setCancelable(true);
    // downFile(URLData.DOWNLOAD_URL);
    final DownloadTask downloadTask = new DownloadTask(
      MainActivity.this);
    downloadTask.execute(url);
    pBar.setOnCancelListener(new DialogInterface.OnCancelListener() {
     @Override
     public void onCancel(DialogInterface dialog) {
      downloadTask.cancel(true);
     }
    });
   }
  });
 }

原生的按鈕:

 new android.app.AlertDialog.Builder(this)
    .setTitle("版本更新")
    .setMessage(content)
    .setPositiveButton("更新", new DialogInterface.OnClickListener() {
     @Override
     public void onClick(DialogInterface dialog, int which) {
      dialog.dismiss();
      pBar = new CommonProgressDialog(MainActivity.this);
      pBar.setCanceledOnTouchOutside(false);
      pBar.setTitle("正在下載");
      pBar.setCustomTitle(LayoutInflater.from(
        MainActivity.this).inflate(
        R.layout.title_dialog, null));
      pBar.setMessage("正在下載");
      pBar.setIndeterminate(true);
      pBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
      pBar.setCancelable(true);
      // downFile(URLData.DOWNLOAD_URL);
      final DownloadTask downloadTask = new DownloadTask(
        MainActivity.this);
      downloadTask.execute(url);
      pBar.setOnCancelListener(new DialogInterface.OnCancelListener() {
       @Override
       public void onCancel(DialogInterface dialog) {
        downloadTask.cancel(true);
       }
      });
     }
    })
    .setNegativeButton("取消", new DialogInterface.OnClickListener() {
     @Override
     public void onClick(DialogInterface dialog, int which) {
      dialog.dismiss();
     }
    })
    .show();

(2)通過異步任務(wù)實(shí)現(xiàn)進(jìn)度++

 /**
  * 下載應(yīng)用
  *
  * @author Administrator
  */
 class DownloadTask extends AsyncTask<String, Integer, String> {

  private Context context;
  private PowerManager.WakeLock mWakeLock;

  public DownloadTask(Context context) {
   this.context = context;
  }

  @Override
  protected String doInBackground(String... sUrl) {
   InputStream input = null;
   OutputStream output = null;
   HttpURLConnection connection = null;
   File file = null;
   try {
    URL url = new URL(sUrl[0]);
    connection = (HttpURLConnection) url.openConnection();
    connection.connect();
    // expect HTTP 200 OK, so we don't mistakenly save error
    // report
    // instead of the file
    if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
     return "Server returned HTTP "
       + connection.getResponseCode() + " "
       + connection.getResponseMessage();
    }
    // this will be useful to display download percentage
    // might be -1: server did not report the length
    int fileLength = connection.getContentLength();
    if (Environment.getExternalStorageState().equals(
      Environment.MEDIA_MOUNTED)) {
     file = new File(Environment.getExternalStorageDirectory(),
       DOWNLOAD_NAME);

     if (!file.exists()) {
      // 判斷父文件夾是否存在
      if (!file.getParentFile().exists()) {
       file.getParentFile().mkdirs();
      }
     }

    } else {
     Toast.makeText(MainActivity.this, "sd卡未掛載",
       Toast.LENGTH_LONG).show();
    }
    input = connection.getInputStream();
    output = new FileOutputStream(file);
    byte data[] = new byte[4096];
    long total = 0;
    int count;
    while ((count = input.read(data)) != -1) {
     // allow canceling with back button
     if (isCancelled()) {
      input.close();
      return null;
     }
     total += count;
     // publishing the progress....
     if (fileLength > 0) // only if total length is known
      publishProgress((int) (total * 100 / fileLength));
     output.write(data, 0, count);

    }
   } catch (Exception e) {
    System.out.println(e.toString());
    return e.toString();

   } finally {
    try {
     if (output != null)
      output.close();
     if (input != null)
      input.close();
    } catch (IOException ignored) {
    }
    if (connection != null)
     connection.disconnect();
   }
   return null;
  }

  @Override
  protected void onPreExecute() {
   super.onPreExecute();
   // take CPU lock to prevent CPU from going off if the user
   // presses the power button during download
   PowerManager pm = (PowerManager) context
     .getSystemService(Context.POWER_SERVICE);
   mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
     getClass().getName());
   mWakeLock.acquire();
   pBar.show();
  }

  @Override
  protected void onProgressUpdate(Integer... progress) {
   super.onProgressUpdate(progress);
   // if we get here, length is known, now set indeterminate to false
   pBar.setIndeterminate(false);
   pBar.setMax(100);
   pBar.setProgress(progress[0]);
  }

  @Override
  protected void onPostExecute(String result) {
   mWakeLock.release();
   pBar.dismiss();
   if (result != null) {

//    // 申請(qǐng)多個(gè)權(quán)限。大神的界面
//    AndPermission.with(MainActivity.this)
//      .requestCode(REQUEST_CODE_PERMISSION_OTHER)
//      .permission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE)
//      // rationale作用是:用戶拒絕一次權(quán)限,再次申請(qǐng)時(shí)先征求用戶同意,再打開授權(quán)對(duì)話框,避免用戶勾選不再提示。
//      .rationale(new RationaleListener() {
//          @Override
//          public void showRequestPermissionRationale(int requestCode, Rationale rationale) {
//           // 這里的對(duì)話框可以自定義,只要調(diào)用rationale.resume()就可以繼續(xù)申請(qǐng)。
//           AndPermission.rationaleDialog(MainActivity.this, rationale).show();
//          }
//         }
//      )
//      .send();
    // 申請(qǐng)多個(gè)權(quán)限。
    AndPermission.with(MainActivity.this)
      .requestCode(REQUEST_CODE_PERMISSION_SD)
      .permission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE)
      // rationale作用是:用戶拒絕一次權(quán)限,再次申請(qǐng)時(shí)先征求用戶同意,再打開授權(quán)對(duì)話框,避免用戶勾選不再提示。
      .rationale(rationaleListener
      )
      .send();


    Toast.makeText(context, "您未打開SD卡權(quán)限" + result, Toast.LENGTH_LONG).show();
   } else {
    // Toast.makeText(context, "File downloaded",
    // Toast.LENGTH_SHORT)
    // .show();
    update();
   }

  }
 }

此處下載apk文件,需要獲取SD的讀寫權(quán)限(用的是嚴(yán)大的權(quán)限庫)

權(quán)限庫GitHub

private static final int REQUEST_CODE_PERMISSION_SD = 101;

 private static final int REQUEST_CODE_SETTING = 300;
 private RationaleListener rationaleListener = new RationaleListener() {
  @Override
  public void showRequestPermissionRationale(int requestCode, final Rationale rationale) {
   // 這里使用自定義對(duì)話框,如果不想自定義,用AndPermission默認(rèn)對(duì)話框:
   // AndPermission.rationaleDialog(Context, Rationale).show();

   // 自定義對(duì)話框。
   AlertDialog.build(MainActivity.this)
     .setTitle(R.string.title_dialog)
     .setMessage(R.string.message_permission_rationale)
     .setPositiveButton(R.string.btn_dialog_yes_permission, new DialogInterface.OnClickListener() {
      @Override
      public void onClick(DialogInterface dialog, int which) {
       dialog.cancel();
       rationale.resume();
      }
     })

     .setNegativeButton(R.string.btn_dialog_no_permission, new DialogInterface.OnClickListener() {
      @Override
      public void onClick(DialogInterface dialog, int which) {
       dialog.cancel();
       rationale.cancel();
      }
     })
     .show();
  }
 };
 //----------------------------------SD權(quán)限----------------------------------//


 @PermissionYes(REQUEST_CODE_PERMISSION_SD)
 private void getMultiYes(List<String> grantedPermissions) {
  Toast.makeText(this, R.string.message_post_succeed, Toast.LENGTH_SHORT).show();
 }

 @PermissionNo(REQUEST_CODE_PERMISSION_SD)
 private void getMultiNo(List<String> deniedPermissions) {
  Toast.makeText(this, R.string.message_post_failed, Toast.LENGTH_SHORT).show();

  // 用戶否勾選了不再提示并且拒絕了權(quán)限,那么提示用戶到設(shè)置中授權(quán)。
  if (AndPermission.hasAlwaysDeniedPermission(this, deniedPermissions)) {
   AndPermission.defaultSettingDialog(this, REQUEST_CODE_SETTING)
     .setTitle(R.string.title_dialog)
     .setMessage(R.string.message_permission_failed)
     .setPositiveButton(R.string.btn_dialog_yes_permission)
     .setNegativeButton(R.string.btn_dialog_no_permission, null)
     .show();

   // 更多自定dialog,請(qǐng)看上面。
  }
 }

 //----------------------------------權(quán)限回調(diào)處理----------------------------------//

 @Override
 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[]
   grantResults) {
  super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  /**
   * 轉(zhuǎn)給AndPermission分析結(jié)果。
   *
   * @param object  要接受結(jié)果的Activity、Fragment。
   * @param requestCode 請(qǐng)求碼。
   * @param permissions 權(quán)限數(shù)組,一個(gè)或者多個(gè)。
   * @param grantResults 請(qǐng)求結(jié)果。
   */
  AndPermission.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
 }

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  switch (requestCode) {
   case REQUEST_CODE_SETTING: {
    Toast.makeText(this, R.string.message_setting_back, Toast.LENGTH_LONG).show();
    //設(shè)置成功,再次請(qǐng)求更新
    getVersion(Tools.getVersion(MainActivity.this));
    break;
   }
  }
 }

(3) 當(dāng)apk文件下載完畢時(shí),打開安裝

private void update() {
  //安裝應(yīng)用
  Intent intent = new Intent(Intent.ACTION_VIEW);
  intent.setDataAndType(Uri.fromFile(new File(Environment
      .getExternalStorageDirectory(), DOWNLOAD_NAME)),
    "application/vnd.android.package-archive");
  startActivity(intent);
 }

源碼

此demo已經(jīng)上傳到GitHub,如有需要自行下載

GitHub: 鏈接地址

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI