当前位置: 移动技术网 > IT编程>移动开发>Android > Android应用APP自动更新功能的代码实现

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

2019年07月24日  | 移动技术网IT编程  | 我要评论

喔ii零,星登陆,红人居

由于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是否存在下载文件:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网