Android站内更新

一、添加引用

请注意使用最新版

api 'com.linc.android:base:0.2.22'

二、新建相关的类

①新建UpdateService继承BaseLincUpdateService

import android.os.Handler;
import android.os.Looper;
import androidx.annotation.NonNull;
import com.linc.android.base.update.BaseLincUpdateService;
import com.linc.android.base.update.LincCheckUpdateBean;
import com.lkl.linc.app.utils.MyToast;
import com.lkl.linc.app.utils.eventbus.EventBus;
import com.lkl.linc.app.utils.eventbus.EventData;
import com.lkl.linc.app.utils.log.LogUtils;
import java.io.File;

public class UpdateService extends BaseLincUpdateService {
    public static LincCheckUpdateBean checkUpdateBean;

    public static synchronized void checkUpdate(boolean showTip) {
        if (UpdateService.isDownloading()) {
            //如果正在进行下载,又调用了检查更新,那就弹出窗口
            if (checkUpdateBean == null) return;
            EventBus.get().send(Code.UpdateDialogShow);
        } else {
            Handler handler = new Handler(Looper.getMainLooper());
            OnValueCallBack<LincCheckUpdateBean> callBack = bean -> {
                if (bean != null && bean.isNeedUpdate()) {
                    checkUpdateBean = bean;
                    EventBus.get().send(Code.UpdateDialogShow);
                } else {
                    if (showTip) MyToast.showToast("已是最新版本");
                }
            };
            LincCheckUpdateBean.checkUpdateOnLine(handler, callBack);
            if (App.debug) {
                handler.postDelayed(() -> LincCheckUpdateBean.checkUpdateDebug(handler, 本地目录, callBack), 1000);
            }
        }
    }

    @NonNull
    @Override
    protected Class<?> onNotifyClass() {
        //通知栏点开后,需要弹出的界面
        try {
            return Class.forName(我的页面);
        } catch (Exception e) {
            return getClass();
        }
    }

    @Override
    protected int setSmallIcon() {
        //通知栏图标,注意是mipmap
        return android.R.mipmap.sym_def_app_icon;
    }

    @Override
    protected boolean onDownLoadProgress(int progress) {
        return false;
    }

    @Override
    protected boolean onDownLoadFinish(File file) {
        //不使用默认命令,发送show,弹窗即可,在show方法里面判断安装还是展示
        EventBus.get().send(EventData.build(Code.UpdateDialogShow, BaseLincUpdateService.OnDownLoadFinish));
        return true;
    }

    @Override
    protected void onErrorMessage(String error) {
        EventBus.get().send(Code.UpdateCancel);
        MyToast.showToast(error);
    }
}

②新建更新弹窗对话框

import android.app.Dialog;
import android.content.Context;
import android.os.CountDownTimer;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;

import com.linc.android.base.update.BaseLincUpdateDialog;
import com.linc.android.base.update.LincCheckUpdateBean;
import com.linc.android.loading.LoadingDialog;
import com.lkl.linc.app.utils.eventbus.EventBus;

public class UpdateDialog extends BaseLincUpdateDialog {

    private LoadingDialog loadingDialog;

    public UpdateDialog(@NonNull Context context, LincCheckUpdateBean bean) {
        super(context, bean);
    }


    @NonNull
    @Override
    protected int[] setMainColor() {
        //第0位是主题色,第1位是点击后的颜色,实现按钮点击效果
        return new int[]{ContextCompat.getColor(getContext(), R.color.main),
                ContextCompat.getColor(getContext(), R.color.mainLight3)};
    }

