Android 通知栏提醒和桌面角标适配

2023-11-06 22:10

本文主要是介绍Android 通知栏提醒和桌面角标适配,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 实现后的显示效果(由于角标功能由各个厂商自己实现的,所以各个厂商的实现方法不一样)

备注:小米系统在进入应用后会隐藏角标的显示,只有当退出到桌面时去设置角标才会显示

git项目地址badgeNumber: Android 通知栏提醒和桌面角标适配 (gitee.com)

1、先判断通知权限是否开启

    private void initNoticePermission() {if (!NotifyManagerUtils.isNotifyEnabled(this)) {AlertDialog dialog = new AlertDialog.Builder(this).setMessage("当前通知权限未开启,是否前往打开").setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {NotifyManagerUtils.openNotificationSettingsForApp(MainActivity.this);}}).setNegativeButton("取消", null).create();dialog.show();}}

上面用到的工具类

NotifyManagerUtils
import android.annotation.SuppressLint;
import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.os.Build;import java.lang.reflect.Field;
import java.lang.reflect.Method;/*** 判断通知权限并跳转的工具类*/
public class NotifyManagerUtils {private static final String CHECK_OP_NO_THROW = "checkOpNoThrow";private static final String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";//调用该方法获取是否开启通知栏权限public static boolean isNotifyEnabled(Context context) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {return isEnableV26(context);} else {return isEnabledV19(context);}}/*** 8.0以下判断** @param context api19  4.4及以上判断* @return*/private static boolean isEnabledV19(Context context) {AppOpsManager mAppOps =(AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);ApplicationInfo appInfo = context.getApplicationInfo();String pkg = context.getApplicationContext().getPackageName();int uid = appInfo.uid;Class appOpsClass;try {appOpsClass = Class.forName(AppOpsManager.class.getName());Method checkOpNoThrowMethod =appOpsClass.getMethod(CHECK_OP_NO_THROW,Integer.TYPE, Integer.TYPE, String.class);Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION);int value = (Integer) opPostNotificationValue.get(Integer.class);return ((Integer) checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg) ==AppOpsManager.MODE_ALLOWED);} catch (Exception e) {e.printStackTrace();return true;}}/*** 8.0及以上通知权限判断** @param context* @return*/private static boolean isEnableV26(Context context) {ApplicationInfo appInfo = context.getApplicationInfo();String pkg = context.getApplicationContext().getPackageName();int uid = appInfo.uid;try {NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);@SuppressLint("DiscouragedPrivateApi")Method sServiceField = notificationManager.getClass().getDeclaredMethod("getService");sServiceField.setAccessible(true);Object sService = sServiceField.invoke(notificationManager);Method method = null;if (sService != null) {method = sService.getClass().getDeclaredMethod("areNotificationsEnabledForPackage", String.class, Integer.TYPE);method.setAccessible(true);}return (boolean) method.invoke(sService, pkg, uid);} catch (Exception e) {return true;}}/*** 打开通知权限** @param context*/public static void openNotificationSettingsForApp(Context context) {// Links to this app's notification settings.if (isNotifyEnabled(context))return;Intent intent = new Intent();intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");intent.putExtra("app_package", context.getPackageName());intent.putExtra("app_uid", context.getApplicationInfo().uid);// for Android 8 and aboveintent.putExtra("android.provider.extra.APP_PACKAGE", context.getPackageName());context.startActivity(intent);}
}

2、开启通知栏和显示角标的方法

/*** 参数context,count:角标数字,“title”:通知栏的标题,“info”:通知栏的内容* 不需要通知栏的话可以后面两个参数不加*/
BadgeNumberManager.getInstance().setBadgeNumber(MainActivity.this, count, "title", "info");

上面用到的工具类

