问题来了,平时开发应用也许你会遇到这种场景:应用启动检查服务器版本,若大于当前版本,则要从网络上下载APK文件,并在Activity上展示进度条。
版本更新,无非是下载apk文件,安装apk。
//其中用到 Xutils
ublic class CheckVersionUtils {
private static CheckVersionUtils mCheckVersionUtils;
private CheckVersionUtils() {
}
public static CheckVersionUtils getInstance() {
if (mCheckVersionUtils == null) {
mCheckVersionUtils = new CheckVersionUtils();
}
return mCheckVersionUtils;
}
/**
* 访问网络检查版本号码
*
* @param isToastNoVersion 是否弹出"当前版本已为最新版本"的Toast
* @param activity 弹窗需要的依赖的Activity
*/
public void checkVersionToServer(final boolean isToastNoVersion, final Activity activity) {
x.http().get(new RequestParams(ConstantValue.CHECK_VERSION_JSON_URL), new Callback.CommonCallback() {
@Override
public void onSuccess(String result) {
Log.e("CheckVersionActivity", "CheckVersionActivity onSuccess()" + result);
processData(result, activity, isToastNoVersion);
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
}
@Override
public void onCancelled(CancelledException cex) {
}
@Override
public void onFinished() {
}
});
}
/**
* 返回版本号
*/
private int getVersionCode() {
return BuildConfig.VERSION_CODE;
}
/**
* 解析JSON
*
* @param json
* @param isToastNoVersion
*/
private void processData(String json, Activity activity, boolean isToastNoVersion) {
Gson gson = new Gson();
CheckVersionBean checkVersionBean = gson.fromJson(json, CheckVersionBean.class);
/**
* 保存在手机的位置
*/
String saveSDPath = EXB_SD_PATH_APK + checkVersionBean.getFileName();
//判断是否需要更新
if (getVersionCode() < checkVersionBean.getVersionCode()) {
showUpdateDialog(checkVersionBean, saveSDPath, activity);
} else {
if (isToastNoVersion) {
//不更新
Toast.makeText(activity, "当前版本已为最新版本", Toast.LENGTH_SHORT).show();
}
}
}
/**
* 显示更新对话框
*
* @param checkVersionBean
*/
private void showUpdateDialog(final CheckVersionBean checkVersionBean, final String saveSDPath, final Activity activity) {
//创建文件,判断是否存在
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
AlertDialog alertDialog = builder.create();
//更新描述信息
String updateLog = checkVersionBean.getUpdateLog();
if (TextUtils.isEmpty(updateLog)) {
updateLog = "新版本,欢迎更新";
}
//版本名称
String versionName = checkVersionBean.getVersionName();
if (TextUtils.isEmpty(versionName)) {
versionName = "1.1";
}
alertDialog.setTitle("新版本" + versionName);
alertDialog.setMessage(updateLog);
//判断是否要强制更新
if (checkVersionBean.getIsForceUpdate() == 1) {
//强制更新
//设置外部点了没有效果
alertDialog.setCanceledOnTouchOutside(false);
//禁用返回键
alertDialog.setCancelable(false);
alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "更新", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//更新
downloadApk(checkVersionBean.getDownloadUrl(), saveSDPath, activity);
}
});
} else {
alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "更新", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//更新
downloadApk(checkVersionBean.getDownloadUrl(), saveSDPath, activity);
}
});
}
alertDialog.show();
}
/**
* 下载apk
*
* @param downurl
*/
private void downloadApk(String downurl, String path, final Activity activity) {
final ProgressDialog progressDialog = new ProgressDialog(activity);
RequestParams requestParams = new RequestParams(downurl);
requestParams.setSaveFilePath(path);
x.http().get(requestParams, new Callback.ProgressCallback() {
@Override
public void onWaiting() {
}
@Override
public void onStarted() {
}
@Override
public void onLoading(long total, long current, boolean isDownloading) {
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("拼命下载中...");
progressDialog.show();
progressDialog.setMax(100);
double fcurrent = current;
progressDialog.setProgress((int) ((fcurrent / total) * 100));
}
@Override
public void onSuccess(File result) {
Toast.makeText(NiceyooApplication.getNiceyooApp(), "下载完成", Toast.LENGTH_SHORT).show();
progressDialog.dismiss();
installApk(activity, result);
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
ex.printStackTrace();
Toast.makeText(NiceyooApplication.getNiceyooApp(), "下载失败,请检查网络和SD卡", Toast.LENGTH_SHORT).show();
progressDialog.dismiss();
}
@Override
public void onCancelled(CancelledException cex) {
}
@Override
public void onFinished() {
}
});
}
/**
* 安装对应apk
*
* @param activity
* @param file 安装文件
*/
private void installApk(Activity activity, File file) {
//系统应用界面,源码,安装apk入口
Intent intent = new Intent("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
//设置安装的类型
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
activity.startActivityForResult(intent, ConstantValue.INSTALL_NEW_VERSION_SUCCESS);
}
}
为什么要用server下载呢?因为有可能 你需要更新的这个Activity要求是可以转屏的。那么在转屏时Actvitiy会重启,如何保证下载的进度条能正确展示进度呢?当然是用server下载了…
public class UpdateService extends Service {
public UpdateService() {
}
/**
* 安卓系统下载类
**/
DownloadManager manager;
/**
* 接收下载完的广播
**/
DownloadCompleteReceiver receiver;
/**
* 初始化下载器
**/
private void initDownManager() {
manager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
receiver = new DownloadCompleteReceiver();
//设置下载地址
DownloadManager.Request down = new DownloadManager.Request(
// 百度音乐
Uri.parse("http://gdown.baidu.com/data/wisegame/fd84b7f6746f0b18/baiduyinyue_4802.apk"));
// 乐视体育
// Uri.parse("http://122.228.237.132/apk.r1.market.hiapk.com/data/upload/apkres/2016/6_12/16/com.lesports.glivesports_040405.apk"));
// 设置允许使用的网络类型,这里是移动网络和wifi都可以
down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
// 下载时,通知栏显示途中
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
down.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
}
// 显示下载界面
down.setVisibleInDownloadsUi(true);
// 设置下载后文件存放的位置
down.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, "leshi.apk");
// 将下载请求放入队列
manager.enqueue(down);
//注册下载广播
registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 调用下载
initDownManager();
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
// 注销下载广播
if (receiver != null)
unregisterReceiver(receiver);
super.onDestroy();
}
// 接受下载完成后的intent
class DownloadCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//判断是否下载完成的广播
if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
//获取下载的文件id
long downId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
//自动安装apk
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
Uri uriForDownloadedFile = manager.getUriForDownloadedFile(downId);
Log.d("kodulf", "uri=" + uriForDownloadedFile);
installApkNew(uriForDownloadedFile);
}
//停止服务并关闭广播
UpdateService.this.stopSelf();
}
}
//安装apk
protected void installApkNew(Uri uri) {
Intent intent = new Intent();
//执行动作
intent.setAction(Intent.ACTION_VIEW);
//执行的数据类型
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
//不加下面这句话是可以的,查考的里面说如果不加上这句的话在apk安装完成之后点击单开会崩溃
// android.os.Process.killProcess(android.os.Process.myPid());
startActivity(intent);
}
}
}
参考:http://blog.csdn.net/rodulf/article/details/51706788#comments