android 版本更新
2016-07-27 15:14
423 查看
版本更新
本文是以解析xml的为例.从服务器获取版本号(版本号存在于xml文件中)并与当前检测到的版本进行匹配,如果不匹配,提示用户进行升级,如果匹配则进入程序主界面。
当提示用户进行版本升级时,如果用户点击了确定,系统将自动从服务器上下载并进行自动升级,如果点击取消将进入程序主界面。
首先我们需要请求网络的信息得到接口里面给我们都是什么信息
我们以这个接口为例:(http://www.oschina.net/MobileAppVersion.xml)
以下是关键的一个更新的工具类:
import java.io.BufferedInputStream; import java.io.File; import java.io.FileNotFoundException; 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 com.bwei.test.url.URLS; import android.app.AlertDialog; import android.app.ProgressDialog; import android.app.AlertDialog.Builder; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.util.Log; import android.widget.Button; import android.widget.Toast; /** * 更新版本的工具类 * @author * @date * */ public class UpdateVersionutil { private final String TAG = this.getClass().getName(); private final int UPDATA_NONEED = 0; private final int UPDATA_CLIENT = 1; private final int GET_UNDATAINFO_ERROR = 2; private final int SDCARD_NOMOUNTED = 3; private final int DOWN_ERROR = 4; private Button getVersion; private String localVersion; public static Context mContext; private static UpdateVersionutil updateVersionutil; public static boolean mNeedUpdate; InputStream is; private Update parse; public UpdateVersionutil(Context mContext) { super(); this.mContext = mContext; } /** * 检测更新 */ public void startUpdate(){ localVersion = getVersionName(); CheckVersionTask cv = new CheckVersionTask(); new Thread(cv).start(); } public static UpdateVersionutil getUpdataManger(Context context){ if(updateVersionutil==null){ updateVersionutil=new UpdateVersionutil(context); } return updateVersionutil; } public static void checkUpdata(){ updateVersionutil.startUpdate(); } private String getVersionName() { //getPackageName()是你当前类的包名,0代表是获取版本信息 PackageManager packageManager =mContext.getPackageManager(); PackageInfo packInfo = null; try { packInfo = packageManager.getPackageInfo(mContext.getPackageName(), 0); } catch (NameNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } return packInfo.versionName; } /** * 网络请求 * 获取到网络接口的版本号进行对比 * @author * @date */ public class CheckVersionTask implements Runnable { public void run() { try { //这里URLS.UPDATE_VERSION 是网络接口获取网络信息 URL url = new URL(URLS.UPDATE_VERSION); //***************************************************** HttpURLConnection conn = (HttpURLConnection) url .openConnection(); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); int responseCode = conn.getResponseCode(); if (responseCode == 200) { // 从服务器获得一个输入流 is = conn.getInputStream(); } //******************************************* //调用解析的方法 parse = Update.parse(is); Url = parse.getDownloadUrl(); //********************************************** System.out.println("新版版本名:"+parse.getVersionName()); System.out.println("本地版本名:"+localVersion); //对比版本号 if (parse.getVersionName().equals(localVersion)) { mNeedUpdate=false; Log.i(TAG, "版本号相同"); Message msg = new Message(); msg.what = UPDATA_NONEED; handler.sendMessage(msg); // LoginMain(); } else { mNeedUpdate=true; Log.i(TAG, "版本号不相同 "); Message msg = new Message(); msg.what = UPDATA_CLIENT; handler.sendMessage(msg); } } catch (Exception e) { Message msg = new Message(); msg.what = GET_UNDATAINFO_ERROR; handler.sendMessage(msg); e.printStackTrace(); } } } Handler handler = new Handler() { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); switch (msg.what) { case UPDATA_NONEED: Toast.makeText(mContext, "不需要更新", Toast.LENGTH_SHORT).show(); case UPDATA_CLIENT: //对话框通知用户升级程序 showUpdataDialog(); break; case GET_UNDATAINFO_ERROR: //服务器超时 Toast.makeText(mContext, "获取服务器更新信息失败", 1).show(); break; case DOWN_ERROR: //下载apk失败 Toast.makeText(mContext, "下载新版本失败", 1).show(); break; } } }; /* * * 弹出对话框通知用户更新程序 * * 弹出对话框的步骤: * 1.创建alertDialog的builder. * 2.要给builder设置属性, 对话框的内容,样式,按钮 * 3.通过builder 创建一个对话框 * 4.对话框show()出来 */ protected void showUpdataDialog() { AlertDialog.Builder builer = new Builder(mContext); builer.setTitle("版本升级"); //********************************************* //更新提示语 builer.setMessage(parse.getUpdateLog()); //******************************************************* //当点确定按钮时从服务器上下载 新的apk 然后安装 װ builer.setPositiveButton("立马更新", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Log.i(TAG, "下载apk,更新"); downLoadApk(); } }); builer.setNegativeButton("稍后再说", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub //do sth } }); AlertDialog dialog = builer.create(); dialog.show(); } /* * 从服务器中下载APK */ protected void downLoadApk() { final ProgressDialog pd; //进度条对话框 pd = new ProgressDialog(mContext); pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); pd.setMessage("正在下载更新"); pd.show(); new Thread(){ @Override public void run() { try { File file = DownLoadManager.getFileFromServer(parse.getDownloadUrl(), pd); sleep(3000); installApk(file); pd.dismiss(); //结束掉进度条对话框 } catch (Exception e) { Message msg = new Message(); msg.what = DOWN_ERROR; handler.sendMessage(msg); e.printStackTrace(); } }}.start(); } //安装apk protected void installApk(File file) { Intent intent = new Intent(); //执行动作 intent.setAction(Intent.ACTION_VIEW); //执行的数据类型 intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); mContext.startActivity(intent); } public static String Url; public static String getUrl(){ return Url; } /** * 判断SD卡是什么状态进行下载 * @author * @date */ public static class DownLoadManager { public static File getFileFromServer(String path, ProgressDialog pd) { //如果相等的话表示当前的sdcard挂载在手机上并且是可用的 if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ URL url = null; try { url = new URL(path); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } HttpURLConnection conn = null; try { conn = (HttpURLConnection) url.openConnection(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } conn.setConnectTimeout(5000); //获取到文件的大小 pd.setMax(conn.getContentLength()); InputStream is = null; try { is = conn.getInputStream(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } File file = new File(Environment.getExternalStorageDirectory(), "updata.apk"); FileOutputStream fos = null; try { fos = new FileOutputStream(file); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } BufferedInputStream bis = new BufferedInputStream(is); byte[] buffer = new byte[1024]; int len ; int total=0; try { while((len =bis.read(buffer))!=-1){ fos.write(buffer, 0, len); total+= len; //获取当前下载量 pd.setProgress(total); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { fos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { bis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { is.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return file; } else{ return null; } } } }
上面的代码中我们需要用到获取到信息之后进行解析,这里我用的纸xml:
/** * 解析获取到输入流 * @param inputStream * @return */ public static Update parse(InputStream inputStream){ Update update = null; //获得XmlPullParser解析器 XmlPullParser xmlParser = Xml.newPullParser(); try { xmlParser.setInput(inputStream, UTF8); //获得解析到的事件类别,这里有开始文档,结束文档,开始标签,结束标签,文本等等事件。 int evtType=xmlParser.getEventType(); //一直循环,直到文档结束 while(evtType!=XmlPullParser.END_DOCUMENT){ String tag = xmlParser.getName(); switch(evtType){ case XmlPullParser.START_TAG: //通知信息 if(tag.equalsIgnoreCase("android")) { update = new Update(); } else if(update != null) { if(tag.equalsIgnoreCase("versionCode")) { //字符转换整数 update.setVersionCode(toInt(xmlParser.nextText(),0)); } else if(tag.equalsIgnoreCase("versionName")) { update.setVersionName(xmlParser.nextText()); } else if(tag.equalsIgnoreCase("downloadUrl")) { update.setDownloadUrl(xmlParser.nextText()); } else if(tag.equalsIgnoreCase("updateLog")) { update.setUpdateLog(xmlParser.nextText()); } } break; case XmlPullParser.END_TAG: break; } //如果xml没有结束,则导航到下一个节点 evtType=xmlParser.next(); } } catch (XmlPullParserException e) { e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { inputStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return update; } /** * 字符串转整数 * @param str * @param defValue * @return */ public static int toInt(String str, int defValue) { try{ return Integer.parseInt(str); }catch(Exception e){} return defValue; }
不要忘记了要写相应的bean类:
/** * 应用程序更新实体类 * @author * @date */ @SuppressWarnings("serial") public class Update implements Serializable{ public final static String UTF8 = "UTF-8"; public final static String NODE_ROOT = "oschina"; private int versionCode; private String versionName; private String downloadUrl; private String updateLog; public int getVersionCode() { return versionCode; } public void setVersionCode(int versionCode) { this.versionCode = versionCode; } public String getVersionName() { return versionName; } public void setVersionName(String versionName) { this.versionName = versionName; } public String getDownloadUrl() { return downloadUrl; } public void setDownloadUrl(String downloadUrl) { this.downloadUrl = downloadUrl; } public String getUpdateLog() { return updateLog; } public void setUpdateLog(String updateLog) { this.updateLog = updateLog; }
然后我们调用这个就可以了
注意上下文
UpdateVersionutil.getUpdataManger(this).startUpdate();
效果展示:
更新完成!!!
相关文章推荐
- XML 与 JSON 优劣对比
- As3.0 xml + Loader应用代码
- 网马生成器 MS Internet Explorer XML Parsing Buffer Overflow Exploit (vista) 0day
- ext读取两种结构的xml的代码
- 实例解析Ruby程序中调用REXML来解析XML格式数据的用法
- Ruby中XML格式数据处理库REXML的使用方法指南
- C#中如何使用 XmlReader 读取XML文件
- C#针对xml基本操作及保存配置文件应用实例
- Ruby使用REXML库来解析xml格式数据的方法
- Ruby程序中创建和解析XML文件的方法
- Ruby的XML格式数据解析库Nokogiri的使用进阶
- asp下查询xml的实现代码
- sqlserver FOR XML PATH 语句的应用
- 使用sp_xml_preparedocument处理XML文档的方法
- EBS xml publisher中文乱码问题及解决办法
- C#中的Linq to Xml详解
- C#代码操作XML进行增、删、改操作
- C#操作XML文件实例汇总
- C# XML序列化方法及常用特性总结分析