一、添加引用
请注意使用最新版
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);