一、动态获取项目清单版本信息
有时候我们在更新了软件之后需要将新的软件版本信息显示到界面我们该如何动态的操作呢?PackageManager : 用来管理Apk
创建一个方法用来动态获取项目清单的版本信息
public String getVersionName(){
//用来管理手机的Apk
PackageManager manager = getPackageManager();
try {
//得知Apk功能清单项目
PackageInfo info = manager.getPackageInfo(getPackageName(), 0);
//返回项目清单里面的版本名称
return info.versionName;
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
注意这里的是: 如果在项目清单中配置过版本信息,那么就不能在低于配置版本信息的版本号了,不然会报错的
<span style="white-space:pre"> </span>Installation error: INSTALL_FAILED_VERSION_DOWNGRADE
二、软件升级流程
配置好版本信息过后我们就可以通过访问服务器的方式升级软件,为了演示我们开启Tocat然后配置一个updateinfo.xml的信息,里面包括了版本信息、版本描述、以及最新下载新版本的地址
然后我们在Activity中配置一个请求服务器的类,通过这个类获取到版本信息、版本描述、以及最新下载新版本的地址
为了演示只是在Log里面打印而已:
/**
* 判断是否可更新
*/
public String CheckUpdate() {
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
URL url = new URL(getString(R.string.serverurl));
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
int responseCode = connection.getResponseCode();
if(responseCode == 200){
InputStream inputStream = connection.getInputStream();
String result = StreamTools.readFromStream(inputStream);
Log.d(TAG, result);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
return null;
}
链接服务器查看版本更新信息
在程序启动的时候会链接服务器获取最新版本信息,然后将自己的版本跟从服务器获取的版本信息进行对比,如
果不一致(有最新版本)则提示用户更新。
注意:1、这里我们使用到了网络,因此要在清单文件中添加 android.permission.INTERNET 权限。2、因为访问网
络是“耗时”过程,因此我们把检查版本更新业务要放在子线程中进行。
/**
* 判断是否可更新
*/
private void CheckUpdate() {
new Thread(new Runnable() {
@Override
public void run() {
long StartTime = java.lang.System.currentTimeMillis();
// TODO Auto-generated method stub
// 不要new ,直接获取
Message message = new Message();
try {
URL url = new URL(getString(R.string.serverurl));
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.connect();
int responseCode = connection.getResponseCode();
if (responseCode == 200) {
InputStream inputStream = connection.getInputStream();
String result = StreamTools.readFromStream(inputStream);
Log.d(TAG, result);
// 解析JSON,
JSONObject object = new JSONObject(result);
// 解析出来的信息,包括版本,升级内容,升级地址
Object version = object.get("version");
description = (String) object.get("description");
apkurl = (String) object.get("apkurl");
Log.d(TAG, "版本信息 :" + version);
if (getVersionName().equals(version)) {
// 进入主页
message.what = ENTER_HOME;
} else {
// 显示下载dialog
message.what = SHOW_DIALOG;
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
message.what = EXCEPITON;
} finally {
long Endtime = java.lang.System.currentTimeMillis();
//所用时间
long Dtime = Endtime - StartTime;
if(Dtime < 2000){
try {
Thread.sleep(2000 - Dtime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
handler.sendMessage(message);
}
}
}).start();
}
在 onCreate 方法中,给 Splash 界面添加启动画面。这里添加的是渐变动画,透明度从 0 到 1 渐变,时长 500 毫秒
AlphaAnimation alphaAnimation = new AlphaAnimation(0.f, 1.f);
RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.rl_root);
alphaAnimation.setDuration(500);
relativeLayout.startAnimation(alphaAnimation);
发送到handler里面之后,我们进行判断,发送的内容,是进行升级还是,直接进入主界面,还是抛出了异常
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch (msg.what) {
case ENTER_HOME:
EnterHome();
break;
case SHOW_DIALOG:
// Toast.makeText(MainActivity.this, "新版本信息内容 : " +
// description, Toast.LENGTH_SHORT).show();
// 升级应用程序
showUpdateDialog();
break;
case EXCEPITON:
EnterHome();
Toast.makeText(MainActivity.this, "Unknown Error",
Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
};
这里我们可以看出如果是没有更新就直接进入主界面,如果有我们就在showUpdateDialog里面进行更新,抛出异常了得话
我们提醒用户出错,进入主界面这里就不演示了自己实现
private void showUpdateDialog() {
// TODO Auto-generated method stub
AlertDialog.Builder builder = new Builder(this);
builder.setTitle("发现新版本");
builder.setMessage("已经发布新版本了,希望您能及时升级。");
builder.setCancelable(false);
builder.setPositiveButton("升级", new OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, int which) {
// TODO Auto-generated method stub
// 安装并替换
// 一般下载的安装包会放在sd卡上
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
// 这里使用框架进行下载
FinalHttp finalHttp = new FinalHttp();
finalHttp.download(apkurl, Environment.getExternalStorageDirectory().getAbsolutePath()+"/mobilesafe3.0.apk", new AjaxCallBack<File>() {
/*
* 下载错误
*/
@Override
public void onFailure(Throwable t, int errorNo,
String strMsg) {
// TODO Auto-generated method stub
t.printStackTrace();
//print Error Log
Toast.makeText(getApplicationContext(), "下载出错", 0).show();
super.onFailure(t, errorNo, strMsg);
}
/*
* 正在下载
*/
@Override
public void onLoading(long count, long current) {
// TODO Auto-generated method stub
super.onLoading(count, current);
int values = (int) (current * 100 / count);
progress.setText("下载进度" +values+ "%");
}
/*
* 下载成功
*/
@Override
public void onSuccess(File t) {
// TODO Auto-generated method stub
super.onSuccess(t);
Toast.makeText(getApplicationContext(), "下载成功", 0).show();
installAPK(t);
}
private void installAPK(File t) {
// TODO Auto-generated method stub
/**
* 安装APK
*/
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
intent.setDataAndType(Uri.fromFile(t), "application/vnd.android.package-archive");
startActivity(intent);
}
});
} else {
Toast.makeText(getApplicationContext(), "请安装好sd卡后再试试", 0)
.show();
return;
}
}
});
builder.setNegativeButton("下次下载", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
/*
* 消掉对话框进入主页面
*/
dialog.dismiss();
EnterHome();
}
});
builder.show();
}
这里在下载新版本安装包时需要使用到框架afinal,这里不过多介绍.
这样一个进入界面检查版本是否需要更新,更新弹出更新或者不更新的Dialog就创建好了