uni-app实现热更新、全量更新带状态栏进度提示

-----------------------------------uni-app--------------------------------------

checkAppVersion

// 版本更新
export function checkAppVersion(_t, isShowWarn = false) {
	// #ifdef APP-PLUS
	// 若是正在更新不执行
	if(_t.isShowModal || _t.isUpdate) return;
	const os_type = plus.os.name.toLowerCase();
	const app_version = plus.runtime.version;
	plus.runtime.getProperty(plus.runtime.appid, function(info) {
		uni.setStorageSync('VERSION', info.version);
		const res_version = info.version;
		const requestData = {
			osType: os_type,
			appVersion: app_version,
			resVersion: res_version
		}
		_t.$api.getAppVersion(requestData).then(res => {
			Log.d("版本信息:" + JSON.stringify(res));
			if (res.statusCode != 200 || !res.data.success) return;
			const data = res.data.result;
			if (data.isUpdate === 0) return;
			const app_version_db = data.appVersion;
			const res_version_db = data.resVersion;
			const app_url = data.appUrl;
			const res_url = data.resUrl;
			const app_version_desc = data.content;
			//大版本更新(涉及安卓壳子或壳子改动)
			if (app_version_db !== app_version && (parseInt(app_version.replace(/\./g, "")) <
					parseInt(app_version_db.replace(/\./g, "")))) {
				// 定义安卓apk存放路径
				const filename = "_downloads/park.apk";
				// 处理安装提示在本应用上方弹出导致下载弹窗重复弹出问题
				nativeJs("bridge", "getFileApkVersion", {
					path: plus.io.convertLocalFileSystemURL(filename)
				}, originAppVersion => {
					Log.d("原来存在的apk包版本:" + originAppVersion)
					if(parseInt(originAppVersion.replace(/\./g, "")) === parseInt(app_version_db.replace(/\./g, ""))) {
						// 如果原来存在的apk包版本比app版本高直接提示安装
						if(parseInt(originAppVersion.replace(/\./g, "")) > parseInt(app_version.replace(/\./g, ""))) {
							// 决定是否弹出安装,解决部分机型在应用界面弹出安装提示而重复提示问题
							nativeJs("bridge", "getFileCreatedTime", {
								path: plus.io.convertLocalFileSystemURL(filename)
							}, createdTime => {
								if(createdTime) {
									Log.d("现在时间" + new Date().getTime())
									Log.d("文件创建时间" + parseInt(createdTime))
									Log.d("现在时间与文件创建时间差" + (new Date().getTime() - parseInt(createdTime)))
									// 超过1分钟提示安装
									if(new Date().getTime() - parseInt(createdTime) > 60 * 1 * 1000) {
										_t.isShowModal = true;
										uni.showModal({ //提醒用户更新
											title: "版本更新",
											content: "是否立即更新",
											showCancel: false,
											complete: () => {
												_t.isShowModal = false;
											},
											success: res => {
												if(res.confirm) {
													plus.runtime.install(plus.io.convertLocalFileSystemURL(filename), //安装APP
													{
														force: true
													},
													function() {
														Log.d('安装旧包准备成功');
													},
													function() {
														Log.d('安装旧包准备失败');
													});
												}
											}
										})
									}
								}
							})
						}else {
							// 删除原来安装包缩小体积
							nativeJs("bridge", "deleteFile", {
								path: plus.io.convertLocalFileSystemURL(filename)
							});
						}
						return;
					}
					_t.isShowModal = true;
					uni.showModal({ //提醒用户更新  
						title: "版本更新",
						content: app_version_desc,
						showCancel: false,
						complete: () => {
							_t.isShowModal = false;
						},
						success: res => {
							if(res.confirm) {
								// plus.downloader.clear();
								Log.d("全量更新地址:" + app_url)
								// 清除下载任务
								if(_t.dtask) _t.dtask.abort();
								// 下载前清除以前下载的缓存,避免apk包累积应用变大
								nativeJs("bridge", "deleteFile", {
									path: plus.io.convertLocalFileSystemURL(filename)
								});
								_t.dtask = plus.downloader.createDownload(app_url, {
									method: "GET",
									filename //利用保存路径,实现下载文件的重命名
								},
								function(d, status){
									Log.d("createDownloaded下载完成" + JSON.stringify(d))
									if(status !== 200) {
										_t.isUpdate = false;
										// 清除下载任务
										_t.dtask.abort();
									}
								});
								_t.dtask.addEventListener("statechanged", function(task, status) {
									switch(task.state) {
								        case 1: // 开始  
								            break;
								        case 2: //已连接到服务器  
								            break;
								        case 3: // 已接收到数据  
								            const current = parseInt(100 * task.downloadedSize / task.totalSize);
								            nativeJs("notification", "setProgress", {
												current
											});
											break;
								        case 4: // 下载完成 
											nativeJs("notification", "compProgressNotification", {
												title: '下载完成'
											});
								            plus.runtime.install(plus.io.convertLocalFileSystemURL(task.filename), //安装APP  
								                {
								                    force: true
								                },
								                function() {
													Log.d('安装准备成功');
													_t.isUpdate = false;
								                },
								                function() {
								                    Log.d('安装准备失败');
													_t.isUpdate = false;
								                });
								            break;
								    }
								});
								nativeJs("notification", "init");
								_t.isUpdate = true;
								_t.dtask.start();
							}
						}
					})
				});
			} else {
				//小版本更新(uniapp中的改动)
				if (res_version_db !== res_version && (parseInt(res_version.replace(/\./g, "")) <
						parseInt(res_version_db.replace(/\./g, "")))) {
					uni.showLoading({
						title: '更新中...',
						mask: true
					});
					Log.d("热更新地址:" + res_url)
					_t.isUpdate = true;
					uni.downloadFile({
						url: res_url,
						success: (downloadResult) => {
							Log.d("补丁信息:" + JSON.stringify(downloadResult))
							if (downloadResult.statusCode === 200) {
								plus.runtime.install(downloadResult.tempFilePath, {
									force: true
								}, function() {
									Log.d('install success...');
									uni.hideLoading();
									_t.isUpdate = false;
									plus.runtime.restart();
									// 删除安装包
									nativeJs("bridge", "deleteFile", {
										path: plus.io.convertLocalFileSystemURL(downloadResult.tempFilePath)
									});
								}, function(e) {
									uni.hideLoading();
									_t.isUpdate = false;
									Log.d('install fail...' + JSON.stringify(e));
									// 删除安装包
									nativeJs("bridge", "deleteFile", {
										path: plus.io.convertLocalFileSystemURL(downloadResult.tempFilePath)
									});
								});
							} else {
								uni.hideLoading();
								_t.isUpdate = false;
							}
						},
						fail() {
							uni.hideLoading();
							_t.isUpdate = false;
						}
					});
				}
				if (isShowWarn && res_version_db === res_version && app_version_db ===
					app_version) {
					uni.showToast({
						title: '已是最新版本',
						icon: 'none',
						duration: 1000,
						mask: false
					});
				}
				if (isShowWarn && (parseInt(res_version.replace(/\./g, "")) > parseInt(
						res_version_db.replace(/\./g, "")) || parseInt(app_version.replace(
						/\./g, "")) > parseInt(app_version_db.replace(/\./g, "")))) {
					uni.showToast({
						title: '暂无新版本',
						icon: 'none',
						duration: 1000,
						mask: false
					});
				}
			}
		})
	});
	// #endif
}

