首页 > 系统 > Android > 正文

Android应用更新之自动检测版本及自动升级

2019-10-21 21:39:18
字体:
来源:转载
供稿:网友

步骤:

1.检测当前版本的信息AndroidManifest.xml–>manifest–>[Android]

2.从服务器获取版本号(版本号存在于xml文件中)并与当前检测到的版本进行匹配,如果不匹配,提示用户进行升级,如果匹配则进入程序主界面。(demo中假设需要更新)

3.当提示用户进行版本升级时,如果用户点击了“更新”,系统将自动从服务器上下载安装包并进行自动升级,如果点击取消将进入程序主界面。

效果图如下:

Android,应用更新,自动检测版本,自动升级 
Android,应用更新,自动检测版本,自动升级

Android,应用更新,自动检测版本,自动升级

Android,应用更新,自动检测版本,自动升级

下面介绍一下代码的实现:

1.获取应用的当前版本号,我是封装了一个工具类来获取

 // 获取本版本号,是否更新  int vision = Tools.getVersion(this);

获取当前版本号工具类:

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 * 获取版本号 3 * @return 当前应用的版本号 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.获取服务器版本号,是否要更新(此处就是简单的网络请求拿到需要的数据即可,我是写了固定值)

 // 获取更新版本号 private void getVersion(final int vision) {//   {"data":{"content":"其他bug修复。","id":"2","api_key":"android",//   // "version":"2.1"},"msg":"获取成功","status":1}  String data = "";  //网络请求获取当前版本号和下载链接  //实际操作是从服务器获取  //demo写死了  String newversion = "2.1";//更新新的版本号  String content = "/n" +    "就不告诉你我们更新了什么-。-/n" +    "/n" +    "----------万能的分割线-----------/n" +    "/n" +    "(ㄒoㄒ) 被老板打了一顿,还是来告诉你吧:/n" +    "1.下架商品误买了?恩。。。我搞了点小动作就不会出现了/n" +    "2.侧边栏、弹框优化 —— 这个你自己去探索吧,总得留点悬念嘛-。-/n";//更新内容  String url = "http://openbox.mobilem.360.cn/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);    // 版本号不同    ShowDialog(vision, newversion, content, url);   }  } }

3.接下来就是下载文件了 

(1) 显示下载 
此处用的是自定义按钮:

 /**  * 升级系统  *  * @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)通过异步任务实现进度++

 

 /**  * 下载应用  *  * @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) {//    // 申请多个权限。大神的界面//    AndPermission.with(MainActivity.this)//      .requestCode(REQUEST_CODE_PERMISSION_OTHER)//      .permission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE)//      // rationale作用是:用户拒绝一次权限,再次申请时先征求用户同意,再打开授权对话框,避免用户勾选不再提示。//      .rationale(new RationaleListener() {//          @Override//          public void showRequestPermissionRationale(int requestCode, Rationale rationale) {//           // 这里的对话框可以自定义,只要调用rationale.resume()就可以继续申请。//           AndPermission.rationaleDialog(MainActivity.this, rationale).show();//          }//         }//      )//      .send();    // 申请多个权限。    AndPermission.with(MainActivity.this)      .requestCode(REQUEST_CODE_PERMISSION_SD)      .permission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE)      // rationale作用是:用户拒绝一次权限,再次申请时先征求用户同意,再打开授权对话框,避免用户勾选不再提示。      .rationale(rationaleListener      )      .send();    Toast.makeText(context, "您未打开SD卡权限" + result, Toast.LENGTH_LONG).show();   } else {    // Toast.makeText(context, "File downloaded",    // Toast.LENGTH_SHORT)    // .show();    update();   }  } }

此处下载apk文件,需要获取SD的读写权限(用的是严大的权限库) 

权限库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) {   // 这里使用自定义对话框,如果不想自定义,用AndPermission默认对话框:   // AndPermission.rationaleDialog(Context, Rationale).show();   // 自定义对话框。   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权限----------------------------------// @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();  // 用户否勾选了不再提示并且拒绝了权限,那么提示用户到设置中授权。  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,请看上面。  } } //----------------------------------权限回调处理----------------------------------// @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[]   grantResults) {  super.onRequestPermissionsResult(requestCode, permissions, grantResults);  /**   * 转给AndPermission分析结果。   *   * @param object  要接受结果的Activity、Fragment。   * @param requestCode 请求码。   * @param permissions 权限数组,一个或者多个。   * @param grantResults 请求结果。   */  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();    //设置成功,再次请求更新    getVersion(Tools.getVersion(MainActivity.this));    break;   }  } }

(3) 当apk文件下载完毕时,打开安装

private void update() {  //安装应用  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已经上传到GitHub,如有需要自行下载

GitHub: 链接地址

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表