------- 源自梦想、永远是你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事业的好友、只是勇敢地说出我学到! ----------