美文网首页
Android站内更新

Android站内更新

作者: 刘坤林 | 来源:发表于2024-08-14 15:23 被阅读0次

    一、新建更新服务Service类

    通知栏,对话框,吐司,换成自己的

    import android.app.Notification;
    import android.app.NotificationManager;
    import android.app.PendingIntent;
    import android.app.Service;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.graphics.BitmapFactory;
    import android.net.Uri;
    import android.os.Build;
    import android.os.IBinder;
    import android.text.TextUtils;
    
    import androidx.annotation.Nullable;
    import androidx.core.content.FileProvider;
    
    import java.io.File;
    import java.util.Random;
    
    /**
     * createTime   :2024/6/29 11:13
     * createBy     :lkl
     */
    public class UpdateService extends Service {
        private static Intent intentService;
    
        public static void start(String version, String url) {
            if (intentService != null) {
                stop();
            }
            Context context = App.getContext();
            intentService = new Intent(context, UpdateService.class);
            intentService.putExtra("version", version);
            intentService.putExtra("url", url);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                context.startForegroundService(intentService);
            } else {
                context.startService(intentService);
            }
        }
    
        public static void stop() {
            if (intentService == null) {
                return;
            }
            Context context = App.getContext();
            context.stopService(intentService);
            intentService = null;
        }
    
        public static boolean isDownloading() {
            return intentService != null;
        }
    
    
        public static void sendCancel() {
            if (!isDownloading()) {
                return;
            }
            Intent intent = new Intent(ACTION_CANCEL);
            App.getContext().sendBroadcast(intent);
        }
    
        public static void sendChange() {
            if (!isDownloading()) {
                return;
            }
            Intent intent = new Intent(ACTION_CHANGE);
            App.getContext().sendBroadcast(intent);
        }
    
        public static void sendSetUp() {
            if (!isDownloading()) {
                return;
            }
            Intent intent = new Intent(ACTION_SET_UP);
            App.getContext().sendBroadcast(intent);
        }
    
        //取消
        public static final String ACTION_CANCEL = "UpdateServiceCancel";
        //更改(点击的动作,也就是PendIntent)
        public static final String ACTION_CHANGE = "UpdateServiceChange";
        //安装
        public static final String ACTION_SET_UP = "UpdateServiceSetup";
        public static int progress = 0;
        private File apkFile;
    
        private NotificationManager manager;
        private int notifyId;
        private Notification.Builder builder;
        private BroadcastReceiver receiver;
        private TipDialog tipDialog;
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            notifyId = new Random().nextInt(1000);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                builder = new Notification.Builder(this, NotifyUtils.minChannelId)
                        .setChannelId(NotifyUtils.minChannelId);
            } else {
                builder = new Notification.Builder(this);
            }
            //设置标题
            builder.setContentTitle(App.instance.setAppName() + "正在下载更新")
                    //设置内容
                    .setContentText("下载中0%")
                    .setAutoCancel(false)
                    .setNumber(0)
                    //是否是进行中通知,如果是,用户将无法取消此通知
                    .setOngoing(true)
                    //设置创建时间
                    .setWhen(System.currentTimeMillis())
                    //设置状态栏图标
                    .setSmallIcon(R.mipmap.icon_move_up)
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.app_icon))
                    .setContentIntent(getPendingIntent());
            receiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    String action = intent.getAction();
                    if (action == null) {
                        return;
                    }
                    switch (action) {
                        case ACTION_CANCEL:
                            if (tipDialog != null) {
                                tipDialog.dismiss();
                            }
                            tipDialog = TipDialog.create(App.instance.getTopActivity())
                                    .title("是否取消更新?")
                                    .setSureText("是")
                                    .setCancelText("否")
                                    .notOutSideClose()
                                    .onClickListener(is -> {
                                        if (is) {
                                            UpdateService.stop();
                                            MyToast.showToast("已取消更新");
                                        }
                                    });
                            tipDialog.show();
                            break;
                        case ACTION_CHANGE:
                            if (tipDialog != null) {
                                tipDialog.dismiss();
                            }
                            manager.notify(notifyId, builder
                                    .setContentIntent(getPendingIntent())
                                    .build());
                            break;
                        case ACTION_SET_UP:
                            BaseActivity<?> activity = (BaseActivity<?>) App.instance.getTopActivity();
                            activity.startActivity(createSetupIntent());
                            break;
                    }
                }
            };
            IntentFilter filter = new IntentFilter();
            filter.addAction(UpdateService.ACTION_CANCEL);
            filter.addAction(UpdateService.ACTION_CHANGE);
            filter.addAction(UpdateService.ACTION_SET_UP);
            registerReceiver(receiver, filter);
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            startForeground(notifyId, builder.build());
            manager.notify(notifyId, builder.build());
            progress = 1;
            String version = intent.getStringExtra("version");
            String fileName = version + ".apk";
            apkFile = new File(DirUtils.getDownLoadDir(), fileName);
            String url = intent.getStringExtra("url");
            DirUtils.downLoad(apkFile.getPath(), url, new DirUtils.OnDownLoadListener() {
                @Override
                public void onProgress(int p) {
                    LogUtils.i("下载中" + p + "," + DirUtils.fileSize(apkFile.length()));
                    manager.notify(notifyId, builder.setContentText("下载中" + p + "%").build());
                    progress = p;
                    MessageListener.callActionBack(Code.UPDATE, progress);
                }
    
                @Override
                public void onFinish(File file) {
                    LogUtils.i("下载完成");
                    manager.notify(notifyId, builder
                            .setContentTitle(App.instance.setAppName() + "新版" + version + "已就绪")
                            .setContentText("如未自动安装,请点击这里开始安装")
                            .setContentIntent(getSetupIntent())
                            .build());
                    progress = 100;
                    MessageListener.callActionBack(Code.UPDATE, progress);
                    TipDialog.create(App.instance.getTopActivity())
                            .title("新版" + intent.getStringExtra("version") + "下载成功")
                            .content("是否立即安装更新")
                            .setSureText("立即安装")
                            .setCancelText("取消安装")
                            .notOutSideClose()
                            .onClickListener(is -> {
                                if (is) {
                                    UpdateService.sendSetUp();
                                }
                            }).show();
                }
    
                @Override
                public void onCancel() {
                    LogUtils.i("下载已取消");
                    manager.cancel(notifyId);
                    progress = 0;
                    MessageListener.callActionBack(Code.UPDATE, progress);
                }
    
                @Override
                public void onError(String error) {
                    LogUtils.e("下载异常" + error);
                    manager.cancel(notifyId);
                    progress = 0;
                    MessageListener.callActionBack(Code.UPDATE, progress);
                }
            });
            //“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
            return START_NOT_STICKY;
        }
    
        private PendingIntent getPendingIntent() {
            if (progress == 100) {
                LogUtils.i("安装PendingIntent");
                return getSetupIntent();
            } else if (App.instance.isForeground()) {
                LogUtils.i("取消下载PendingIntent");
                return getCancelIntent();
            } else {
                LogUtils.i("主页PendingIntent");
                return getMainIntent();
            }
        }
    
        private PendingIntent getCancelIntent() {
            Intent intent = new Intent(ACTION_CANCEL);
            return PendingIntent.getBroadcast(this, 0, intent,
                    PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
        }
    
        private PendingIntent getMainIntent() {
            Class<?> mainClass;
            try {
                mainClass = Class.forName("com.test.android.MainActivity.class");
            } catch (ClassNotFoundException e) {
                return null;
            }
            Intent intent = new Intent(this, mainClass);
    //        //有activity就直接返回,没有就新建
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
            return PendingIntent.getActivity(this, 0, intent,
                    PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
        }
    
        private PendingIntent getSetupIntent() {
            return PendingIntent.getActivity(this, 0, createSetupIntent(), PendingIntent.FLAG_IMMUTABLE);
        }
    
        private Intent createSetupIntent() {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.putExtra("showCancelTip", false);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            String extension = android.webkit.MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(apkFile).toString());
            String mimetype = android.webkit.MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
            //7.0以上需要
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                Uri uri = FileProvider.getUriForFile(this, App.authority, apkFile);
                intent.setDataAndType(uri, mimetype);
            } else {
                intent.setDataAndType(Uri.fromFile(apkFile), mimetype);
            }
            //有activity就直接返回,没有就新建
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
            return intent;
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            DirUtils.cancelDownload();
            //文件不为空且未完成下载,就删除文件
            if (apkFile != null && apkFile.exists() && progress != 100) {
                LogUtils.i("apk文件删除:" + apkFile.delete());
            }
            if (receiver != null) {
                unregisterReceiver(receiver);
            }
            if (tipDialog != null) {
                tipDialog.dismiss();
                tipDialog = null;
            }
            progress = 0;
            MessageListener.callActionBack(Code.UPDATE, 0);
        }
    }
    

    二、通过查到新版本后的操作,即准备更新的操作

    if (data.isNeedUpdate()) {
        TipDialog updateDialog;
        Activity context = App.instance.getTopActivity();
        if (data.foce == 1) {
            updateDialog = TipDialog.createSingle(context).notClose();
        } else {
            updateDialog = TipDialog.create(context).notOutSideClose();
        }
        LincTextView tv = ViewBuilder.builder12(context).pad(SizeUtils.dp(10f))
            createLincTextView();
        tv.setHtml(data.description);
        updateDialog.title("发现新版本v" + data.version).addView(tv)
            .setSureText("立即更新")
            .setCancelText("暂不更新")
            .onClickListener(is -> {
                if (is && !UpdateService.isDownloading()) {
                    UpdateService.start(data.version, data.url);
                }
            }).show();
            //申请安装权限
        String[] ps = new String[]{Manifest.permission.INSTALL_PACKAGES, Manifest.permission.REQUEST_INSTALL_PACKAGES};
        checkPermission(ps,null);
    } else if (showTip) {
        toast("已是最新版本");
    }
    

    方法isNeedUpdate()

        public boolean isNeedUpdate() {
            //LogUtils.i("新版:" + version + ",当前版本:" + App.version);
            return !TextUtils.isEmpty(version) && version.compareTo(App.version) > 0;
        }
    

    三、可选的优化

    到这里,配置就已经完成了,但每次点击通知栏,都是会弹出“是否取消更新”的弹窗,我们希望回到桌面时,点击通知栏是打开程序,代码如下
    逻辑解释如下:

    1.在您的应用程序Application中定义好逻辑“程序是否进入在前台”,此标识用于区分点击通知栏的操作
    2.应用前后台发生发变化时,会更改setContentIntent()内的值,发送不同的通知以达到上述效果

        @Override
        public void onActivityStarted(@NonNull Activity activity) {
            super.onActivityStarted(activity);
            if (!isForeground()) {
                UpdateService.sendChange();
            }
        }
    
        @Override
        public void onActivityStopped(@NonNull Activity activity) {
            super.onActivityStopped(activity);
            if (!isForeground()) {
                UpdateService.sendChange();
            }
        }
    

    相关文章

      网友评论

          本文标题:Android站内更新

          本文链接:https://www.haomeiwen.com/subject/hxzdkjtx.html