在安卓开发过程中,很多时候再软件启动时需要检查进行更版本更新,在本文中,采取tomcat7.0作为服务器,进行相关版本的获取。
功能描述:软件启动时进行版本检查,检查到新版本时提示更新。
1、首先我们编写界面文件如下(activity_start):
package com.sw.xmk;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.json.JSONException;
import org.json.JSONObject;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.sw.xmk.utils.StreamUtil;
import com.sw.xmk.utils.ToastUtil;
import com.sw.xmk.R;
import com.sw.xmk.R.layout;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.text.style.UpdateAppearance;
import android.util.Log;
import android.view.Menu;
import android.view.Window;
import android.view.animation.AlphaAnimation;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
* @author Swxctx
*
*/
public class StartActivity extends Activity {
private TextView textView;
private TextView tv_version_name;
private int mLocalVersionCode;//本地的版本号
private String mVersionDes;
private String mDownloadUrl;
protected static final String tag="SplashActivity";
protected static final int UPDATE_VERSION = 100;
protected static final int ENTER_HOME = 101;
protected static final int URL_ERROR = 102;
protected static final int IO_ERROR = 103;
protected static final int JSON_ERROR = 104;
//handler为类的成员变量,对handler重新命名为mHandler
private Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case UPDATE_VERSION:
//弹出对话框,提示用户更新
showUpdateDialog();
break;
case ENTER_HOME:
//当接收到ENTER_HOME后,由splash界面进入应用程序主界面,activity跳转过程,封装到enterHome方法中
enterHome();//选中此方法,ctrl+1,选中第2个(在splash中创建)创建Activity的成员方法,去写此方法。
break;
case URL_ERROR:
//Toast.makeText(context, text, duration).show();
ToastUtil.show(StartActivity.this, "url异常");
enterHome();
break;
case IO_ERROR:
//Toast.makeText(context, text, duration).show();
ToastUtil.show(StartActivity.this, "读取异常");
enterHome();
break;
case JSON_ERROR:
ToastUtil.show(StartActivity.this, "json解析异常");
enterHome();
break;
}
}
};
private RelativeLayout rl_root;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_start);
//初始化UI
initUI();
//初始化数据
initData();
//初始化动画,(ctrl+1)创建此方法
initAnimation();
}
/**
* 添加淡入动画效果
*/
private void initAnimation() {
//Animation(2),它是抽象类,其有很多子类,选中它(ctrl+t)查看其子类,
//调用第2个构造方法,从一个透明度到另外一个透明度fromAlpha=0, toAlpha=1,由完全透明到完全不透明
AlphaAnimation alphaAnimation= new AlphaAnimation(0,1);
//选中AlphaAnimation(ctrl+1)生成对应的对象alphaAnimation
//设定时长
alphaAnimation.setDuration(3000);
rl_root.startAnimation(alphaAnimation);
}
//显示对话框操作
protected void showUpdateDialog() {
// TODO Auto-generated method stub
Builder builder = new AlertDialog.Builder(this);
//设置左上角图标
builder.setIcon(R.drawable.ic_launcher);
builder.setTitle("版本更新");
//设置描述内容
builder.setMessage(mVersionDes);
builder.setPositiveButton("立即更新", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
// 下载apk,apk的链接地址,downloadUrl
downloadApk(); //将其作为类的成员方法,在splashActivity中创建
}
});
//消极按钮
builder.setNegativeButton("稍后再说 ", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
// 取消对话框,进入主界面
enterHome();
}
});
//点击取消事件监听
builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
// 即使用户点击取消,也要进入应用程序主界面
enterHome();
dialog.dismiss();
}
});
builder.show();
}
protected void downloadApk() {
//apk下载链接地址,放置apk的所在路径
//1,判断sd卡是否可用,是否挂载在上面
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
//2,获取sd路径,拿到绝对路径。
String path = Environment.getExternalStorageDirectory().getAbsolutePath()
+File.separator+"SplashActivity.apk";
//3,发送请求,获取apk,并且放置到指定路径.
HttpUtils httpUtils = new HttpUtils();
//4,发送请求,传递参数(下载地址,下载应用放置位置),target参数是path路径
httpUtils.download(mDownloadUrl, path,new RequestCallBack() {
@Override
public void onSuccess(ResponseInfo responseInfo) {
// TODO Auto-generated method stub
// 下载成功(下载过后的放置在sd卡中的apk)
Log.i(tag, "下载成功");
File file = responseInfo.result;
//提示用户安装,作为类的成员方法
installApk(file);
}
// 下载失败
@Override
public void onFailure(HttpException arg0, String arg1) {
// TODO Auto-generated method stub
Log.i(tag, "下载失败");
}
//刚刚开始下载的方法(Alt+/)
@Override
public void onStart() {
Log.i(tag, "刚刚开始下载");
super.onStart();
}
//下载过程中的方法,进度条的改变(Alt+/),total总数,current当前的,isUploading是否正在下载
@Override
public void onLoading(long total, long current, boolean isUploading) {
Log.i(tag, "下载中.......");
Log.i(tag, "total = "+total);
Log.i(tag, "current = "+current);
super.onLoading(total, current, isUploading);
}
});
}
}
protected void installApk(File file) {
Intent intent =new Intent("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
//startActivity(intent);
startActivityForResult(intent,0);
}
//开启一个activity后,返回结果调用的方法
@Override
//一旦后面一个界面结束回到前一个界面,就会去调用前一个界面的onActivityResult方法,只写onActivityResult回车,所有内容都包含了。
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
enterHome(); //只需要跳转到HomeActivity方法
super.onActivityResult(requestCode, resultCode, data);
}
/**
* 进入应用程序主界面
*/
protected void enterHome() {
// TODO Auto-generated method stub
Intent intent = new Intent(this,LoginActivity.class);
startActivity(intent);
//在开启一个新的界面后,将导航界面关闭(导航界面只可见一次)
finish();
}
private void initData() {
//1,应用版本名称
String versionName = getVersionName();
//String versionName(13)=getVersionName();
tv_version_name.setText("版本名称"+getVersionName());
//将 int versionCode(ctrl+1)转换为类的成员变量mVersionCode
//2,获取本地版本号,将mVersionCode(alt+shift+R)变为mLocalVersionCode
mLocalVersionCode = getVersionCode();
//获取服务器版本号
//3,获取服务器版本号(客户端请求,服务器端响应(json,xml))
//http://www.oxxx.com/update74.jon?key=value 返回200请求成功,流的方式将数据读取下来
/*json中内容包含:
* 更新版本的版本名称
* 新版本的描述信息
* 服务器版本号
* 新版本apk的下载地址
*/
checkVersion();
}
private void checkVersion() {
new Thread(){
public void run() {
Message msg = Message.obtain();//返回一个msg对象
long startTime = System.currentTimeMillis();
try {
//1,封装url地址
URL url = new URL("http://10.0.2.2:8080/update.json");
//2,开启一个链接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();//返回HttpURLConnection的对象
//3,设置常见请求参数(请求头)
//请求超时,指链接超时,根本就没连接上
connection.setConnectTimeout(2000);
//读取超时
connection.setReadTimeout(2000);
//默认就是get请求方式
connection.setRequestMethod("POST");
//4,获取请求成功响应码
if(connection.getResponseCode()==200){
//5,以流的形式,将数据获取下来
InputStream is = connection.getInputStream();
//6,将流转换成字符串(攻击类封装)
String json = StreamUtil.streamToString(is);
Log.i(tag, json);//用log来打印日志
//7,json解析
JSONObject jsonObject = new JSONObject(json);
mDownloadUrl = jsonObject.getString("downloadUrl");
String versionCode = jsonObject.getString("versionCode");
mVersionDes = jsonObject.getString("versionDes");
String versionName = jsonObject.getString("versionName");
Log.i(tag,mDownloadUrl);
Log.i(tag,versionCode);
Log.i(tag,mVersionDes);
Log.i(tag,versionName);
//8,比对版本号(本地版本号<服务器版本号,提示用户更新)
if(mLocalVersionCode
同时需要在此目录下放置一个Json文件,内容如下:
{
"downloadUrl": "http://10.0.2.2:8080/xc.apk",
"versionCode": "2",
"versionDes": "Welcome to use 2.0,please download",
"versionName": "2.0"
}