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

本文为大家分享了Android自动检测版本及自动升级的具体代码,供大家参考,具体内容如下

步骤:

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

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

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

效果图如下:


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

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: 链接地址

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

(0)

相关推荐

  • Android应用App更新实例详解

    前言:现在一般的Android软件都是需要不断更新的,当你打开某个app的时候,如果有新的版本,它会提示你有新版本需要更新.该项目实现的就是这个功能.并且有强制更新和更新提示两种方式,当有更新时,会弹出一个提示框,点击下载,则在通知来创建一个进度条进行下载,点击取消,则取消更新. 效果: 开发环境:AndroidStudio2.1.2+gradle-2.10 部分代码: public class UpdateVersionController { private Context context;

  • Android App实现应用内部自动更新的最基本方法示例

    这只是初步的实现,并没有加入自动编译等功能.需要手动更改更新的xml文件和最新的apk.    共涉及到四个文件! 一.客户端 AndroidUpdateTestActivity:程序首页 main.xml:首页布局 Update:更新类 softupdate_progress:更新等待界面 Updage package majier.test; import java.io.File; import java.io.FileOutputStream; import java.io.IOExce

  • Android应用APP自动更新功能的代码实现

    由于Android项目开源所致,市面上出现了N多安卓软件市场.为了让我们开发的软件有更多的用户使用,我们需要向N多市场发布,软件升级后,我们也必须到安卓市场上进行更新,给我们增加了工作量.因此我们有必要给我们的Android应用增加自动更新的功能. 既然实现自动更新,我们首先必须让我们的应用知道是否存在新版本的软件,因此我们可以在自己的网站上放置配置文件,存放软件的版本信息: <update> <version>2</version> <name>baidu

  • Android编程实现应用自动更新、下载、安装的方法

    本文实例讲述了Android编程实现应用自动更新.下载.安装的方法.分享给大家供大家参考,具体如下: 我们看到很多Android应用都具有自动更新功能,用户一键就可以完成软件的升级更新.得益于Android系统的软件包管理和安装机制,这一功能实现起来相当简单,下面我们就来实践一下. 1. 准备知识 在AndroidManifest.xml里定义了每个Android apk的版本标识: <manifest xmlns:android="http://schemas.android.com/a

  • 非常实用的小功能 Android应用版本的更新实例

    每一个应用都是具备一个功能,那就是版本更新,我记得我之前在面试的时候,面试官让我介绍一下应用版本更新的一些具体操作.我当时因为做过这个功能,所以回答的还是很流畅,现在我把这个分享给大家,需要能够共同进步. 我当时是这么说的: 首先呢,我们是应该在用户登录后,在首页执行检查版本信息的操作,具体是,获取到本地的版本号后,提交给服务器进行判断,然后后台来告诉我们当前版本是否为最新版本,紧接着我们拿到下载地址,执行下载的操作,具体的可以使用输入输出流来对文件进行存储和读取,为了方便下载,我们还可以使用一

  • Android编程实现自动检测版本及自动升级的方法

    本文实例讲述了Android编程实现自动检测版本及自动升级的方法.分享给大家供大家参考,具体如下: 步骤: 1.检测当前版本的信息AndroidManifest.xml-->manifest-->android:versionName. 2.从服务器获取版本号(版本号存在于xml文件中)并与当前检测到的版本进行匹配,如果不匹配,提示用户进行升级,如果匹配则进入程序主界面. 3.当提示用户进行版本升级时,如果用户点击了确定,系统将自动从服务器上下载并进行自动升级,如果点击取消将进入程序主界面.

  • Android应用强制更新APP的示例代码

    Android应用强制更新的用途十分广泛,特别上刚上线的应用肯定会存在或多或少的bug,特别是涉及移动支付这一块的内容,如果出错了会造成比较大的损失,所以强制更新显得尤为重要. 一般来说,强制更新的策略就是: 应用启动时请求后台,后台发送应用最新版本的信息(包括应用版本号.名称.更新内容说明.下载包的服务器地址.是否强制更新的标志位)等等. 下面我们就将根据以上思路来写实现代码. 1.AndroidManifest配置版本信息 在AndroidManifest.xml里定义了每个Android

  • Android应用自动更新功能实现的方法

    本文给大家分享Android里应用版本更新功能这一块的实现. 一个好的应用软件都是需要好的维护,从初出版本到最后精品,这个过程需要版本不停的更新,那么如何让用户第一时间获取最新的应用安装包呢?那么就要求我们从第一个版本就要实现升级模块这一功能. 自动更新功能的实现原理,就是我们事先和后台协商好一个接口,我们在应用的主Activity里,去访问这个接口,如果需要更新,后台会返回一些数据(比如,提示语:最新版本的url等).然后我们给出提示框,用户点击开始下载,下载完成开始覆盖安装程序,这样用户的应

  • 安卓(Android)应用版本更新方法

    开发中对版本进行检查并更新的需求基本是所有应用必须有的功能,可是在实际开发中有些朋友就容易忽略一些细节. 版本更新的基本流程: 一般是将本地版本告诉服务器,服务器经过相关处理会返回客户端相关信息,告诉客户端需不需要更新,如果需要更新是强制更新还是非强制更新.客户端得到服务器返回的相关信息后再进一步做逻辑处理. 强制更新: 一般的处理就是进入应用就弹窗通知用户有版本更新,弹窗可以没有取消按钮并不能取消.这样用户就只能选择更新或者关闭应用了,当然也可以添加取消按钮,但是如果用户选择取消则直接退出应用

  • android实现程序自动升级到安装示例分享(下载android程序安装包)

    复制代码 代码如下: //程序下载升级 zhouxiang@JavascriptInterfacepublic void UpdateCAECP(final String path){try{AlertDialog.Builder builder = new Builder((Context)obj);builder.setMessage("检测到有新版本发布,是否进行下载升级?");builder.setTitle("程序更新提示");builder.setPos

随机推荐