Android 版本检测更新
Posted 刘永祥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 版本检测更新相关的知识,希望对你有一定的参考价值。
android版本检测更新是每个应用升级所不可少的,以前早就做过一些,一直没有时间与大家分享,现在就跟大家来分享一下我做的版本检测更新吧。先上图
点击更新之后的
可能有人会问为啥点击更新提示框不消失啊,可以根据自己的情况而定,有的需要强制更新,也是为了方便用户看到下载的进度。我这里只是为了测试一下效果而已。真正的是点击更新以后会在通知栏里面进行显示的 效果就是这样的
也有的可能需要在桌面上面展示给用户,下面的效果
这些都是是需求而定的。不多说了上代码
package com.liuyongxiang.update.activity;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
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.liuyongxiang.update.R;
import com.liuyongxiang.update.bean.VersionBean;
import com.liuyongxiang.update.utils.MyConstants;
import com.liuyongxiang.update.utils.SpTools;
import com.liuyongxiang.update.view.NumberProgressBar;
import com.liuyongxiang.update.view.OnProgressBarListener;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.PixelFormat;
import android.graphics.pdf.PdfDocument;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.RemoteViews;
import android.widget.TextView;
import android.widget.Toast;
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class SplashActivity extends Activity implements OnProgressBarListener {
private static final int LOADMAIN = 1;// 加载主界面
private static final int SHOWUPDATEDIALOG = 2;// 显示是否更新的对话框
protected static final int ERROR = 3;// 错误统一代号
private RelativeLayout rl_root;// 界面的根布局组件
private int versionCode;// 版本号
private String versionName;// 版本名
private TextView tv_versionName;// 显示版本名的组件
private VersionBean parseJson;// url信息封装bean
private long startTimeMillis;// 记录开始访问网络的时间
private NumberProgressBar pb_download;// 下载最新版本apk的进度条
private Notification.Builder mBuilder;
private NotificationManager mNotificationManager;
public static final int NOTIFICATION_ID = 200; // 通知唯一id
public static final int MUTE = 0; // 0表示静音
public static final int VIBRATE = 1; // 1表示震动
public static final int SOUND = 2; // 2表示响音
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 初始化界面
initView();
// 初始化数据
initData();
//如果正常的从服务器获取应调用下面的timeInitialization(),而showUpdateDialog()只是为了测试查看一下效果
// timeInitialization();
showUpdateDialog();
}
/**
* 耗时的功能封装,只要耗时的处理,都放到此方法
*/
private void timeInitialization() {
// 一开始动画,就应该干耗时的业务(网络,本地数据初始化,数据的拷贝等)
if (SpTools.getBoolean(getApplicationContext(), MyConstants.AUTOUPDATE,
false)) {
// true 自动更新
// 检测服务器的版本
checkVerion();
}
// 增加自己的耗时功能处理
}
private void initData() {
// 获取自己的版本信息
PackageManager pm = getPackageManager();
try {
PackageInfo packageInfo = pm.getPackageInfo(getPackageName(), 0);
// 版本号
versionCode = packageInfo.versionCode;
// 版本名
versionName = packageInfo.versionName;
// 设置textview
tv_versionName.setText(versionName);
} catch (NameNotFoundException e) {
// can not reach 异常不会发生
}
}
private void checkVerion() {
// 耗时操作都要放到子线程中执行
new Thread(new Runnable() {
@Override
public void run() {
BufferedReader bfr = null;
HttpURLConnection conn = null;
int errorCode = -1;// 正常,没有错误
try {
startTimeMillis = System.currentTimeMillis();
URL url = new URL("http://10.0.2.2:8080/guardversion.json");
conn = (HttpURLConnection) url.openConnection();
// 读取数据的超时时间
conn.setReadTimeout(5000);
// 网络连接超时
conn.setConnectTimeout(5000);
// 设置请求方式
// 获取相应结果
int code = conn.getResponseCode();
if (code == 200) {// 数据获取成功
// 获取读取的字节流
InputStream is = conn.getInputStream();
// 把字节流转换成字符流
bfr = new BufferedReader(new InputStreamReader(is));
// 读取一行信息
String line = bfr.readLine();
// json字符串数据的封装
StringBuilder json = new StringBuilder();
while (line != null) {
json.append(line);
line = bfr.readLine();
}
parseJson = parseJson(json);// 返回数据封装信息
} else {
errorCode = 404;
}
} catch (MalformedURLException e) {// 4002
errorCode = 4002;
e.printStackTrace();
} catch (IOException e) {// 4001
errorCode = 4001;
e.printStackTrace();
} catch (JSONException e) {
errorCode = 4003;
e.printStackTrace();
} finally {
Message msg = Message.obtain();
if (errorCode == -1) {
msg.what = isNewVersion(parseJson);// 检测是否有新版本
} else {
msg.what = ERROR;
msg.arg1 = errorCode;
}
long endTime = System.currentTimeMillis();
if (endTime - startTimeMillis < 3000) {
SystemClock.sleep(3000 - (endTime - startTimeMillis));// 时间不超过3秒,补足3秒
}
handler.sendMessage(msg);// 发送消息
try {
// 关闭连接资源
if (bfr != null) {
bfr.close();
}
if (conn != null) {
conn.disconnect();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
// 处理消息
switch (msg.what) {
case LOADMAIN:// 加载主界面
loadMain();
break;
case ERROR:// 有异常
switch (msg.arg1) {
case 404:// 资源找不到
Toast.makeText(getApplicationContext(), "404资源找不到", 0)
.show();
break;
case 4001:// 找不到网络
Toast.makeText(getApplicationContext(), "4001没有网络", 0)
.show();
break;
case 4003:// json格式错误
Toast.makeText(getApplicationContext(), "4003json格式错误", 0)
.show();
break;
default:
break;
}
loadMain();// 进入主界面
break;
case SHOWUPDATEDIALOG:// 显示更新版本的对话框
showUpdateDialog();
break;
default:
break;
}
}
};
private AlertDialog dialog;
private void loadMain() {
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
startActivity(intent);// 进入主界面
finish();// 关闭自己
};
protected int isNewVersion(VersionBean parseJson) {
// 获取服务器设置的版本
// int serverCode = parseJson.getVersionCode();
int serverCode = 2;// 获取服务器的版本
System.out.println("serverCode----->" + serverCode);
if (serverCode == versionCode) {
// 如果版本一致直接进入到主界面
return LOADMAIN;
/*
* 进入主界面 Message msg = Message.obtain(); msg.what = LOADMAIN;
*/
} else {
// 否则会弹出提示更新的提示框
return SHOWUPDATEDIALOG;
}
}
/**
* 显示是否更新新版本的对话框
*/
public void showUpdateDialog() {
dialog = new AlertDialog.Builder(this).create();
dialog.setCancelable(false);
dialog.show();
Window window = dialog.getWindow();
window.setContentView(R.layout.prompt_alertdialog);
LinearLayout ll_title = (LinearLayout) window
.findViewById(R.id.ll_title);
ll_title.setVisibility(View.VISIBLE);
TextView tv_title = (TextView) window.findViewById(R.id.tv_title);
pb_download = (NumberProgressBar) window
.findViewById(R.id.pb_splash_download);
pb_download.setVisibility(View.GONE);// 隐藏进度条
pb_download.setOnProgressBarListener(this);
tv_title.setText("版本更新");
TextView tv_content = (TextView) window.findViewById(R.id.tv_content);
tv_content.setMovementMethod(new ScrollingMovementMethod());
tv_content
.setText("是否更新新版本?新版本的具有如下特性:1.是否更新新版本?新版本的具有如下特性 2.是否更新新版本?新版本的具有如下特性 3.是否更新新版本?新版本的具有如下特性 4.是否更新新版本?新版本的具有如下特性 5.是否更新新版本?新版本的具有如下特性 6.是否更新新版本?新版本的具有如下特性 7.是否更新新版本?新版本的具有如下特性 8.是否更新新版本?新版本的具有如下特性");
final TextView tv_sure = (TextView) window.findViewById(R.id.tv_sure);
final TextView tv_cancle = (TextView) window
.findViewById(R.id.tv_cancle);
tv_cancle.setText("取消");
tv_cancle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
loadMain();
dialog.cancel();
}
});
tv_sure.setText("更新");
tv_sure.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
downLoadNewApk();// 下载新版本
createFloatView();
tv_cancle.setEnabled(false);
tv_sure.setEnabled(false);
dialog.cancel();
loadMain();
pb_download.setVisibility(View.VISIBLE);
}
});
}
/**
* 新版本的下载安装
*/
protected void downLoadNewApk() {
HttpUtils utils = new HttpUtils();
// parseJson.getUrl() 下载的url
// target 本地路径
// System.out.println(parseJson.getUrl());
File file = new File("/mnt/sdcard/测试.apk");
//如果此文件已存在先删除
file.delete();// 删除文件
utils.download(
"http://www.gamept.cn/d/file/game/qipai/20140627/HappyLordZZ_1.0.19_20140325_300002877528_2200139763.apk",
"/mnt/sdcard/测试.apk", new RequestCallBack<File>() {
@Override
public void onLoading(final long total, final long current,
boolean isUploading) {
pb_download.setVisibility(View.VISIBLE);// 设置进度的显示
int max = (int) total;
int progress = (int) current;
pb_download.setMax(max);// 设置进度条的最大值
pb_download.setProgress(progress);// 设置当前进度
pb_download2.setMax(max);
pb_download2.setProgress(progress);
// showNotification(max,progree);
showNotifi(max, progress);
super.onLoading(total, current, isUploading);
}
@Override
public void onSuccess(ResponseInfo<File> arg0) {
// 下载成功
// 在主线程中执行
Toast.makeText(getApplicationContext(), "下载新版本成功", 1)
.show();
// 安装apk
installApk();// 安装apk
pb_download.setVisibility(View.GONE);// 隐藏进度条
rl_notification.setVisibility(View.GONE);
}
@Override
public void onFailure(HttpException arg0, String arg1) {
// 下载失败
Toast.makeText(getApplicationContext(), "下载新版本失败", 1)
.show();
pb_download.setVisibility(View.GONE);// 隐藏进度条
}
});
}
private NumberProgressBar pb_download2;
private RelativeLayout rl_notification;
/**
* 安装下载的新版本
*/
protected void installApk() {
Intent intent = new Intent("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
String type = "application/vnd.android.package-archive";
Uri data = Uri.fromFile(new File("/mnt/sdcard/测试.apk"));
intent.setDataAndType(data, type);
startActivityForResult(intent, 0);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// 如果用户取消更新apk,那么直接进入主界面
loadMain();
super.onActivityResult(requestCode, resultCode, data);
}
/**
* @param jsonString
* url的json数据
* @return url信息封装对象
* @throws JSONException
*/
protected VersionBean parseJson(StringBuilder jsonString)
throws JSONException {
VersionBean bean = new VersionBean();
JSONObject jsonObj;
jsonObj = new JSONObject(jsonString + "");
int versionCode = jsonObj.getInt("version");
String url = jsonObj.getString("url");
String desc = jsonObj.getString("desc");
// 封装结果数据
bean.setDesc(desc);
bean.setUrl(url);
bean.setVersionCode(versionCode);
return bean;
}
/**
* 初始化界面
*/
private void initView() {
setContentView(R.layout.activity_main);
rl_root = (RelativeLayout) findViewById(R.id.rl_splash_root);
tv_versionName = (TextView) findViewById(R.id.tv_splash_version_name);
}
@Override
public void onProgressChange(int current, int max) {
pb_download.setProgress(current);
pb_download2.setProgress(current);
}
private void createFloatView() {
final WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();
getApplication();
final WindowManager mWindowManager = (WindowManager) getApplication()
.getSystemService(Context.WINDOW_SERVICE);
wmParams.type = LayoutParams.TYPE_PHONE;
wmParams.format = PixelFormat.RGBA_8888;
wmParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE;
wmParams.gravity = Gravity.LEFT | Gravity.TOP;
wmParams.x = 0;
wmParams.y = 0;
wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
LayoutInflater inflater = LayoutInflater.from(getApplication());
final View mFloatLayout = inflater.inflate(
R.layout.activity_notification, null);
mWindowManager.addView(mFloatLayout, wmParams);
rl_notification = (RelativeLayout) mFloatLayout
.findViewById(R.id.rl_notification);
pb_download2 = (NumberProgressBar) mFloatLayout
.findViewById(R.id.pb_download);
// TextView tv_name = (TextView)
// mFloatLayout.findViewById(R.id.tv_name);
// TextView tv_time = (TextView)
// mFloatLayout.findViewById(R.id.tv_time);
// ImageView iv_icon = (ImageView)
// mFloatLayout.findViewById(R.id.iv_icon);// 系统显示的通知图片
mFloatLayout.measure(View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED), View.MeasureSpec
.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
rl_notification.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
wmParams.x = (int) event.getRawX()
- rl_notification.getMeasuredWidth() / 2;
wmParams.y = (int) event.getRawY()
- rl_notification.getMeasuredHeight() / 2 - 25;
mWindowManager.updateViewLayout(mFloatLayout, wmParams);
return false;
}
});
}
private void showNotification(final int total, final int current) {
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mBuilder = new Notification.Builder(SplashActivity.this);
LayoutInflater inflater = LayoutInflater.from(getApplication());
View view = inflater.inflate(R.layout.activity_notification, null);
mBuilder.setContentTitle("这是测试").setContentText("下载中...")
.setSmallIcon(R.drawable.app_icon);
new Thread(new Runnable() {
@SuppressLint("NewApi")
@Override
public void run() {
mBuilder.setProgress(total, current, false);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
if (current / total == 1) {
mNotificationManager.cancel(0);
}
}
}).start();
}
private void showNotifi(final int total, final int current) {
NotificationManager notiManage;
Notification note;
mBuilder = new Notification.Builder(SplashActivity.this);
notiManage = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
note = new Notification();
note.flags = Notification.FLAG_AUTO_CANCEL;
RemoteViews contentView = new RemoteViews(getPackageName(),
R.layout.activity_notifi);
contentView.setTextViewText(R.id.notificationTitle, "这是测试");
String str_progress =current*100/total+"%";
contentView.setTextViewText(R.id.notificationPercent, str_progress);
contentView.setProgressBar(R.id.notificationProgress, total, current,
false);
note.contentView = contentView;
note.tickerText = "正在下载";
note.icon = R.drawable.app_icon;
PendingIntent p = PendingIntent.getActivity(SplashActivity.this, 0,
new Intent(Intent.ACTION_VIEW), 0);// 这个非要不可。
note.contentIntent = p;
notiManage.notify(NOTIFICATION_ID, note);
if (current / total == 1) {
notiManage.cancelAll();
}
}
}
这只是一些简单的代码,如果想测试一下具体效果
点击免费下载源码
如果有问题请加Android交流群 470707794或留言
以上是关于Android 版本检测更新的主要内容,如果未能解决你的问题,请参考以下文章