Android应用自动更新的实现

jopen 11年前

那如何实现软件自动更新,下面是具体实例:

效果图:

Android应用自动更新的实现    Android应用自动更新的实现

Android应用自动更新的实现     

具体步骤:

1. 在服务器上部署更新所用的xml文件:version.xml

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

2. 在客户端实现更新操作

  涉及到三个技术:

   1.xml文件的解析

   2.HttpURLConnection连接

   3.文件流I/O

 

这里创建一个解析xml文件的服务类:ParXmlService.java

package com.xiaowu.news.update;    import java.io.InputStream;  import java.util.HashMap;    import javax.xml.parsers.DocumentBuilder;  import javax.xml.parsers.DocumentBuilderFactory;    import org.w3c.dom.Document;  import org.w3c.dom.Element;  import org.w3c.dom.Node;  import org.w3c.dom.NodeList;    public class ParseXmlService {   public HashMap<String, String> parseXml (InputStream inStream) throws Exception{    HashMap<String, String> hashMap = new HashMap<String, String>();    //创建DocumentBuilderFactory,该对象将创建DocumentBuilder。    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();    //创建DocumentBuilder,DocumentBuilder将实际进行解析以创建Document对象    DocumentBuilder builder = factory.newDocumentBuilder();    //解析该文件以创建Document对象    Document document = builder.parse(inStream);    //获取XML文件根节点     Element root = document.getDocumentElement();    //获得所有子节点    NodeList childNodes = root.getChildNodes();    for(int i = 0; i < childNodes.getLength(); i++) {     Node childNode = (Node) childNodes.item(i);     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;   }  }
实现更新操作的管理类:UpdateManager.java
package com.xiaowu.news.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 javax.net.ssl.HttpsURLConnection;    import android.app.AlertDialog;  import android.app.AlertDialog.Builder;  import android.app.Dialog;  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.view.LayoutInflater;  import android.view.View;  import android.widget.ProgressBar;  import android.widget.Toast;    import com.xiaowu.news.R;    /**   *    * @author wwj   * @date 2012/11/17   * 实现软件更新的管理类   */  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 mProgressBar;   //更新进度条的对话框   private Dialog mDownloadDialog;         private Handler mHandler = new Handler() {    public void handleMessage(android.os.Message msg) {     switch(msg.what){     //下载中。。。     case DOWNLOAD:      //更新进度条      System.out.println(progress);      mProgressBar.setProgress(progress);      break;     //下载完成     case DOWNLOAD_FINISH:      // 安装文件      installApk();      break;     }    };   };       public UpdateManager(Context context) {    super();    this.mContext = context;   }         /**    * 检测软件更新    */   public void checkUpdate() {    if (isUpdate()) {     //显示提示对话框     showNoticeDialog();    } else {     Toast.makeText(mContext, R.string.soft_update_no, Toast.LENGTH_SHORT).show();    }       }      private void showNoticeDialog() {    // TODO Auto-generated method stub    //构造对话框    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) {      // TODO Auto-generated method stub      dialog.dismiss();      // 显示下载对话框      showDownloadDialog();     }    });    // 稍后更新    builder.setNegativeButton(R.string.soft_update_later, new OnClickListener() {          @Override     public void onClick(DialogInterface dialog, int which) {      // TODO Auto-generated method stub      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 view = inflater.inflate(R.layout.softupdate_progress, null);    mProgressBar = (ProgressBar) view.findViewById(R.id.update_progress);    builder.setView(view);    builder.setNegativeButton(R.string.soft_update_cancel, new OnClickListener() {          @Override     public void onClick(DialogInterface dialog, int which) {      // TODO Auto-generated method stub      dialog.dismiss();      // 设置取消状态      cancelUpdate = true;     }    });    mDownloadDialog = builder.create();    mDownloadDialog.show();    //下载文件    downloadApk();   }      /**    * 下载APK文件    */   private void downloadApk() {    // TODO Auto-generated method stub    // 启动新线程下载软件    new DownloadApkThread().start();   }       /**    * 检查软件是否有更新版本    * @return    */   public 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) {     // TODO: handle exception     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) {    // TODO Auto-generated method stub    int versionCode = 0;      // 获取软件版本号,对应AndroidManifest.xml下android:versionCode    try {     versionCode = context.getPackageManager().getPackageInfo(       "com.xiaowu.news", 0).versionCode;    } catch (NameNotFoundException e) {     // TODO Auto-generated catch block     e.printStackTrace();    }    return versionCode;   }      /**    * 下载文件线程    * @author Administrator    *    */   private class DownloadApkThread extends Thread {    @Override    public void run() {     try     {      //判断SD卡是否存在,并且是否具有读写权限      if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))      {       // 获取SDCard的路径       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 i = new Intent(Intent.ACTION_VIEW);    i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");    mContext.startActivity(i);   }  }
来自:http://blog.csdn.net/wwj_748/article/details/8195565