BadgeNumberManager
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;import androidx.core.app.NotificationCompat;import org.ismarter.zxyq.R;
import org.ismarter.zxyq.activity.MainActivity;/*** 应用桌面角标设置的管理类* Created by zlq on 2017 17/8/23 14:50.*/public class BadgeNumberManager {private final static int NOTICI_ID = 1;private static BadgeNumberManager manager;private NotificationManager notificationManager;private Notification notification;private BadgeNumberManager() {}public static BadgeNumberManager getInstance() {if (manager == null) {synchronized (BadgeNumberManager.class) {if (manager == null) {manager = new BadgeNumberManager();}}}return manager;}private static final BadgeNumberManager.Impl IMPL;/*** 设置应用在桌面上显示的角标数字** @param number 显示的数字*/public void setBadgeNumber(Context context, int number) {IMPL.setBadgeNumber(context, number);}/*** 设置应用在桌面上显示的角标数字** @param number 显示的数字*/public void setBadgeNumber(Context context, int number, String title, String desc) {setNotification(context, number, title, desc);if (IMPL instanceof ImplXiaoMi || IMPL instanceof ImplBase) {IMPL.setBadgeNumber(notification, number);} else {IMPL.setBadgeNumber(context, number);}}public void setNotification(Context context, int number, String title, String desc) {notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {String channelId = "approval_message_id";String channelName = "新增待审批消息通知";NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);channel.setShowBadge(true);channel.setDescription("收到新的待审批消息时使用的通知类别");notificationManager.createNotificationChannel(channel);}Intent intent = new Intent(context, MainActivity.class);intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);notification = new NotificationCompat.Builder(context, "approval_message_id").setContentTitle(title).setContentText(desc).setWhen(System.currentTimeMillis()).setSmallIcon(R.drawable.icon).setAutoCancel(true).setChannelId("approval_message_id").setNumber(number).setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL).setContentIntent(pendingIntent)//通知栏点击进入的页面.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)//设置将从系统默认值继承哪些通知属性 基本就是用来设置是否通知音效或者震动.setSound(alarmSound).setVibrate(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400}) //自定义震动的频率.setTicker(desc)//收到通知后从顶部弹出精简版通知.build();//取消掉上一条通知消息notificationManager.cancel(NOTICI_ID);notificationManager.notify(NOTICI_ID, notification);}public void cancleNotification() {if (notificationManager != null) {notificationManager.cancel(NOTICI_ID);}}interface Impl {void setBadgeNumber(Context context, int number);void setBadgeNumber(Notification notification, int number);}static class ImplHuaWei implements Impl {@Overridepublic void setBadgeNumber(Context context, int number) {BadgeNumberManagerHuaWei.setBadgeNumber(context, number);}@Overridepublic void setBadgeNumber(Notification notification, int number) {}}static class ImplXiaoMi implements Impl {@Overridepublic void setBadgeNumber(Context context, int number) {}@Overridepublic void setBadgeNumber(Notification notification, int number) {//小米机型的桌面应用角标API跟通知绑定在一起了,所以单独做处理BadgeNumberManagerXiaoMi.setBadgeNumber(notification, number);}}static class ImplVIVO implements Impl {@Overridepublic void setBadgeNumber(Context context, int number) {BadgeNumberManagerVIVO.setBadgeNumber(context, number);}@Overridepublic void setBadgeNumber(Notification notification, int number) {}}static class ImplOPPO implements Impl {@Overridepublic void setBadgeNumber(Context context, int number) {BadgeNumberManagerOPPO.setBadgeNumber(context, number);}@Overridepublic void setBadgeNumber(Notification notification, int number) {}}static class ImplSAMSUNG implements Impl {@Overridepublic void setBadgeNumber(Context context, int number) {BadgeNumberManagerSAMSUNG.setBadgeNumber(context, number);}@Overridepublic void setBadgeNumber(Notification notification, int number) {}}static class ImplSONY implements Impl {@Overridepublic void setBadgeNumber(Context context, int number) {BadgeNumberManagerSONY.setBadgeNumber(context, number);}@Overridepublic void setBadgeNumber(Notification notification, int number) {}}static class ImplLENOVO implements Impl {@Overridepublic void setBadgeNumber(Context context, int number) {BadgeNumberManagerLENOVO.setBadgeNumber(context, number);}@Overridepublic void setBadgeNumber(Notification notification, int number) {}}static class ImplBase implements Impl {@Overridepublic void setBadgeNumber(Context context, int number) {}@Overridepublic void setBadgeNumber(Notification notification, int number) {BadgeNumberManagerXiaoMi.setBadgeNumber(notification, number);}}static {String manufacturer = Build.MANUFACTURER;if (manufacturer.equalsIgnoreCase(MobileBrand.HUAWEI)) {IMPL = new ImplHuaWei();//华为} else if (manufacturer.equalsIgnoreCase(MobileBrand.XIAOMI)) {IMPL = new ImplXiaoMi();//小米} else if (manufacturer.equalsIgnoreCase(MobileBrand.VIVO)) {IMPL = new ImplVIVO();//vivo} else if (manufacturer.equalsIgnoreCase(MobileBrand.OPPO)) {IMPL = new ImplOPPO();//oppo} else if (manufacturer.equalsIgnoreCase(MobileBrand.SAMSUNG)) {IMPL = new ImplSAMSUNG();//三星} else if (manufacturer.equalsIgnoreCase(MobileBrand.SONY)) {IMPL = new ImplSONY();//索尼} else if (manufacturer.equalsIgnoreCase(MobileBrand.LENOVO)) {IMPL = new ImplLENOVO();//联想} else {IMPL = new ImplBase();}}public static String getLauncherClassName(Context context) {ComponentName launchComponent = getLauncherComponentName(context);if (launchComponent == null) {return "";} else {return launchComponent.getClassName();}}public static ComponentName getLauncherComponentName(Context context) {Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());if (launchIntent != null) {return launchIntent.getComponent();} else {return null;}}
}
MobileBrand
/*** 手机的 Build.MANUFACTURER 常量* Created by zlq on 2017 17/8/22 18:08.*/public class MobileBrand {public final static String HUAWEI = "Huawei";   //华为public final static String MEIZU = "Meizu";     //魅族public final static String XIAOMI = "Xiaomi";   //小米public final static String SONY = "Sony";       //索尼public final static String OPPO = "OPPO";       //OPPOpublic final static String VIVO = "vivo";       //VIVOpublic final static String SAMSUNG = "samsung"; //三星public final static String LG = "LG";           //LGpublic final static String LETV = "Letv";       //乐视public final static String ZTE = "ZTE";         //中兴public final static String YULONG = "YuLong";   //酷派public final static String LENOVO = "LENOVO";   //联想}
BadgeNumberManagerHuaWei
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;/*** 华为机型的桌面角标设置管理类* Created by zlq on 2017 17/8/23 16:35.*/public class BadgeNumberManagerHuaWei {/*** 设置应用的桌面角标,已在一些华为手机上测试通过,但是无法保证在所有华为手机上都生效** @param context context* @param number  角标显示的数字*/public static void setBadgeNumber(Context context, int number) {try {if (number < 0) number = 0;Bundle bundle = new Bundle();bundle.putString("package", context.getPackageName());String launchClassName = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).getComponent().getClassName();bundle.putString("class", launchClassName);bundle.putInt("badgenumber", number);context.getContentResolver().call(Uri.parse("content://com.huawei.android.launcher.settings/badge/"), "change_badge", null, bundle);} catch (Exception e) {e.printStackTrace();}}
}
BadgeNumberManagerLENOVO
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;import java.util.ArrayList;/*** 联想机型的桌面角标设置管理类* Created by zlq on 2017 17/8/23 16:35.*/public class BadgeNumberManagerLENOVO {public static boolean setBadgeNumber(Context context, int count) {try {Bundle extra = new Bundle();ArrayList<String> ids = new ArrayList<>();// 以列表形式传递快捷方式id,可以添加多个快捷方式id// ids这个参数可以为空或者“null”表示对主图标进行角标标记
//        ids.add("custom_id_1");
//        ids.add("custom_id_2");extra.putStringArrayList("app_shortcut_custom_id", ids);extra.putInt("app_badge_count", count);Uri contentUri = Uri.parse("content://com.android.badge/badge");Bundle bundle = context.getContentResolver().call(contentUri, "setAppBadgeCount", null,extra);return bundle != null;} catch (Exception e) {e.printStackTrace();return false;}}
}
BadgeNumberManagerOPPO
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;import java.util.List;/*** OPPO机型的桌面角标设置管理类* Created by zlq on 2017 17/8/23 16:35.*/public class BadgeNumberManagerOPPO {public static void setBadgeNumber(Context context, int number) {try {if (number == 0) {number = -1;}Intent intent = new Intent("com.oppo.unsettledevent");intent.putExtra("pakeageName", context.getPackageName());intent.putExtra("number", number);intent.putExtra("upgradeNumber", number);if (canResolveBroadcast(context, intent)) {context.sendBroadcast(intent);} else {try {Bundle extras = new Bundle();extras.putInt("app_badge_count", number);context.getContentResolver().call(Uri.parse("content://com.android.badge/badge"), "setAppBadgeCount", null, extras);} catch (Throwable th) {Log.e("OPPO" + " Badge error", "unable to resolve intent: " + intent.toString());}}} catch (Exception e) {e.printStackTrace();Log.e("OPPO" + " Badge error", "set Badge failed");}}public static boolean canResolveBroadcast(Context context, Intent intent) {PackageManager packageManager = context.getPackageManager();List<ResolveInfo> receivers = packageManager.queryBroadcastReceivers(intent, 0);return receivers != null && receivers.size() > 0;}
}
BadgeNumberManagerSAMSUNG
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;/*** 三星机型的桌面角标设置管理类* Created by zlq on 2017 17/8/23 16:35.*/public class BadgeNumberManagerSAMSUNG {public static void setBadgeNumber(Context context, int count) {String launcherClassName = BadgeNumberManager.getLauncherClassName(context);if (TextUtils.isEmpty(launcherClassName)) {return;}Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE");intent.putExtra("badge_count", count);intent.putExtra("badge_count_package_name", context.getPackageName());intent.putExtra("badge_count_class_name", launcherClassName);context.sendBroadcast(intent);}
}
BadgeNumberManagerSONY
import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;/*** 索尼机型的桌面角标设置管理类* Created by zlq on 2017 17/8/23 16:35.*/public class BadgeNumberManagerSONY {public static void setBadgeNumber(Context context, int count) {String launcherClassName = BadgeNumberManager.getLauncherClassName(context);if (TextUtils.isEmpty(launcherClassName)) {return;}try {//官方给出方法ContentValues contentValues = new ContentValues();contentValues.put("badge_count", count);contentValues.put("package_name", context.getPackageName());contentValues.put("activity_name", launcherClassName);SonyAsyncQueryHandler asyncQueryHandler = new SonyAsyncQueryHandler(context.getContentResolver());asyncQueryHandler.startInsert(0, null, Uri.parse("content://com.sonymobile.home" +".resourceprovider/badge"), contentValues);} catch (Exception e) {try {//网上大部分使用方法Intent intent = new Intent("com.sonyericsson.home.action.UPDATE_BADGE");intent.putExtra("com.sonyericsson.home.intent.extra.badge.SHOW_MESSAGE", count > 0);intent.putExtra("com.sonyericsson.home.intent.extra.badge.ACTIVITY_NAME",launcherClassName);intent.putExtra("com.sonyericsson.home.intent.extra.badge.MESSAGE", String.valueOf(count));intent.putExtra("com.sonyericsson.home.intent.extra.badge.PACKAGE_NAME", context.getPackageName());context.sendBroadcast(intent);} catch (Exception e1) {e1.printStackTrace();}}}static class SonyAsyncQueryHandler extends AsyncQueryHandler {SonyAsyncQueryHandler(ContentResolver cr) {super(cr);}}
}
BadgeNumberManagerVIVO
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.os.Build;/*** vivo机型的桌面角标设置管理类* Created by zlq on 2017 17/8/23 16:35.*/public class BadgeNumberManagerVIVO {public static final int FLAG_RECEIVER_INCLUDE_BACKGROUND = 0x01000000;@SuppressLint("WrongConstant")public static void setBadgeNumber(Context context, int number) {try {Intent intent = new Intent("launcher.action.CHANGE_APPLICATION_NOTIFICATION_NUM");intent.putExtra("packageName", context.getPackageName());String launchClassName = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).getComponent().getClassName();intent.putExtra("className", launchClassName);intent.putExtra("notificationNum", number);if ((Build.VERSION.SDK_INT >= 26)) {intent.addFlags(FLAG_RECEIVER_INCLUDE_BACKGROUND);}context.sendBroadcast(intent);} catch (Exception e) {e.printStackTrace();}}
}
BadgeNumberManagerXiaoMi
import android.app.Notification;import java.lang.reflect.Field;
import java.lang.reflect.Method;/*** 小米机型的桌面角标设置管理类* Created by zlq on 2017 17/8/23 16:35.*/public class BadgeNumberManagerXiaoMi {public static void setBadgeNumber(Notification notification, int number) {try {Field field = notification.getClass().getDeclaredField("extraNotification");Object extraNotification = field.get(notification);Method method = extraNotification.getClass().getDeclaredMethod("setMessageCount", int.class);method.invoke(extraNotification, number);} catch (Exception e) {e.printStackTrace();}}
}

这篇关于Android 通知栏提醒和桌面角标适配的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/359331

相关文章

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

一文详解Java Condition的await和signal等待通知机制

《一文详解JavaCondition的await和signal等待通知机制》这篇文章主要为大家详细介绍了JavaCondition的await和signal等待通知机制的相关知识,文中的示例代码讲... 目录1. Condition的核心方法2. 使用场景与优势3. 使用流程与规范基本模板生产者-消费者示例

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

Android WebView的加载超时处理方案

《AndroidWebView的加载超时处理方案》在Android开发中,WebView是一个常用的组件,用于在应用中嵌入网页,然而,当网络状况不佳或页面加载过慢时,用户可能会遇到加载超时的问题,本... 目录引言一、WebView加载超时的原因二、加载超时处理方案1. 使用Handler和Timer进行超

鸿蒙开发搭建flutter适配的开发环境

《鸿蒙开发搭建flutter适配的开发环境》文章详细介绍了在Windows系统上如何创建和运行鸿蒙Flutter项目,包括使用flutterdoctor检测环境、创建项目、编译HAP包以及在真机上运... 目录环境搭建创建运行项目打包项目总结环境搭建1.安装 DevEco Studio NEXT IDE

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影