Android在线更新下载方案

2018-05-03  本文已影响0人  Eren丶耶格尔

目的

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;
}

上一篇 下一篇

猜你喜欢

热点阅读