Android检测版本更新

一、准备

1.检测当前版本的信息AndroidManifest.xml-->manifest-->android:versionName。

2.从服务器获取版本号(版本号存在于xml文件中)并与当前检测到的版本进行匹配,如果不匹配,提示用户进行升级,如果匹配则进入程序主界面。

3.当提示用户进行版本升级时,如果用户点击了确定,系统将自动从服务器上下载并进行自动升级,如果点击取消将进入程序主界面。

二、效果图

Android版本更新_第1张图片Android版本更新_第2张图片Android版本更新_第3张图片Android版本更新_第4张图片

三、必要说明

服务器端存储apk文件,同时有version.xml文件便于比对更新。

<?xml version="1.0" encoding="utf-8"?>
<info>
<version>2.0</version>
<url>http://192.168.1.187:8080/mobilesafe.apk</url>
<description>检测到最新版本,请及时更新!</description>
<url_server>http://192.168.1.99/version.xml</url_server>
</info>

通过一个实体类获取上述信息。

package com.android;
public class UpdataInfo {
private String version;
private String url;
private String description;
private String url_server;
public String getUrl_server() {
return url_server;
}
public void setUrl_server(String url_server) {
this.url_server = url_server;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

apk和版本信息地址都放在服务器端的version.xml里比较方便,当然如果服务器端不变动,apk地址可以放在strings.xml里,不过版本号信息是新的,必须放在服务器端,xml地址放在strings.xml。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, VersionActivity!</string>
    <string name="app_name">Version</string>
    <string name="url_server">http://192.168.1.99/version.xml</string>
</resources>

不知道读者发现没有,笔者犯了个错误,那就是url_server地址必须放在本地,否则怎么读取version.xml,所以url_server不必在实体类和version里添加,毕竟是现需要version地址也就是url_server,才能够读取version。

三、代码实现

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
<Button 
    android:id="@+id/btn_getVersion"
    android:text="检查更新"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
</LinearLayout>
package com.android;
import java.io.InputStream;
import org.xmlpull.v1.XmlPullParser;
import android.util.Xml;
public class UpdataInfoParser {
public static UpdataInfo getUpdataInfo(InputStream is) throws Exception{
XmlPullParser  parser = Xml.newPullParser();  
parser.setInput(is, "utf-8");
int type = parser.getEventType();
UpdataInfo info = new UpdataInfo();
while(type != XmlPullParser.END_DOCUMENT ){
switch (type) {
case XmlPullParser.START_TAG:
if("version".equals(parser.getName())){
info.setVersion(parser.nextText());
}else if ("url".equals(parser.getName())){
info.setUrl(parser.nextText());
}else if ("description".equals(parser.getName())){
info.setDescription(parser.nextText());
}
break;
}
type = parser.next();
}
return info;
}
}
package com.android;
import java.io.File;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class VersionActivity extends Activity {
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 UpdataInfo info;
private String localVersion;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getVersion = (Button) findViewById(R.id.btn_getVersion);
getVersion.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
localVersion = getVersionName();
CheckVersionTask cv = new CheckVersionTask();
new Thread(cv).start();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
private String getVersionName() throws Exception {
//getPackageName()是你当前类的包名,0代表是获取版本信息  
PackageManager packageManager = getPackageManager();
PackageInfo packInfo = packageManager.getPackageInfo(getPackageName(),
0);
return packInfo.versionName;
}
public class CheckVersionTask implements Runnable {
InputStream is;
public void run() {
try {
String path = getResources().getString(R.string.url_server);
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET"); 
                int responseCode = conn.getResponseCode(); 
                if (responseCode == 200) { 
                    // 从服务器获得一个输入流 
                is = conn.getInputStream(); 
                } 
info = UpdataInfoParser.getUpdataInfo(is);
if (info.getVersion().equals(localVersion)) {
Log.i(TAG, "版本号相同");
Message msg = new Message();
msg.what = UPDATA_NONEED;
handler.sendMessage(msg);
// LoginMain();
} else {
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(getApplicationContext(), "不需要更新",
Toast.LENGTH_SHORT).show();
case UPDATA_CLIENT:
 //对话框通知用户升级程序   
showUpdataDialog();
break;
case GET_UNDATAINFO_ERROR:
//服务器超时   
            Toast.makeText(getApplicationContext(), "获取服务器更新信息失败", 1).show(); 
break;
case DOWN_ERROR:
//下载apk失败  
            Toast.makeText(getApplicationContext(), "下载新版本失败", 1).show(); 
break;
}
}
};
/* 
 *  
 * 弹出对话框通知用户更新程序  
 *  
 * 弹出对话框的步骤: 
 *  1.创建alertDialog的builder.   
 *  2.要给builder设置属性, 对话框的内容,样式,按钮 
 *  3.通过builder 创建一个对话框 
 *  4.对话框show()出来   
 */  
protected void showUpdataDialog() {
AlertDialog.Builder builer = new Builder(this);
builer.setTitle("版本升级");
builer.setMessage(info.getDescription());
 //当点确定按钮时从服务器上下载 新的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(this);  
    pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);  
    pd.setMessage("正在下载更新");  
    pd.show();  
    new Thread(){  
        @Override  
        public void run() {  
            try {  
                File file = DownLoadManager.getFileFromServer(info.getUrl(), 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");  
    startActivity(intent);  
}  
}
package com.android;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.ProgressDialog;
import android.os.Environment;
public class DownLoadManager {
public static File getFileFromServer(String path, ProgressDialog pd) throws Exception{
//如果相等的话表示当前的sdcard挂载在手机上并且是可用的
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
URL url = new URL(path);
HttpURLConnection conn =  (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
//获取到文件的大小 
pd.setMax(conn.getContentLength());
InputStream is = conn.getInputStream();
File file = new File(Environment.getExternalStorageDirectory(), "updata.apk");
FileOutputStream fos = new FileOutputStream(file);
BufferedInputStream bis = new BufferedInputStream(is);
byte[] buffer = new byte[1024];
int len ;
int total=0;
while((len =bis.read(buffer))!=-1){
fos.write(buffer, 0, len);
total+= len;
//获取当前下载量
pd.setProgress(total);
}
fos.close();
bis.close();
is.close();
return file;
}
else{
return null;
}
}
}
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

四、参考文献

http://blog.csdn.net/furongkang/article/details/6886526

作者: 张朋飞出处: http://www.cnblogs.com/hxsyl/本文版权归作者张朋飞所有,欢迎转载和商用,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.

更多相关文章

  1. 从源码看Android常用的数据结构 ( SDK23版本 ) ( 三 , Queue篇)
  2. 通过android代码获取android系统的imei、手机型号、手机品牌、an
  3. 安卓版本和Api Level
  4. Android 去掉运营商STK对话框提示
  5. 谷歌Android系统版本无序发展反噬产业链
  6. Android各版本对应的SDK版本
  7. 获取Android版本信息和电话信息
  8. 超过 50% 的 Android 设备依然运行 2.2 版本
  9. Android版本与Linux内核的关系

随机推荐

  1. Android(安卓)SDK Manager无法下载包的问
  2. Android网络连接判断与处理
  3. Android两种播放视频的方法(SurfaceView
  4. android adb常用命令整理
  5. Android(安卓)获得本机ip地址和MAC地址
  6. 使用Xutils的时候rg.apache.http.client.
  7. Android(安卓)ListView设置Item选中状态
  8. 《宅男的android开发指南》(翻译)--9
  9. Android点击左右按钮实现左右滑动页面切
  10. Android(安卓)activity的生命周期