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

由于Android项目开源所致,市面上出现了N多安卓软件市场。为了让我们开发的软件有更多的用户使用,我们需要向N多市场发布,软件升级后,我们也必须到安卓市场上进行更新,给我们增加了工作量。因此我们有必要给我们的Android应用增加自动更新的功能。

既然实现自动更新,我们首先必须让我们的应用知道是否存在新版本的软件,因此我们可以在自己的网站上放置配置文件,存放软件的版本信息:

<update>
  <version>2</version>
  <name>baidu_xinwen_1.1.0</name>
  <url>http://gdown.baidu.com/data/wisegame/f98d235e39e29031/baiduxinwen.apk</url>
</update>

在这里我使用的是XML文件,方便读取。由于XML文件内容比较少,因此可通过DOM方式进行文件的解析:

public class ParseXmlService
{
  public HashMap<String, String> parseXml(InputStream inStream) throws Exception
  {
    HashMap<String, String> hashMap = new HashMap<String, String>(); 

    // 实例化一个文档构建器工厂
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    // 通过文档构建器工厂获取一个文档构建器
    DocumentBuilder builder = factory.newDocumentBuilder();
    // 通过文档通过文档构建器构建一个文档实例
    Document document = builder.parse(inStream);
    //获取XML文件根节点
    Element root = document.getDocumentElement();
    //获得所有子节点
    NodeList childNodes = root.getChildNodes();
    for (int j = 0; j < childNodes.getLength(); j++)
    {
      //遍历子节点
      Node childNode = (Node) childNodes.item(j);
      if (childNode.getNodeType() == Node.ELEMENT_NODE)
      {
        Element childElement = (Element) childNode;
        //版本号
        if ("version".equals(childElement.getNodeName()))
        {
          hashMap.put("version",childElement.getFirstChild().getNodeValue());
        }
        //软件名称
        else if (("name".equals(childElement.getNodeName())))
        {
          hashMap.put("name",childElement.getFirstChild().getNodeValue());
        }
        //下载地址
        else if (("url".equals(childElement.getNodeName())))
        {
          hashMap.put("url",childElement.getFirstChild().getNodeValue());
        }
      }
    }
    return hashMap;
  }

通过parseXml()方法,我们可以获取服务器上应用的版本、文件名以及下载地址。紧接着我们就需要获取到我们手机上应用的版本信息:

 /**
 * 获取软件版本号
 *
 * @param context
 * @return
 */
private int getVersionCode(Context context)
{
  int versionCode = 0;
  try
  {
    // 获取软件版本号,
    versionCode = context.getPackageManager().getPackageInfo("com.szy.update", 0).versionCode;
  } catch (NameNotFoundException e)
  {
    e.printStackTrace();
  }
  return versionCode;
}

通过该方法我们获取到的versionCode对应AndroidManifest.xml下android:versionCode。android:versionCode和android:versionName两个属性分别表示版本号,版本名称。versionCode是整数型,而versionName是字符串。由于versionName是给用户看的,不太容易比较大小,升级检查时,就可以检查versionCode。把获取到的手机上应用版本与服务器端的版本进行比较,应用就可以判断处是否需要更新软件。

处理流程

处理代码

package com.szy.update; 

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap; 

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast; 

public class UpdateManager
{
  /* 下载中 */
  private static final int DOWNLOAD = 1;
  /* 下载结束 */
  private static final int DOWNLOAD_FINISH = 2;
  /* 保存解析的XML信息 */
  HashMap<String, String> mHashMap;
  /* 下载保存路径 */
  private String mSavePath;
  /* 记录进度条数量 */
  private int progress;
  /* 是否取消更新 */
  private boolean cancelUpdate = false; 

  private Context mContext;
  /* 更新进度条 */
  private ProgressBar mProgress;
  private Dialog mDownloadDialog; 

  private Handler mHandler = new Handler()
  {
    public void handleMessage(Message msg)
    {
      switch (msg.what)
      {
      // 正在下载
      case DOWNLOAD:
        // 设置进度条位置
        mProgress.setProgress(progress);
        break;
      case DOWNLOAD_FINISH:
        // 安装文件
        installApk();
        break;
      default:
        break;
      }
    };
  }; 

