目的
App的在线更新是每一个项目必有的功能,但在过程当中会遇到一些问题,在此记录下心得。
步骤
1、将最新版本号和本地版本号进行对比;
2、如需更新,则弹出更新提示对话框;
3、下载更新APK文件,并显示进度条和通知栏;
4、安装APK
具体流程
一、通过网络接口获取到线上最新版本号,将最新版本号和本地版本号进行对比
首先从网络回调接口中获取最新版本号,再将本地版本号与最新版本号进行对比,如果需要更新则弹出对话框
/**
* 更新提示对话框
*/
public void appUpdateDialog(final Context context, final UpdateCheckRetBean bean) {
new MaterialDialog.Builder(context)
.title("金米米") //标题内容
.titleColor(Color.parseColor("#FFC736")) //标题颜色
.iconRes(R.drawable.ic_logo_share) //图标
.content(bean.getDetail()) //内容
.positiveText("立即更新") //选择更新
.canceledOnTouchOutside(false) //触摸窗口边界以外是否关闭窗口,设置 false
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
dialog.dismiss();
downloadDialog(context, bean.getUrl()); //应用下载
setNotification(context, bean.getDetail()); //显示通知栏
}
})
.negativeText("取消") //选择取消
.onNegative(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
dialog.dismiss();
}
})
.show();
}
三、下载更新APK文件,并显示进度条和通知栏
这部分是重点,分三部分解决:
1、显示进度条:
这里再次使用了一个很好轮子:NumberProgressBar
/**
* 应用下载对话框
*
* @param downloadUrl APK下载链接
*/
private void downloadDialog(final Context mContext, String downloadUrl) {
downLoadDialog = new MaterialDialog.Builder(mContext)
.customView(R.layout.layout_app_update, false) //自定义View
.title("更新中...")
.iconRes(R.drawable.ic_logo_share)
.titleColor(Color.parseColor("#FFC736"))
.negativeText("取消下载") //选择取消
.canceledOnTouchOutside(false) // 触摸窗口边界以外是否关闭窗口,设置 false
.onNegative(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
ToastUtils.showShortToast(mContext, "取消更新");
dialog.dismiss();
notificationManager.cancel(NOTIFICATION_ID); //取消通知栏
OkHttpClientUtil.getInstance().cancelOkHttp("download"); //取消下载更新
}
})
.build();
//拦截手机返回键
downLoadDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
ToastUtils.showShortToast(mContext, "进入后台下载模式");
return keyCode != KeyEvent.KEYCODE_BACK &&
downLoadDialog != null && downLoadDialog.isShowing();
}
});
npbDownload = downLoadDialog.getCustomView().findViewById(R.id.npb_download); //设置进度条
npbDownload.setProgressTextSize(45); //设置进度条字体大小
downLoadDialog.show();
downloadApk(mContext, downloadUrl); //下载更新APK
}
2、下载更新APK文件:
/**
* 下载更新APK
*
* @param downloadUrl APK下载链接
*/
private void downloadApk(final Context mContext, String downloadUrl) {
//下载APK
OkHttpClientUtil.getInstance().downloadFile("download", downloadUrl, new RequestParms(), Environment.getExternalStorageDirectory().getAbsolutePath() + "/lzt.apk", new OkHttpResponseListener() {
@Override
public void onSuccess(Object object) {
downLoadDialog.dismiss();
Intent intent = new Intent(Intent.ACTION_VIEW);
//判断是否是AndroidN以及更高的版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri contentUri = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID + ".fileProvider", (File) object);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile((File) object), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
mContext.startActivity(intent);
}
@Override
public void onFailure(String errorMsg) {
ToastUtil.showShortToast(errorMsg);
}
@Override
public void onFileProgress(int progress) {
if (progress == 100) {
notificationManager.cancel(NOTIFICATION_ID);
}
npbDownload.setProgress(progress);
}
});
}
3、通知栏展示进度:
/**
* 创建通知栏
*/
private void setNotification(Context context, String detail) {
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notification = new Notification.Builder(context);
notification.setSmallIcon(R.drawable.ic_16) //设置通知的图标
.setTicker("正在加载更新包") //设置状态栏的标题
.setContentTitle("正在加载更新包") //设置标题
.setContentText(detail) //设置内容
.setDefaults(Notification.FLAG_NO_CLEAR) //设置默认的提示音
.setPriority(Notification.PRIORITY_DEFAULT) //设置该通知的优先级
.setOngoing(true) //让通知左右滑的时候不能取消通知
.setWhen(System.currentTimeMillis()) //设置通知时间,默认为系统发出通知的时间,通常不用设置
.setAutoCancel(true); //打开程序后图标消失
//解决5.0系统通知栏白色Icon的问题
Drawable appIcon = getAppIcon(context);
Bitmap drawableToBitmap = null;
if (appIcon != null) {
drawableToBitmap = drawableToBitmap(appIcon);
}
if (drawableToBitmap != null) {
notification.setSmallIcon(R.drawable.ic_16);
notification.setLargeIcon(drawableToBitmap);
} else {
notification.setSmallIcon(context.getApplicationInfo().icon);
}
Notification notify = notification.build();
notify.flags |= FLAG_ONLY_ALERT_ONCE;
notificationManager.notify(NOTIFICATION_ID, notify);
}
/**
* 合成更新的Icon
*
* @param drawable
* @return
*/
public Bitmap drawableToBitmap(Drawable drawable) {
Bitmap bitmap = Bitmap.createBitmap(
drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(),
drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
drawable.draw(canvas);
return bitmap;
}
/**
* 获取App的Icon
*
* @param context
* @return
*/
public Drawable getAppIcon(Context context) {
try {
return context.getPackageManager().getApplicationIcon(context.getPackageName());
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return null;
}
网友评论