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

最新文章

  1. js倒计时代码 适合于促销-倒计时代码
  2. 数据库优化实践【MS SQL优化开篇】
  3. 结合Domino打造全功能的Grid
  4. Java 多线程(2)-Executor
  5. MMDrawerController第三方库的使用(根据导航item+滚动条progressView实现的手势滑动切换视图的)
  6. [原创]DELPHI木马DIY之生成服务端
  7. 商户怎样选择商业wifi进行移动营销
  8. iOS:处理XML文件
  9. 130831组队赛-Regionals 2011, Asia - Kuala Lumpur
  10. xp硬盘安装Fedora14 过程记录及心得体会(fedora14 live版本680M 和fedora14 DVD版本3.2G的选择)
  11. PHP的几种排序算法的比较
  12. bzoj 1264: [AHOI2006]基因匹配Match (树状数组优化dp)
  13. 20170811 JQuery基础知识学习记录(一)
  14. 【转载】Layered Window(分层窗体,透明窗体)
  15. k8s kubectl edit 方式修改 nodeport 的端口
  16. [Algorithm] Inorder Successor in a binary search tree
  17. 菜鸟教程之工具使用(一)——Git的基本使用
  18. Python性能优化:PyPy、Numba 与 Cython。PyPy的安装及对应pip的安装
  19. 《C++ Primer Plus》学习笔记——C++程序创建到运行的整个过程
  20. 修改element内部样式的两种方式

热门文章

  1. ADT-bundle
  2. 解决Windows时间同步失败问题!系统时间同步设置!
  3. E3-1230和E3-1230 V2有多神?
  4. [置顶] 2013 Multi-University Training Contest 8
  5. How Tomcat Works(十五)
  6. C语言的struct/union字节对齐
  7. android ExpandAbleListView控件
  8. MFC中OnDraw()和OnPaint()的区别[转]
  9. 栈的应用-四则表达式(C#代码实现)
  10. thinkphp 3+ 观后详解 (3)