  public UpdateManager(Context context)
  {
    this.mContext = context;
  } 

  /**
   * 检测软件更新
   */
  public void checkUpdate()
  {
    if (isUpdate())
    {
      // 显示提示对话框
      showNoticeDialog();
    } else
    {
      Toast.makeText(mContext, R.string.soft_update_no, Toast.LENGTH_LONG).show();
    }
  } 

  /**
   * 检查软件是否有更新版本
   *
   * @return
   */
  private boolean isUpdate()
  {
    // 获取当前软件版本
    int versionCode = getVersionCode(mContext);
    // 把version.xml放到网络上,然后获取文件信息
    InputStream inStream = ParseXmlService.class.getClassLoader().getResourceAsStream("version.xml");
    // 解析XML文件。 由于XML文件比较小,因此使用DOM方式进行解析
    ParseXmlService service = new ParseXmlService();
    try
    {
      mHashMap = service.parseXml(inStream);
    } catch (Exception e)
    {
      e.printStackTrace();
    }
    if (null != mHashMap)
    {
      int serviceCode = Integer.valueOf(mHashMap.get("version"));
      // 版本判断
      if (serviceCode > versionCode)
      {
        return true;
      }
    }
    return false;
  } 

/**
 * 获取软件版本号
 *
 * @param context
 * @return
 */
private int getVersionCode(Context context)
{
  int versionCode = 0;
  try
  {
    // 获取软件版本号,对应AndroidManifest.xml下android:versionCode
    versionCode = context.getPackageManager().getPackageInfo("com.szy.update", 0).versionCode;
  } catch (NameNotFoundException e)
  {
    e.printStackTrace();
  }
  return versionCode;
} 

  /**
   * 显示软件更新对话框
   */
  private void showNoticeDialog()
  {
    // 构造对话框
    AlertDialog.Builder builder = new Builder(mContext);
    builder.setTitle(R.string.soft_update_title);
    builder.setMessage(R.string.soft_update_info);
    // 更新
    builder.setPositiveButton(R.string.soft_update_updatebtn, new OnClickListener()
    {
      @Override
      public void onClick(DialogInterface dialog, int which)
      {
        dialog.dismiss();
        // 显示下载对话框
        showDownloadDialog();
      }
    });
    // 稍后更新
    builder.setNegativeButton(R.string.soft_update_later, new OnClickListener()
    {
      @Override
      public void onClick(DialogInterface dialog, int which)
      {
        dialog.dismiss();
      }
    });
    Dialog noticeDialog = builder.create();
    noticeDialog.show();
  } 

  /**
   * 显示软件下载对话框
   */
  private void showDownloadDialog()
  {
    // 构造软件下载对话框
    AlertDialog.Builder builder = new Builder(mContext);
    builder.setTitle(R.string.soft_updating);
    // 给下载对话框增加进度条
    final LayoutInflater inflater = LayoutInflater.from(mContext);
    View v = inflater.inflate(R.layout.softupdate_progress, null);
    mProgress = (ProgressBar) v.findViewById(R.id.update_progress);
    builder.setView(v);
    // 取消更新
    builder.setNegativeButton(R.string.soft_update_cancel, new OnClickListener()
    {
      @Override
      public void onClick(DialogInterface dialog, int which)
      {
        dialog.dismiss();
        // 设置取消状态
        cancelUpdate = true;
      }
    });
    mDownloadDialog = builder.create();
    mDownloadDialog.show();
    // 现在文件
    downloadApk();
  } 

  /**
   * 下载apk文件
   */
  private void downloadApk()
  {
    // 启动新线程下载软件
    new downloadApkThread().start();
  } 

