zoukankan      html  css  js  c++  java
  • Android小项目之四 自动更新检查的逻辑

    ------- 源自梦想永远是你IT事业的好友、只是勇敢地说出我学到! ----------

    按惯例,写在前面的:可能在学习Android的过程中,大家会和我一样,学习过大量的基础知识,很多的知识点也都能说出了123来,但是这些孤立的点终究显得太零散了,因此,我想从今天开始,以最经典的手机安全卫士项目为例,自己锻炼一下,也是想和大家交流交流,希望大家都能给出见解,共同进步。


    四、自动更新检查的逻辑


    3个软件:everything、size、color(GBR需转换成RGB)

    版本的检测
    会弹出对话框:最新版本的版本号,新版本的描述信息,是(下载路径)、否

    1.新版本,在服务器端创建出来(可在Tomcat):
    写一个update.xml文件,代码如下:

    			<?xml version="1.0" encoding="UTF-8"?>
    			<infos>
    				<version>2.0</version>
    				<description>最新版手机卫士,坚决为您的手机服务,快下载吧,手机杀毒送月饼,下载就开始啦!!</description>
    				<apkurl>http://192.168.1.206/phonesafe2.0.apk</apkurl>
    			</infos>


    开启tomcat服务器,检验xml文件是否能打开。
    2.自动更新的逻辑:
    1连接服务器去读取服务器的配置文件
    2比对客户端和服务器端的版本,看是否相同
    若相同,进入应用程序的主UI
    若不相同,转3
    3升级提醒对话框,看用户是否选择升级?
    若否,进入应用程序的主UI
    若是,下载新版本替换安装,转1

    3.连接服务器,检查更新信息
    联网权限:Internet
    在values文件夹中单独创建一个config.xml文件,不写死路径,并在其中
    增加服务器路径serverurl的String值为http://localhost/Android/update.xml

    checkVersionTask()方法(在新线程中检查更新信息)
    new Thread(){public void run(){...}}.start();
    URL构造函数
    连接网络、设置请求方式和超时时间,当响应码为200时,联网成功,否则出错,用Message给出出错信息,使用Handler()获取信息
    定义一个Message:
    Message msg =Message.obtain();	//Message类

    				msg.what = SERVER_ERROR;
    				msg.what = URL_ERROR;
    				msg.what = NETOWRK_ERROR;

    				protected static final int SERVER_ERROR = 0;
    				protected static final int URL_ERROR = 1;
    				protected static final int NETOWRK_ERROR = 2;




    若没有产生异常的话,则走code == 200:
    获取服务器中的输入流,也就是xml文件:

    解析xml文件:
    属于一个业务方法,建立一个包:com.dondong.phonesafe.engine
    在这个包中建立一个业务类(UpdateInfoParser),类里面有一个方法:getUpdateInfo(InputStream is),
    返回的是UpdateInfo的bean类对象,即返回解析后的更新信息。新建一个UpdateInfo类(bean类),放在domain包下。
    类中有version、description、apkurl三个属性.
    具体代码:
    						public class UpdateInfo {
    							private String version;
    							private String description;
    							private String apkurl;
    							public String getVersion() {
    								return version;
    							}
    							public void setVersion(String version) {
    								this.verison = version;
    							}
    							public String getDescription() {
    								return description;
    							}
    							public void setDescription(String description) {
    								this.description = description;
    							}
    							public String getApkurl() {
    								return apkurl;
    							}
    							public void setApkurl(String apkurl) {
    								this.apkurl = apkurl;
    							}
    						}	



    业务类(UpdateInfoParser)具体代码:
    					public class UpdateInfoParser {
    						
    						/**
    						 * 解析xml文件,返回更新的信息
    						 * @param is	代表xml文件的输入流
    						 * @return	null 表示解析失败,否则返回UpdateInfo对象
    						 */
    						public static UpdateInfo getUpdateInfo(InputStream is){		//这个方法没有用到什么类的成员变量,加static,效率更高些
    							try {
    								XmlPullParser parser = Xml.newPullParser();
    								parser.setInput(is, "utf-8");
    								
    								//getEventType()方法Returns the type of the current event (START_TAG, END_TAG, TEXT, etc.)
    								int type = parser.getEventType(); 
    								UpdateInfo updateInfo = new UpdateInfo();
    								while(type != XmlPullParser.END_DOCUMENT){
    									if(type == XmlPullParser.START_TAG){
    										if("version".equals(parser.getName())){
    											/*
    											 * nextText()方法:
    											 * If current event is START_TAG then 
    											 * if next element is TEXT then element content is returned 
    											 * or if next event is END_TAG then empty string is returned, 
    											 * otherwise exception is thrown.
    											 * After calling this function successfully parser will be positioned on END_TAG. 
    											 */
    											String version = parser.nextText();
    											updateInfo.setVersion(version);
    										}else if("description".equals(parser.getName())){
    											String description = parser.nextText();
    											updateInfo.setDescription(description);
    										}else if("apkurl".equals(parser.getName())){
    											String apkurl = parser.nextText();
    											updateInfo.setApkurl(apkurl);
    										}
    									}
    									type = parser.next();
    								}
    								is.close();
    								return updateInfo;
    							} catch (Exception e) {
    								e.printStackTrace();
    								return null;
    							}
    						}
    					}





    那么什么时候发这个msg呢?try...catch一定会走finally,我们就在finally语句中发送信息:
    handler.sendmessage(msg);


    具体代码:
    						private void checkVersionTask() {
    							new Thread(){
    								@Override
    								public void run() {
    									Message msg =Message.obtain();
    									try {
    										URL url = new URL(getString(R.string.serverurl));	//获取服务器链接url
    										HttpURLConnection conn = (HttpURLConnection) url.openConnection();	//链接网络
    										conn.setRequestMethod("GET");	//设置请求方式
    										conn.setConnectTimeout(5000);	//设置连接超时时限
    										
    										int code = conn.getResponseCode();	//获取响应码,只有在响应码为200时才连接成功
    										if(code == 200){
    											//请求成功
    										}else{
    											//请求失败
    											msg.what = SERVER_ERROR;
    										}
    									}catch (MalformedURLException e) {  //因为MalformedURLException继承了IOException
    										e.printStackTrace();
    										//url错误:This exception is thrown when a program attempts to create an URL from an incorrect specification.
    										msg.what = URL_ERROR;
    									} catch (IOException e) {	//若IOException在MalformedURLException前,则MalformedURLException读不到
    										e.printStackTrace();
    										//网络连接错误
    										msg.what = NETOWRK_ERROR;
    									}finally{
    										handler.sendMessage(msg); //发送后handleMessage(Message msg)就会得到msg
    									}
    								};
    								
    							}.start();
    						}


    这时候handleMessage(Message msg)就可以获得msg,然后我们经过switch判断是那种错误,并Toast错误信息。
    具体代码:
    						private Handler handler = new Handler(){
    
    
    							@Override
    							public void handleMessage(Message msg) {	//得到msg后,就可以做判断了
    								switch (msg.what){
    								case SERVER_ERROR:
    									Toast.makeText(getApplicationContext(), "服务器错误。。。", 0).show();
    									break;
    								case URL_ERROR:
    									Toast.makeText(getApplicationContext(), "更新的URL错误。。。", 0).show();
    									break;
    								case NETOWRK_ERROR:
    									Toast.makeText(getApplicationContext(), "网络错误,请检查连接。。。", 0).show();
    									break;
    								}
    							}
    							
    						};


    若code=200,即请求成功,则
    							//解析成功,则检查版本是否一样,在主线程中执行
    							msg.what = PARSE_XML_SUCCESS;

    并在Hanlder中:
    						case PARSE_XML_SUCCESS:
    							checkVersion();
    							break;

    下面建立一个checkVersion()方法,用于检查客户端与服务端的版本是否相同。
    具体代码:
    						/**
    						 * 对比客户端和服务端的版本是否一样
    						 */
    						protected void checkVersion() {
    							//分别得到客户端和服务端的版本
    							if(getVersion().equals(updateInfo.getVersion())){	//如果版本号相同,则直接进入主界面
    								
    							}else{		//否则,给出升级提醒对话框
    								AlertDialog.Builder builder = new Builder(this);	//创建对话框
    								builder.setTitle("更新提醒:");
    								builder.setMessage(updateInfo.getDescription());
    								builder.setPositiveButton("立即更新", new OnClickListener(){
    
    
    									@Override
    									public void onClick(DialogInterface dialog, int which) {
    										//用户选择更新,则替换安装
    										Log.i(TAG, "版本号不同,下载新的apk,替换安装");
    									}
    								});
    								builder.setNegativeButton("下次再说", new OnClickListener(){
    									
    									@Override
    									public void onClick(DialogInterface dialog, int which) {
    										//用户选择不更新,则直接进入主界面
    										loadMainUI();		
    									}
    								});
    								builder.show();
    							}
    						}


    这里需要做一个演示的主界面(HomeActivity)。

    由于上述各种情况都需要进入主界面,所以在这里抽取成一个方法:loadMainUI()
    具体代码:
    					/**
    					 * 进入主界面
    					 */
    					private void loadMainUI() {
    						Intent intent = new Intent(SplashActivity.this,HomeActivity.class);
    						startActivity(intent);
    						finish();	//关闭当前界面
    					}


    ------- 源自梦想永远是你IT事业的好友、只是勇敢地说出我学到! ----------
    Le王冬冬 博客分享地址: http://www.cnblogs.com/dongdong230/ 每个人都应做一天攻城狮
  • 相关阅读:
    SQL Server 阻止了对组件 'Ole Automation Procedures' 的 过程'sys.sp_OACreate' 的访问
    谷歌浏览器扩展程序manifest.json参数详解
    获取天气api
    UVA 10385 Duathlon
    UVA 10668 Expanding Rods
    UVALIVE 3891 The Teacher's Side of Math
    UVA 11149 Power of Matrix
    UVA 10655 Contemplation! Algebra
    UVA 11210 Chinese Mahjong
    UVA 11384 Help is needed for Dexter
  • 原文地址:https://www.cnblogs.com/dongdong230/p/4183100.html
Copyright © 2011-2022 走看看