nativeJs

// 通过uniapp自带一套执行
export function nativeJs(targetClass, method, params = {}, successCallback, errorCallback) {
	// #ifdef APP-PLUS
	return plus.bridge.exec(targetClass, method, [plus.bridge.callbackId(typeof successCallback ===
		'function' ? successCallback : null, typeof errorCallback === 'function' ? errorCallback :
		null), JSON.stringify(params)]);
	// #endif
}

-----------------------------------android--------------------------------------

BridgeForUniApp

package com.park;

import android.content.Intent;
import android.util.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.park.util.AppUtil;

import org.json.JSONArray;

import java.io.File;

import io.dcloud.common.DHInterface.IWebview;
import io.dcloud.common.DHInterface.StandardFeature;
import io.dcloud.common.util.JSUtil;

public class BridgeForUniApp extends StandardFeature {
    /**
     * h5调此跳转
     * @param pWebView
     * @param arr
     */
    public void goTargetActivity(IWebview pWebView, JSONArray arr){
        Intent intent = new Intent(pWebView.getContext(), RawActivity.class);
        intent.putExtra("CallBackID", arr.optString(0));
        JSONObject params = JSON.parseObject(arr.optString(1));
        intent.putExtra("access_token", params.getString("token"));
        Log.d("params", params.toJSONString());
        pWebView.getContext().startActivity(intent);
    }

