2、更新提示
来源:互联网 发布:养哈士奇 知乎 编辑:程序博客网 时间:2024/06/06 21:38
在进入splash界面的时候后台启动线程,联网检查是否有更新版本可用,如果没有新版本则splash界面显示后进入主界面,否则显示升级对话框让用户选择是否进行更新。
1、权限设置
因为需要联网,所以AndroidManifest.xml文件需要添加访问网络的权限:
<uses-permission android:name="android.permission.INTERNET" />本人就是由于忘记添加该权限,在后面的运行中出现错误:
12-23 03:24:26.999 1528-1541/com.example.mobilesafe W/System.err﹕ java.net.SocketException: socket failed: EACCES (Permission denied)12-23 03:24:26.999 1528-1541/com.example.mobilesafe W/System.err﹕ at libcore.io.IoBridge.socket(IoBridge.java:576)12-23 03:24:27.009 1528-1541/com.example.mobilesafe W/System.err﹕ at java.net.PlainSocketImpl.create(PlainSocketImpl.java:201)12-23 03:24:27.009 1528-1541/com.example.mobilesafe W/System.err﹕ at java.net.Socket.checkOpenAndCreate(Socket.java:664)12-23 03:24:27.009 1528-1541/com.example.mobilesafe W/System.err﹕ at java.net.Socket.connect(Socket.java:808)12-23 03:24:27.009 1528-1541/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.Platform.connectSocket(Platform.java:131)12-23 03:24:27.009 1528-1541/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.Connection.connect(Connection.java:101)12-23 03:24:27.009 1528-1541/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294)12-23 03:24:27.019 1528-1541/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)12-23 03:24:27.019 1528-1541/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)12-23 03:24:27.029 1528-1541/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)12-23 03:24:27.029 1528-1541/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296)12-23 03:24:27.029 1528-1541/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:503)12-23 03:24:27.029 1528-1541/com.example.mobilesafe W/System.err﹕ at com.example.mobilesafe.SplashActivity$checkUpdate.run(SplashActivity.java:146)12-23 03:24:27.029 1528-1541/com.example.mobilesafe W/System.err﹕ at java.lang.Thread.run(Thread.java:841)12-23 03:24:27.029 1528-1541/com.example.mobilesafe W/System.err﹕ Caused by: libcore.io.ErrnoException: socket failed: EACCES (Permission denied)12-23 03:24:27.079 1528-1541/com.example.mobilesafe W/System.err﹕ at libcore.io.Posix.socket(Native Method)12-23 03:24:27.079 1528-1541/com.example.mobilesafe W/System.err﹕ at libcore.io.BlockGuardOs.socket(BlockGuardOs.java:181)12-23 03:24:27.079 1528-1541/com.example.mobilesafe W/System.err﹕ at libcore.io.IoBridge.socket(IoBridge.java:561)12-23 03:24:27.079 1528-1541/com.example.mobilesafe W/System.err﹕ ... 13 more
2、服务器更新配置
这里使用wampserver搭建本地服务器,更新配置文件放在X:\wamp\www\app\mobilesafe目录下,配置内容为:
<?xml version="1.0" encoding="utf-8"?><info> <ver>2.0</ver> <desc>亲,有新版本了,赶紧更新吧!</desc> <apkurl>http://10.0.2.2/app/mobilesafe/mobilesafe.apk</apkurl> </info>
因为服务器地址属于常量字符串,这里添加到strings.xml中:
<?xml version="1.0" encoding="utf-8"?><resources> <string name="app_name">mobilesafe</string> <string name="serverurl">http://10.0.2.2/app/mobilesafe/update.xml</string></resources>
这里是使用本机进行测试的,注意Android访问本机的IP地址是:10.0.2.2,如果使用127.0.0.1会出现如下错误:
12-23 03:29:15.189 1573-1586/com.example.mobilesafe W/System.err﹕ java.net.ConnectException: failed to connect to /127.0.0.1 (port 80) after 5000ms: isConnected failed: ECONNREFUSED (Connection refused)12-23 03:29:15.189 1573-1586/com.example.mobilesafe W/System.err﹕ at libcore.io.IoBridge.isConnected(IoBridge.java:223)12-23 03:29:15.189 1573-1586/com.example.mobilesafe W/System.err﹕ at libcore.io.IoBridge.connectErrno(IoBridge.java:161)12-23 03:29:15.199 1573-1586/com.example.mobilesafe W/System.err﹕ at libcore.io.IoBridge.connect(IoBridge.java:112)12-23 03:29:15.199 1573-1586/com.example.mobilesafe W/System.err﹕ at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)12-23 03:29:15.199 1573-1586/com.example.mobilesafe W/System.err﹕ at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)12-23 03:29:15.199 1573-1586/com.example.mobilesafe W/System.err﹕ at java.net.Socket.connect(Socket.java:843)12-23 03:29:15.199 1573-1586/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.Platform.connectSocket(Platform.java:131)12-23 03:29:15.199 1573-1586/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.Connection.connect(Connection.java:101)12-23 03:29:15.199 1573-1586/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294)12-23 03:29:15.199 1573-1586/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)12-23 03:29:15.199 1573-1586/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)12-23 03:29:15.199 1573-1586/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)12-23 03:29:15.199 1573-1586/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296)12-23 03:29:15.199 1573-1586/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:503)12-23 03:29:15.199 1573-1586/com.example.mobilesafe W/System.err﹕ at com.example.mobilesafe.SplashActivity$checkUpdate.run(SplashActivity.java:146)12-23 03:29:15.199 1573-1586/com.example.mobilesafe W/System.err﹕ at java.lang.Thread.run(Thread.java:841)12-23 03:29:15.199 1573-1586/com.example.mobilesafe W/System.err﹕ Caused by: libcore.io.ErrnoException: isConnected failed: ECONNREFUSED (Connection refused)12-23 03:29:15.199 1573-1586/com.example.mobilesafe W/System.err﹕ at libcore.io.IoBridge.isConnected(IoBridge.java:208)12-23 03:29:15.199 1573-1586/com.example.mobilesafe W/System.err﹕ ... 15 more
相关参考:http://www.myexception.cn/operating-system/754403.html
4、更新信息结构体
按照服务器更新配置,更新信息共有三个字段:版本号,更新提示文本,apk下载地址:
package com.example.mobilesafe;/** * Created by sing on 13-12-23. */public class UpdateInfo { //服务器端版本号 private String version; //服务器端升级提示 private String desc; //服务器端apk下载地址 private String apkurl; public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getApkurl() { return apkurl; } public void setApkurl(String apkurl) { this.apkurl = apkurl; }}
5、XML更新配置解析类
注意XmlPullParser解析XML的nextText存在bug:
12-23 03:46:07.439 1729-1748/com.example.mobilesafe W/System.err﹕ org.xmlpull.v1.XmlPullParserException: END_TAG expected (position:START_TAG <version>@3:14 in java.io.InputStreamReader@b2ef2718)12-23 03:46:07.449 1729-1748/com.example.mobilesafe W/System.err﹕ at org.kxml2.io.KXmlParser.nextText(KXmlParser.java:2077)12-23 03:46:07.479 1729-1748/com.example.mobilesafe W/System.err﹕ at com.example.mobilesafe.UpdateInfoParser.getUpdateInfo(UpdateInfoParser.java:33)12-23 03:46:07.479 1729-1748/com.example.mobilesafe W/System.err﹕ at com.example.mobilesafe.SplashActivity$checkUpdate.run(SplashActivity.java:153)12-23 03:46:07.499 1729-1748/com.example.mobilesafe W/System.err﹕ at java.lang.Thread.run(Thread.java:841)
参考解决:http://blog.csdn.net/nxh_love/article/details/7109762,
这里使用的方法是:当前的位置不是END_TAG时,在调用nextText()之后再调用nextTag(),完整代码:
package com.example.mobilesafe;import android.util.Xml;import org.xmlpull.v1.XmlPullParser;import org.xmlpull.v1.XmlPullParserException;import java.io.IOException;import java.io.InputStream;/** * Created by sing on 13-12-23. */public class UpdateInfoParser { /** *解析一个utf-8格式的xml输入流,返回一个UpdateInfo对象 * XmlPullParser解析bug参考解决:http://blog.csdn.net/nxh_love/article/details/7109762 * @param is * @return UpdateInfo对象 * @throws XmlPullParserException * @throws IOException */ public static UpdateInfo getUpdateInfo(InputStream is) throws XmlPullParserException, IOException { UpdateInfo info = new UpdateInfo(); //获取一个pull解析的实例 XmlPullParser parser = Xml.newPullParser(); //解析xml parser.setInput(is, "UTF-8"); parser.nextTag(); int type = parser.getEventType(); while (parser.nextTag() == XmlPullParser.START_TAG) { String tag = parser.getName(); String text = parser.nextText(); if (parser.getEventType() != XmlPullParser.END_TAG) { parser.nextTag(); } if (tag.equals("ver")) { info.setVersion(text); } else if (tag.equals("desc")) { info.setDesc(text); } else if (tag.equals("apkurl")) { info.setApkurl(text); } } return info; }}
6、SplashActivity::OnCreate创建检查更新的线程
//检查更新 new Thread(new checkUpdate()) { }.start();
/** * 检查更新 */ private class checkUpdate implements Runnable { public void run() { long startTime = System.currentTimeMillis(); long endTime = startTime; Message msg = Message.obtain(); try { //获取服务器更新地址 String serverurl = getResources().getString(R.string.serverurl); URL url = new URL(serverurl); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); int code = conn.getResponseCode(); if (code == 200) { //success InputStream is = conn.getInputStream(); //解析出更新信息 updateinfo = UpdateInfoParser.getUpdateInfo(is); endTime = System.currentTimeMillis(); long time = endTime - startTime; if (time < 2000) { try { Thread.sleep(2000 - time); } catch (InterruptedException e) { e.printStackTrace(); } } msg.what = GET_INFO_SUCCESS; handler.sendMessage(msg); } else { //服务器错误 msg.what = SERVER_ERROR; handler.sendMessage(msg); endTime = System.currentTimeMillis(); long time = endTime - startTime; if (time < 2000) { try { Thread.sleep(2000 - time); } catch (InterruptedException e) { e.printStackTrace(); } } } } catch (MalformedURLException e) { msg.what = SERVER_URL_ERROR; handler.sendMessage(msg); e.printStackTrace(); } catch (ProtocolException e) { msg.what = PROTOCOL_ERROR; handler.sendMessage(msg); e.printStackTrace(); } catch (IOException e) { msg.what = IO_ERROR; handler.sendMessage(msg); e.printStackTrace(); } catch (XmlPullParserException e) { msg.what = XML_PARSER_ERROR; handler.sendMessage(msg); e.printStackTrace(); } catch (Exception e) { msg.what = UNKNOWN_ERROR; handler.sendMessage(msg); e.printStackTrace(); } } }
7、添加消息处理函数,在界面中统一显示
/** * 消息处理器 */ private Handler handler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case GET_INFO_SUCCESS: String serverVersion = updateinfo.getVersion(); String currentVersion = getVersion(); if (currentVersion.equals(serverVersion)) { Log.i(TAG, "版本号相同无需升级,直接进入主界面"); }else { Log.i(TAG, "版本号不同需升级,显示升级对话框"); showUpdateDialog(); } break; case SERVER_ERROR: Toast.makeText(getApplicationContext(), "服务器内部异常", 1).show(); break; case SERVER_URL_ERROR: Toast.makeText(getApplicationContext(), "服务器路径错误", 1).show(); break; case PROTOCOL_ERROR: Toast.makeText(getApplicationContext(), "协议错误", 1).show(); break; case XML_PARSER_ERROR: Toast.makeText(getApplicationContext(), "XML解析错误", 1).show(); break; case IO_ERROR: Toast.makeText(getApplicationContext(), "I/O错误", 1).show(); break; case UNKNOWN_ERROR: Toast.makeText(getApplicationContext(), "未知错误", 1).show(); break; } } };
8、当本地版本号与服务器端获取的版本号不同时提示升级对话框
/** * 显示升级提示对话框 */ protected void showUpdateDialog() { //创建对话框构造器 AlertDialog.Builder builder = new AlertDialog.Builder(this); //设置对话框图标 builder.setIcon(getResources().getDrawable(R.drawable.notification)); //设置对话框标题 builder.setTitle("升级提示"); //设置更新信息为对话框提示内容 builder.setMessage(updateinfo.getDesc()); //设置升级按钮及响应事件 builder.setPositiveButton("升级", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); //设置取消按钮及响应事件 builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); //创建并显示对话框 builder.create().show(); }
9、SplashActivity完整代码
package com.example.mobilesafe;import android.app.Activity;import android.app.AlertDialog;import android.content.DialogInterface;import android.content.pm.PackageInfo;import android.content.pm.PackageManager;import android.os.Bundle;import android.os.Message;import android.util.Log;import android.view.Window;import android.view.WindowManager;import android.view.animation.AlphaAnimation;import android.widget.RelativeLayout;import android.widget.TextView;import android.widget.Toast;import org.xmlpull.v1.XmlPullParserException;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.ProtocolException;import java.net.URL;import android.os.Handler;public class SplashActivity extends Activity { //常量定义 public static final int UNKNOWN_ERROR = 99; public static final int GET_INFO_SUCCESS = 100; public static final int SERVER_ERROR = 101; public static final int SERVER_URL_ERROR = 102; public static final int PROTOCOL_ERROR = 103; public static final int IO_ERROR = 104; public static final int XML_PARSER_ERROR = 105; public static final String TAG = "SplashActivity"; //获取的服务器端的更新信息 UpdateInfo updateinfo; //显示版本号的tv控件 private TextView tv_splash_version; //布局控件 private RelativeLayout r1_splash; /** * Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //设置无标题栏 requestWindowFeature(Window.FEATURE_NO_TITLE); //设置全屏模式 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //设置局部,显示版本号 setContentView(R.layout.activity_splash); r1_splash = (RelativeLayout)findViewById(R.id.r1_splash); tv_splash_version = (TextView)findViewById(R.id.tv_splash_version); tv_splash_version.setText("版本号:" + getVersion()); //显示渐进动画 AlphaAnimation aa = new AlphaAnimation(0.3f, 1.0f); aa.setDuration(2000); r1_splash.startAnimation(aa); //检查更新 new Thread(new checkUpdate()) { }.start(); } //获取当前应用程序的版本号 private String getVersion() { String version = ""; //获取系统包管理器 PackageManager pm = this.getPackageManager(); try { PackageInfo info = pm.getPackageInfo(getPackageName(), 0); version = info.versionName; } catch (Exception e) { e.printStackTrace(); } return version; } /** * 消息处理器 */ private Handler handler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case GET_INFO_SUCCESS: String serverVersion = updateinfo.getVersion(); String currentVersion = getVersion(); if (currentVersion.equals(serverVersion)) { Log.i(TAG, "版本号相同无需升级,直接进入主界面"); }else { Log.i(TAG, "版本号不同需升级,显示升级对话框"); showUpdateDialog(); } break; case SERVER_ERROR: Toast.makeText(getApplicationContext(), "服务器内部异常", 1).show(); break; case SERVER_URL_ERROR: Toast.makeText(getApplicationContext(), "服务器路径错误", 1).show(); break; case PROTOCOL_ERROR: Toast.makeText(getApplicationContext(), "协议错误", 1).show(); break; case XML_PARSER_ERROR: Toast.makeText(getApplicationContext(), "XML解析错误", 1).show(); break; case IO_ERROR: Toast.makeText(getApplicationContext(), "I/O错误", 1).show(); break; case UNKNOWN_ERROR: Toast.makeText(getApplicationContext(), "未知错误", 1).show(); break; } } }; /** * 检查更新 */ private class checkUpdate implements Runnable { public void run() { long startTime = System.currentTimeMillis(); long endTime = startTime; Message msg = Message.obtain(); try { //获取服务器更新地址 String serverurl = getResources().getString(R.string.serverurl); URL url = new URL(serverurl); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); int code = conn.getResponseCode(); if (code == 200) { //success InputStream is = conn.getInputStream(); //解析出更新信息 updateinfo = UpdateInfoParser.getUpdateInfo(is); endTime = System.currentTimeMillis(); long time = endTime - startTime; if (time < 2000) { try { Thread.sleep(2000 - time); } catch (InterruptedException e) { e.printStackTrace(); } } msg.what = GET_INFO_SUCCESS; handler.sendMessage(msg); } else { //服务器错误 msg.what = SERVER_ERROR; handler.sendMessage(msg); endTime = System.currentTimeMillis(); long time = endTime - startTime; if (time < 2000) { try { Thread.sleep(2000 - time); } catch (InterruptedException e) { e.printStackTrace(); } } } } catch (MalformedURLException e) { msg.what = SERVER_URL_ERROR; handler.sendMessage(msg); e.printStackTrace(); } catch (ProtocolException e) { msg.what = PROTOCOL_ERROR; handler.sendMessage(msg); e.printStackTrace(); } catch (IOException e) { msg.what = IO_ERROR; handler.sendMessage(msg); e.printStackTrace(); } catch (XmlPullParserException e) { msg.what = XML_PARSER_ERROR; handler.sendMessage(msg); e.printStackTrace(); } catch (Exception e) { msg.what = UNKNOWN_ERROR; handler.sendMessage(msg); e.printStackTrace(); } } } /** * 显示升级提示对话框 */ protected void showUpdateDialog() { //创建对话框构造器 AlertDialog.Builder builder = new AlertDialog.Builder(this); //设置对话框图标 builder.setIcon(getResources().getDrawable(R.drawable.notification)); //设置对话框标题 builder.setTitle("升级提示"); //设置更新信息为对话框提示内容 builder.setMessage(updateinfo.getDesc()); //设置升级按钮及响应事件 builder.setPositiveButton("升级", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); //设置取消按钮及响应事件 builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); //创建并显示对话框 builder.create().show(); }}
10、运行效果图
本地版本号与服务器版本号相同时直接进入主界面:
12-23 05:43:33.279 2125-2125/com.example.mobilesafe I/SplashActivity﹕ 版本号相同无需升级,直接进入主界面
本地版本号与服务器版本号不同时显示提示升级对话框:
12-23 05:44:37.349 2125-2125/com.example.mobilesafe I/SplashActivity﹕ 版本号不同需升级,显示升级对话框
0 0
- 2、更新提示
- Android提示版本更新
- Android提示版本更新
- Android提示版本更新
- Android版本更新提示
- iOS 版本更新提示
- apk提示版本更新
- 关闭Sublime更新提示
- Android提示版本更新
- Android提示版本更新
- iOS版本更新提示
- Android提示版本更新
- iOS版本更新提示
- android自动提示更新
- Android提示版本更新
- iOS APP更新提示
- androidstudio去掉更新提示
- Android提示版本更新
- Uboot移植
- There is no Action mapped for namespace / and action name"的错误
- ORCFile测试
- rails 中 Observers中别调用与直接调用函数的区别
- 循环方法创建完全二叉树
- 2、更新提示
- 数据库--数据库链接池--DBCP连接池配置参数说明
- 嵌入式 mysql_free_version出现长时间不操作会自动关闭连接解决方法(有代码)
- C#数据类型转换
- iOS学习之iOS沙盒(sandbox)机制和文件操作(一)
- Asio服务端连接管理,实现广播数据
- Windows8共享网络让手机上网
- HDU 2577 How to Type DP也可以模拟
- Android之数据库异步加载利器--Loaders