软件编程
位置:首页>> 软件编程>> Android编程>> Android应用APP自动更新功能的代码实现

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

作者:coolszy  发布时间:2022-09-17 09:48:25 

标签:android,版本更新

由于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。把获取到的手机上应用版本与服务器端的版本进行比较,应用就可以判断处是否需要更新软件。

处理流程
Android应用APP自动更新功能的代码实现

处理代码


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);
 }
}

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

检查模拟器SDCARD是否存在下载文件:Android应用APP自动更新功能的代码实现
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com