    /**
     * 删除文件
     * @param pWebView
     * @param arr
     * @return
     */
    public Boolean deleteFile(IWebview pWebView, JSONArray arr){
        JSONObject params = JSON.parseObject(arr.optString(1));
        File file = new File(params.getString("path"));
        if(file.exists()) file.delete();
        Log.d("h5","删除文件成功" + params.getString("path"));
        return true;
    }

    /**
     * 获取apk版本号
     * @param pWebView
     * @param arr
     * @return
     */
    public void getFileApkVersion(IWebview pWebView, JSONArray arr){
        JSONObject params = JSON.parseObject(arr.optString(1));
        JSUtil.execCallback(pWebView, arr.optString(0), AppUtil.getFileApkVersion(pWebView.getActivity(), params.getString("path")), JSUtil.OK,false);
    }

    /**
     * 根据文件路径获取文件创建时间
     * @param pWebView
     * @param arr
     * @return
     */
    public void getFileCreatedTime(IWebview pWebView, JSONArray arr){
        JSONObject params = JSON.parseObject(arr.optString(1));
        File file = new File(params.getString("path"));
        if(!file.exists()) return;
        JSUtil.execCallback(pWebView, arr.optString(0), file.lastModified(), JSUtil.OK,false);
    }
}

DownloadProgress

package com.park;

import org.json.JSONArray;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.android.park.R;
import com.park.util.NotificationUtils;
import io.dcloud.common.DHInterface.IWebview;
import io.dcloud.common.DHInterface.StandardFeature;

/**
 * app下载进度
 * @author 蓝之静云
 */
public class DownloadProgress extends StandardFeature {
    static final int ids = 1000;
    // 通知工具栏
    NotificationUtils notificationUtils;

    public void init(IWebview pWebView, JSONArray array){
        if(null != notificationUtils) notificationUtils.clearNotification();
        notificationUtils = new NotificationUtils(pWebView.getActivity());
    }

    /**
     * 初始设置
     *
     * @param pWebView
     * @param array
     */
    public void setNotification(IWebview pWebView, JSONArray array) {
        JSONObject params = JSON.parseObject(array.optString(1));
        String title = params.getString("title");
        String content = params.getString("content");
        notificationUtils.sendNotification(ids, title, content, R.mipmap.ic_launcher);
    }

    /**
     * 进度显示
     *
     * @param pWebView
     * @param array
     */
    public void setProgress(IWebview pWebView, final JSONArray array) {
        JSONObject params = JSON.parseObject(array.optString(1));
        notificationUtils.setNotification(Integer.parseInt(params.getString("current")));
    }

    /**
     * 下载完成后
     *
     * @param pWebView
     * @param array
     */
    public void compProgressNotification(IWebview pWebView, JSONArray array) {
        JSONObject params = JSON.parseObject(array.optString(1));
        String title = params.getString("title");
        notificationUtils = new NotificationUtils(pWebView.getActivity());
        notificationUtils.sendNotification(ids, title, "请去安装体验吧", R.mipmap.ic_launcher);
    }
}

AppUtil

package com.park.util;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.util.Log;

import java.io.File;

/**
 * Created by lenovo on 2019/10/17.
 */