  /**
   * 下载文件线程
   *
   * @author coolszy
   */
  private class downloadApkThread extends Thread
  {
    @Override
    public void run()
    {
      try
      {
        // 判断SD卡是否存在,并且是否具有读写权限
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
        {
          // 获得存储卡的路径
          String sdpath = Environment.getExternalStorageDirectory() + "/";
          mSavePath = sdpath + "download";
          URL url = new URL(mHashMap.get("url"));
          // 创建连接
          HttpURLConnection conn = (HttpURLConnection) url.openConnection();
          conn.connect();
          // 获取文件大小
          int length = conn.getContentLength();
          // 创建输入流
          InputStream is = conn.getInputStream(); 

          File file = new File(mSavePath);
          // 判断文件目录是否存在
          if (!file.exists())
          {
            file.mkdir();
          }
          File apkFile = new File(mSavePath, mHashMap.get("name"));
          FileOutputStream fos = new FileOutputStream(apkFile);
          int count = 0;
          // 缓存
          byte buf[] = new byte[1024];
          // 写入到文件中
          do
          {
            int numread = is.read(buf);
            count += numread;
            // 计算进度条位置
            progress = (int) (((float) count / length) * 100);
            // 更新进度
            mHandler.sendEmptyMessage(DOWNLOAD);
            if (numread <= 0)
            {
              // 下载完成
              mHandler.sendEmptyMessage(DOWNLOAD_FINISH);
              break;
            }
            // 写入文件
            fos.write(buf, 0, numread);
          } while (!cancelUpdate);// 点击取消就停止下载.
          fos.close();
          is.close();
        }
      } catch (MalformedURLException e)
      {
        e.printStackTrace();
      } catch (IOException e)
      {
        e.printStackTrace();
      }
      // 取消下载对话框显示
      mDownloadDialog.dismiss();
    }
  }; 

  /**
   * 安装APK文件
   */
  private void installApk()
  {
    File apkfile = new File(mSavePath, mHashMap.get("name"));
    if (!apkfile.exists())
    {
      return;
    }
    // 通过Intent安装APK文件
    Intent i = new Intent(Intent.ACTION_VIEW);
    i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");
    mContext.startActivity(i);
  }
}

效果图

检查模拟器SDCARD是否存在下载文件:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android如何实现APP自动更新

    先来看看要实现的效果图: 对于安卓用户来说,手机应用市场说满天飞可是一点都不夸张,比如小米,魅族,百度,360,机锋,应用宝等等,当我们想上线一款新版本APP时,先不说渠道打包的麻烦,单纯指上传APP到各大应用市场的工作量就已经很大了,好不容易我们把APP都上传完了,突然发现一个会导致应用闪退的小Bug,这时那个崩溃啊,明明不是很大的改动,难道我们还要再去重新去把各大应用市场的版本再上传更新一次?相信我,运营人员肯定会弄死你的!! 有问题,自然就会有解决问题的方案,因此我们就会想到如果在APP里

  • 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示例

    1.设计思路,使用VersionCode定义为版本升级参数.android为我们定义版本提供了2个属性: 复制代码 代码如下: <manifest package="com.cnblogs.tianxia.subway"android:versionCode="1" <!--Integer类型,系统不显示给用户-->android:versionName="1.0"<!--String类型,系统显示用户-->>

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

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

  • Android应用App更新实例详解

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

  • Android-App增量更新的使用姿势

    简述 增量更新,根据字面理解,就是下载增加的那部分来达到更新的目的,实际就是这个意思. 原理 用一个旧的Apk安装与一个新的Apk安装包使用 bsdiff工具 ,执行命令生成一个差异文件,此差异文件就是我们修改需要更新下载的那部分. 引入代码及so文件 首先,根据你的系统的架构选择不同的so文件放到你的工程中 接着,需要把加载so文件的Java类引入到你的工程中,引入时,需注意,不能修改这个类的包名. 到此,增量更新引入完成. 使用 下载bsdiff工具,然后执行命令:bsdiff,会显示出命令

  • Android App增量更新详解及实例代码

    Android App增量更新实例--Smart App Updates        介绍 你所看到的,是一个用于Android应用程序增量更新的开源库. 包括客户端.服务端两部分代码. 原理 自从 Android 4.1 开始,Google引入了应用程序的增量更新. Link: http://developer.android.com/about/versions/jelly-bean.html Smart app updates is a new feature of Google Pla

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

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

  • Android实现APP自动更新功能

