本文主要是介绍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 通知栏提醒和桌面角标适配的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!