public class AppUtil {
	/**
	 * 获取apk文件的包信息
	 * @param context
	 * @param apkPath
	 * @return
	 */
	public static String getFileApkVersion(Context context, String apkPath) {
		File apkFile = new File(apkPath);
		if(!apkFile.exists()) return "";
		PackageManager pm = context.getPackageManager();
		PackageInfo info = pm.getPackageArchiveInfo(apkPath, PackageManager.GET_ACTIVITIES);
		if (info != null) {
			ApplicationInfo appInfo = info.applicationInfo;
			String packageName = appInfo.packageName;  //得到安装包名称
			String version = info.versionName;//获取安装包的版本号
			int versionCode = info.versionCode;
			try {
				return version;
			} catch (OutOfMemoryError e) {
				Log.d("yue-tag", "GetApkInfo: " + e);
			}
		}
		return "";
	}
}

NotificationUtils

package com.park.util;

import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.widget.RemoteViews;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;

import com.android.park.R;

import static android.app.Notification.VISIBILITY_SECRET;
import static androidx.core.app.NotificationCompat.PRIORITY_DEFAULT;

/**
 * <pre>
 *     @author WTY
 *     desc  : 通知栏工具类
 *     revise:
 * </pre>
 */
public class NotificationUtils extends ContextWrapper {

    public static final String CHANNEL_ID = "default";
    private static final String CHANNEL_NAME = "Default_Channel";
    private NotificationManager mManager;
    private int[] flags;