    现在一般的android软件都是需要不断更新的,当你打开某个app的时候,如果有新的版本,它会提示你有新版本需要更新.该小程序实现的就是这个功能. 该小程序的特点是,当有更新时,会弹出一个提示框,点击确定,则在通知来创建一个进度条进行下载,点击取消,则取消更新. 以下是详细代码: 1.创建布局文件notification_item.xml,用于在通知栏生成一个进度条和下载图标. <?xml version="1.0" encoding="utf-8"?>

  • Android实现图片自动切换功能(实例代码详解)

    在Android中图片的自动切换不仅可以实现自动切换,而且还可以使用手动切换.而且一般在切换的时候,在图片下方还带有其他内容的切换,用来标记是第几个图片的切换. 这种效果在我们日常生活中很常见,例如某宝购物,一些商城都可以使用到,用户体验度极好,今天小编就通过实例代码给大家分享android 图片自动切换功能的实现. 实现效果如下: 具体的示例代码如下: 布局代码: <?xml version="1.0" encoding="utf-8"?> <S

  • 基于Retrofit2+RxJava2实现Android App自动更新

    本文实例为大家分享了Retrofit2 RxJava2实现Android App自动更新,具体内容如下 功能解析 自动更新可以说已经是App的标配了,很多第三方平台也都支持这个功能,最近手头上的项目需要加入这个App自动更新,考虑到项目里有用到Retrofit2和RxJava2,于是打算使用它俩自己实现这个功能. 分析App自动更新,可以分为以下三个功能点: 1.APK文件的下载 2.下载进度的实时更新显示 3.下载完成后的自动安装 其中比较难的一点是下载进度的实时更新显示,更难的是如何优雅的进

  • android实现软件自动更新的步骤

    本篇文章是直接下载最新的APK安装的方法,并不是增量下载该APk. 想要实现一个android应用,自动更新下载APK软件的方法,我采取的是以下几步方法: 1.每次进入主界面时,获取服务器的数据,看是否是最新版本,是,则无操作,否,则进行以下步骤: 2.弹出是否更新软件的对话框,点击下载后 3.弹出下载的进度条的对话框,开始下载,可以上随时点击按钮,停止下载 4.下载完成后,调用系统安装软件的服务,安装软件 效果图:     实现过程:   新建一个UpdateManager方法,具体内容我已经

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

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

  • Android程序自动更新功能模块的实现方法【附完整demo源码下载】

    本文实例讲述了Android程序自动更新功能模块的实现方法.分享给大家供大家参考,具体如下: 在程序启动的时候检测服务器上有没有对应版本更新,如果有更新,提示用户是否更新. 在程序启动的时候首先调用更新模块检测服务器上存放的版本号跟当前程序的版本号如果大于当前版本号,弹出更新对话框,如果用户选择更新,则显示当前更新状态,然后替换当前程序. 程序调用版本更新检测: private UpdateManager updateMan; private ProgressDialog updateProgr

  • Android App自动更新之通知栏下载

    本文实例为大家分享了Android App自动更新通知栏下载的具体代码,供大家参考,具体内容如下 版本更新说明 这里有调用UpdateService启动服务检查下载安装包等 1. 文件下载,下完后写入到sdcard 2. 如何在通知栏上显示下载进度 3. 下载完毕自动安装 4. 如何判断是否有新版本 版本更新的主类 package com.wei.update; import java.io.IOException; import java.io.InputStream; import java

  • Android 百度地图POI搜索功能实例代码

    在没介绍正文之前先给大家说下poi是什么意思. 由于工作的关系,经常在文件中会看到POI这三个字母的缩写,但是一直对POI的概念和含义没有很详细的去研究其背后代表的意思.今天下班之前,又看到了POI这三个字母,决定认认真真的搜索一些POI具体的含义. POI是英文的缩写,原来的单词是point of interest, 直译成中文就是兴趣点的意思.兴趣点这个词最早来自于导航地图厂商.地图厂商为了提供尽可能多的位置信息,花费了很大的精力去寻找诸如加油站,餐馆,酒店,景点等目的地,这些目的地其实都可

随机推荐