    @Override
    protected View.OnClickListener onCancelClickListener(boolean isForce) {
        //点击取消更新按钮的动作。如果是强制更新,取消后,需要停止服务并退出程序,否则只需要停止服务即可
        return v -> {
            if (isForce) {
                TipDialog.create(getContext()).title("此版本为强制更新的版本,如取消更新将直接关闭程序,是否取消?")
                        .setSureText("确定取消").setCancelText("暂不取消").onNoCloseClickListener((is, d) -> {
                            if (is) {
                                EventBus.get().send(Code.UpdateCancel);
                                UpdateService.stop();
                                loadingDialog = new LoadingDialog(getContext());
                                loadingDialog.setCancelable(false);
                                loadingDialog.show();
                                //留一点时间给程序删除资源
                                new CountDownTimer(1000, 1000) {

                                    @Override
                                    public void onTick(long left) {

                                    }

                                    @Override
                                    public void onFinish() {
                                        loadingDialog.dismiss();
                                        d.dismiss();
                                        App.exitOut();
                                    }
                                }.start();
                            } else {
                                d.dismiss();
                            }
                        }).show();
            } else {
                TipDialog.create(getContext()).title("确定取消更新?")
                        .setCancelText("暂不取消")
                        .setSureText("确定取消")
                        .onClickListener(is -> {
                            if (is) {
                                //停止服务
                                UpdateService.stop();
                                dismiss();
                                EventBus.get().send(Code.UpdateCancel);
                            }
                        }).show();

            }
        };
    }

    @Override
    protected void onCancelSetupCallActionBack(Dialog dialog) {

    }

    @NonNull
    @Override
    protected Class<?> setUpdateService() {
        //刚刚创建的UpdateService
        return UpdateService.class;
    }
}

三、添加权限和服务

①权限

    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
    <!--发送前台通知,需要的权限-->
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <!--安装应用需要的权限1,不需要动态申请-->
    <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
    <!--安装应用需要的权限2,不需要动态申请-->
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
    <!--写上就行,不需要动态申请-->
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
    <!--安卓15要写上这个权限(这里暂时用不到,可以不写)-->
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />

②添加服务

    <service
        android:name=".UpdateService"
        android:exported="false"
        android:foregroundServiceType="mediaPlayback" />

四、页面配置
①在baseActivity中添加检查更新的代码,并在有需要的地方,调用此方法

    protected void checkUpdate(boolean showTip) {
        if (updateDialog != null) {
            if (UpdateService.isDownloading()) {
                updateDialog.show();
                return;
            } else {
                updateDialog = null;
            }
        }
        getComPresenter().checkUpdate((b, i, s, data) -> {
            if (b) {
                if (data.isNeedUpdate()) {
                    //重点,这里需要赋值给服务里面的字段,以便于在弹窗时能读取到数据
                    UpdateService.checkUpdateBean = data;
                    updateDialog = new UpdateDialog(activity, data);
                    updateDialog.show();
                } else if (showTip) {
                    MyToast.showToast("已是最新版本");
                }
            } else {
                if (showTip) {
                    MyToast.showToast(s);
                }
            }
        });
    } 

②在baseActivity中添加code监听

    private UpdateDialog updateDialog;
    @Override
    public void onMessage(String type, @NonNull Object obj) {
        super.onMessage(type, obj);
        switch (type) {
            case Code.UpdateCancel:
                if (updateDialog != null && updateDialog.isShowing()) {
                    updateDialog.dismiss();
                }
                updateDialog = null;
                break;
            case Code.UpdateDialogShow:
                if (!isActive && App.instance.isForeground())  return;///确保不会有多个弹窗,或者去掉的话,就是所有Activity都弹窗,点击取消安装时,需要发送UpdateCancel通知即可
                if (updateDialog == null) {
                    updateDialog = new UpdateDialog(this, UpdateService.checkUpdateBean);
                }
                if (BaseLincUpdateService.OnDownLoadFinish.equals(obj) && updateDialog.isShowing()) {
                    //如果是下载完成,并且对话框正在展示,就发送安装命令(必须延迟发送,否则无响应)
                    handler.postDelayed(BaseLincUpdateService::sendSetUp, 1000);
                } else {
                    //如果没有下载完成,就展示对话框即可
                    updateDialog.show();
                }
                break;
        }
    }

五、特别注意

1、要在程序标签下添加FileProvider

        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
        </provider>

2、在退出登录时,需要调用 UpdateService.stop() 以停止服务

UpdateService.stop()

3、检查更新的时候,如果已经有正在更新的服务了,就直接弹窗好了

    UpdateService.checkUpdate(false);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容