    public NotificationUtils(Context base) {
        super(base);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            //android 8.0以上需要特殊处理,也就是targetSDKVersion为26以上
            createNotificationChannel();
        }
    }

    @TargetApi(Build.VERSION_CODES.O)
    private void createNotificationChannel() {
        //第一个参数:channel_id
        //第二个参数:channel_name
        //第三个参数:设置通知重要性级别
        //注意:该级别必须要在 NotificationChannel 的构造函数中指定,总共要五个级别;
        //范围是从 NotificationManager.IMPORTANCE_NONE(0) ~ NotificationManager.IMPORTANCE_HIGH(4)
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME,
                NotificationManager.IMPORTANCE_LOW);
        channel.canBypassDnd();//是否绕过请勿打扰模式
        channel.enableLights(true);//是否在桌面icon右上角展示小红点
        channel.setLockscreenVisibility(VISIBILITY_SECRET);//锁屏显示通知
        channel.setLightColor(Color.RED);//闪关灯的灯光颜色
        channel.canShowBadge();//桌面launcher的消息角标
        channel.enableVibration(true);//是否允许震动
        channel.getAudioAttributes();//获取系统通知响铃声音的配置
        channel.getGroup();//获取通知取到组
        channel.setBypassDnd(true);//设置可绕过 请勿打扰模式
        channel.setSound(null, null);
        channel.setVibrationPattern(new long[]{100, 100, 200});//设置震动模式
        channel.shouldShowLights();//是否会有灯光
        channel.setShowBadge(true); //是否在久按桌面图标时显示此渠道的通知
        getManager().createNotificationChannel(channel);
    }

    /**
     * 获取创建一个NotificationManager的对象
     * @return                          NotificationManager对象
     */
    public NotificationManager getManager() {
        if (mManager == null) {
            mManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        }
        return mManager;
    }

    /**
     * 清空所有的通知
     */
    public void clearNotification(){
        getManager().cancelAll();
    }

    /**
     * 获取Notification
     * @param title                     title
     * @param content                   content
     */
    public Notification getNotification(String title, String content , int icon){
        Notification build;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            //android 8.0以上需要特殊处理,也就是targetSDKVersion为26以上
            //通知用到NotificationCompat()这个V4库中的方法。但是在实际使用时发现书上的代码已经过时并且Android8.0已经不支持这种写法
            Notification.Builder builder = getChannelNotification(title, content, icon);
            build = builder.build();
        } else {
            NotificationCompat.Builder builder = getNotificationCompat(title, content, icon);
            build = builder.build();
        }
        if (flags!=null && flags.length>0){
            for (int a=0 ; a<flags.length ; a++){
                build.flags |= flags[a];
            }
        }
        return build;
    }


    /**
     * 建议使用这个发送通知
     * 调用该方法可以发送通知
     * @param notifyId                  notifyId
     * @param title                     title
     * @param content                   content
     */
    public void sendNotification(int notifyId, String title, String content , int icon) {
        Notification build;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            //android 8.0以上需要特殊处理,也就是targetSDKVersion为26以上
            //通知用到NotificationCompat()这个V4库中的方法。但是在实际使用时发现书上的代码已经过时并且Android8.0已经不支持这种写法
            Notification.Builder builder = getChannelNotification(title, content, icon);
            build = builder.build();
        } else {
            NotificationCompat.Builder builder = getNotificationCompat(title, content, icon);
            build = builder.build();
        }
        if (flags!=null && flags.length>0){
            for (int a=0 ; a<flags.length ; a++){
                build.flags |= flags[a];
            }
        }
        getManager().notify(notifyId, build);
    }

    /**
     * 调用该方法可以发送通知
     * @param notifyId                  notifyId
     * @param title                     title
     * @param content                   content
     */
    public void sendNotificationCompat(int notifyId, String title, String content , int icon) {
        NotificationCompat.Builder builder = getNotificationCompat(title, content, icon);
        Notification build = builder.build();
        if (flags!=null && flags.length>0){
            for (int a=0 ; a<flags.length ; a++){
                build.flags |= flags[a];
            }
        }
        getManager().notify(notifyId, build);
    }


    private NotificationCompat.Builder getNotificationCompat(String title, String content, int icon) {
        NotificationCompat.Builder builder;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            builder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID);
        } else {
            //注意用下面这个方法,在8.0以上无法出现通知栏。8.0之前是正常的。这里需要增强判断逻辑
            builder = new NotificationCompat.Builder(getApplicationContext());
            builder.setPriority(PRIORITY_DEFAULT);
        }
        builder.setContentTitle(title);
        builder.setContentText(content);
        builder.setSmallIcon(icon);
        builder.setPriority(priority);
        builder.setOnlyAlertOnce(onlyAlertOnce);
        builder.setOngoing(ongoing);
        if (remoteViews!=null){
            builder.setContent(remoteViews);
        }
        if (intent!=null){
            builder.setContentIntent(intent);
        }
        if (ticker!=null && ticker.length()>0){
            builder.setTicker(ticker);
        }
        if (when!=0){
            builder.setWhen(when);
        }
        if (sound!=null){
            builder.setSound(sound);
        }
        if (defaults!=0){
            builder.setDefaults(defaults);
        }
        //点击自动删除通知
        builder.setAutoCancel(true);
        return builder;
    }


    @RequiresApi(api = Build.VERSION_CODES.O)
    private Notification.Builder getChannelNotification(String title, String content, int icon){
        Notification.Builder builder = new Notification.Builder(getApplicationContext(), CHANNEL_ID);
        Notification.Builder notificationBuilder = builder
                //设置标题
                .setContentTitle(title)
                //消息内容
                .setContentText(content)
                //设置通知的图标
                .setSmallIcon(icon)
                //让通知左右滑的时候是否可以取消通知
                .setOngoing(ongoing)
                //设置优先级
                .setPriority(priority)
                //是否提示一次.true - 如果Notification已经存在状态栏即使在调用notify函数也不会更新
                .setOnlyAlertOnce(onlyAlertOnce)
                .setAutoCancel(true);
        if (remoteViews!=null){
            //设置自定义view通知栏
            notificationBuilder.setContent(remoteViews);
        }
        if (intent!=null){
            notificationBuilder.setContentIntent(intent);
        }
        if (ticker!=null && ticker.length()>0){
            //设置状态栏的标题
            notificationBuilder.setTicker(ticker);
        }
        if (when!=0){
            //设置通知时间,默认为系统发出通知的时间,通常不用设置
            notificationBuilder.setWhen(when);
        }
        if (sound!=null){
            //设置sound
            notificationBuilder.setSound(sound);
        }
        if (defaults!=0){
            //设置默认的提示音
            notificationBuilder.setDefaults(defaults);
        }
        if (pattern!=null){
            //自定义震动效果
            notificationBuilder.setVibrate(pattern);
        }
        return notificationBuilder;
    }



    private boolean ongoing = false;
    private RemoteViews remoteViews = null;
    private PendingIntent intent = null;
    private String ticker = "";
    private int priority = Notification.PRIORITY_DEFAULT;
    private boolean onlyAlertOnce = false;
    private long when = 0;
    private Uri sound = null;
    private int defaults = 0;
    private long[] pattern = null;

    /**
     * 让通知左右滑的时候是否可以取消通知
     * @param ongoing                   是否可以取消通知
     * @return
     */
    public NotificationUtils setOngoing(boolean ongoing){
        this.ongoing = ongoing;
        return this;
    }

    /**
     * 设置自定义view通知栏布局
     * @param remoteViews               view
     * @return
     */
    public NotificationUtils setContent(RemoteViews remoteViews){
        this.remoteViews = remoteViews;
        return this;
    }

    /**
     * 设置内容点击
     * @param intent                    intent
     * @return
     */
    public NotificationUtils setContentIntent(PendingIntent intent){
        this.intent = intent;
        return this;
    }

    /**
     * 设置状态栏的标题
     * @param ticker                    状态栏的标题
     * @return
     */
    public NotificationUtils setTicker(String ticker){
        this.ticker = ticker;
        return this;
    }


    /**
     * 设置优先级
     * 注意:
     * Android 8.0以及上,在 NotificationChannel 的构造函数中指定,总共要五个级别;
     * Android 7.1(API 25)及以下的设备,还得调用NotificationCompat 的 setPriority方法来设置
     *
     * @param priority                  优先级,默认是Notification.PRIORITY_DEFAULT
     * @return
     */
    public NotificationUtils setPriority(int priority){
        this.priority = priority;
        return this;
    }

    /**
     * 是否提示一次.true - 如果Notification已经存在状态栏即使在调用notify函数也不会更新
     * @param onlyAlertOnce             是否只提示一次,默认是false
     * @return
     */
    public NotificationUtils setOnlyAlertOnce(boolean onlyAlertOnce){
        this.onlyAlertOnce = onlyAlertOnce;
        return this;
    }

    /**
     * 设置通知时间,默认为系统发出通知的时间,通常不用设置
     * @param when                      when
     * @return
     */
    public NotificationUtils setWhen(long when){
        this.when = when;
        return this;
    }

    /**
     * 设置sound
     * @param sound                     sound
     * @return
     */
    public NotificationUtils setSound(Uri sound){
        this.sound = sound;
        return this;
    }


    /**
     * 设置默认的提示音
     * @param defaults                  defaults
     * @return
     */
    public NotificationUtils setDefaults(int defaults){
        this.defaults = defaults;
        return this;
    }

    /**
     * 自定义震动效果
     * @param pattern                  pattern
     * @return
     */
    public NotificationUtils setVibrate(long[] pattern){
        this.pattern = pattern;
        return this;
    }

    /**
     * 设置flag标签
     * @param flags                     flags
     * @return
     */
    public NotificationUtils setFlags(int... flags){
        this.flags = flags;
        return this;
    }

    public void setNotification(int progress) {
        if (this==null){
            return;
        }
        Intent intent = new Intent();
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        RemoteViews remoteViews = new RemoteViews(this.getPackageName(), R.layout.remote_notification_view);
        remoteViews.setTextViewText(R.id.tvTitle, "正在下载:");
        remoteViews.setProgressBar(R.id.pb, 100, progress, false);
        NotificationManager manager = this.getManager();
        Notification notification = this.setContentIntent(pendingIntent)
                .setContent(remoteViews)
                .setFlags(Notification.FLAG_AUTO_CANCEL)
                .setOnlyAlertOnce(true)
                .getNotification("新消息", "应用开始更新", R.mipmap.ic_launcher);
        //下载成功或者失败
        if (progress == 100 || progress == -1) {
            this.clearNotification();
        } else {
            manager.notify(1, notification);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值