1、先大致说下主流厂商目前对角标的支持吧、
华为:支持、
小米:支持、
vivo:中高端支持、老版本不支持(7.0、8.0设备)、
oppo:支持红点角标但无数字、仅特定应用支持角标数字(微信? qq 0.0!!)、
三星:支持、
小众设备暂未统计;
2、小米、vivo oppo 适配注意的点(敲黑板)
先说小米:小米角标和通知相关、即通知数量==角标显示数量、官方似乎也意识到了此设计的缺陷、提出了解决方案:https://dev.mi.com/console/doc/detail?pId=939。
通知消失/app重启 角标都会消失。
oppo:同小米
小米 vivo oppo:需要在通知权限中、开启圆角通知(不同设备叫法不一样、注意区分)。
3、相关代码
3-1、角标设置类(核心)
public class BadgerUtils {
public static int notificationId = 100;
//xiaomi oppo 通用
public static void setNotificationBadge(Context context, int count) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService
(Context.NOTIFICATION_SERVICE);
if (notificationManager == null) {
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// 8.0之后添加角标需要NotificationChannel
NotificationChannel channel = new NotificationChannel("badge", "齐齐乐通知角标",
NotificationManager.IMPORTANCE_DEFAULT);
channel.setShowBadge(true);
channel.enableLights(false);
channel.enableVibration(false);
channel.setSound(null, null);
notificationManager.createNotificationChannel(channel);
}
if (!(context instanceof Activity)) {
Log.d("BadgerUtils", "xiaomi or oppo not set On MainActivity、it's wrong");
return;
}
String content=count==0?"暂无通知":"您有" + count + "条未读消息";
Activity activity = (Activity) context;
Intent intent = new Intent(context, activity.getClass());
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
Notification notification = new NotificationCompat.Builder(context, "badge")
.setContentTitle("齐齐乐")
.setContentText(content)
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap
.ic_launcher))
.setSmallIcon(R.mipmap.ic_launcher)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setChannelId("badge")
.setNumber(count)
.setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL).build();
// 小米
try {
Field field = notification.getClass().getDeclaredField("extraNotification");
Object extraNotification = field.get(notification);
Method method = extraNotification.getClass().getDeclaredMethod("extraNotification", int.class);
method.invoke(extraNotification, count);
} catch (Exception e) {
e.printStackTrace();
}
notificationManager.notify(notificationId++, notification);
}
//华为
public static boolean setHuaweiBadge(Context context, int count) {
try {
String launchClassName = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).getComponent().getClassName();
Bundle bundle = new Bundle();
bundle.putString("package", context.getPackageName());
bundle.putString("class", launchClassName);
bundle.putInt("badgenumber", count);
context.getContentResolver().call(Uri.parse("content://com.huawei.android.launcher" +
".settings/badge/"), "change_badge", null, bundle);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
//vivo
public static void setVivoBadge(Context context, int count) {
try {
String launchClassName = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).getComponent().getClassName();
Intent intent = new Intent();
intent.setAction("launcher.action.CHANGE_APPLICATION_NOTIFICATION_NUM");
intent.putExtra("packageName", context.getPackageName());
intent.putExtra("className", launchClassName);
intent.putExtra("notificationNum", count);
/* if (Build.VERSION.SDK_INT>=26) {
intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
}*/
context.sendBroadcast(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
//三星
public static void setSamsungBadge(Context context, int count) {
try {
String launchClassName = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).getComponent().getClassName();
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", launchClassName);
context.sendBroadcast(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
// 联想ZUK(支持)
public static void setZukBadge(Context context, int count) {
try {
Bundle extra = new Bundle();
ArrayList<String> ids = new ArrayList<>();
// 以列表形式传递快捷方式id,可以添加多个快捷方式id
// 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);
} catch (Exception e) {
e.printStackTrace();
}
}
//HTC
public static void setHTCBadge(Context context, int count) {
try {
ComponentName launcherComponentName = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).getComponent();
Intent intent1 = new Intent("com.htc.launcher.action.SET_NOTIFICATION");
intent1.putExtra("com.htc.launcher.extra.COMPONENT", launcherComponentName
.flattenToShortString());
intent1.putExtra("com.htc.launcher.extra.COUNT", count);
context.sendBroadcast(intent1);
Intent intent2 = new Intent("com.htc.launcher.action.UPDATE_SHORTCUT");
intent2.putExtra("packagename", launcherComponentName.getPackageName());
intent2.putExtra("count", count);
context.sendBroadcast(intent2);
} catch (Exception e) {
e.printStackTrace();
}
}
//索尼
public static void setSonyBadge(Context context, int count) {
try {
//官方给出方法
String launchClassName = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).getComponent().getClassName();
ContentValues contentValues = new ContentValues();
contentValues.put("badge_count", count);
contentValues.put("package_name", context.getPackageName());
contentValues.put("activity_name", launchClassName);
SonyAsyncQueryHandler asyncQueryHandler = new SonyAsyncQueryHandler(context
.getContentResolver());
asyncQueryHandler.startInsert(0, null, Uri.parse("content://com.sonymobile.home" +
".resourceprovider/badge"), contentValues);
} catch (Exception e) {
try {
//网上大部分使用方法
String launchClassName = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).getComponent().getClassName();
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",
launchClassName);
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);
}
}
}
3-2? 角标管理类、省去讨厌机型的判断。
public class BadgerManger {
public static void addBadgerNum(Context context, int num) {
if (RomUtils.isHuawei()) {
BadgerUtils.setHuaweiBadge(context, num);
} else if (RomUtils.isVivo()) {
BadgerUtils.setVivoBadge(context, num);
} else if (RomUtils.isXiaomi() || RomUtils.isOppo()) {
BadgerUtils.setNotificationBadge(context, num);
} else if (RomUtils.isSamsung()) {
BadgerUtils.setSamsungBadge(context, num);
} else if (RomUtils.isLenovo()) {
BadgerUtils.setZukBadge(context, num);
} else if (RomUtils.isHtc()) {
BadgerUtils.setHTCBadge(context, num);
} else if (RomUtils.isSony()) {
BadgerUtils.setSonyBadge(context, num);
}
}
public static void badgerRemoveAll(Context context) {
if (RomUtils.isHuawei()) {
BadgerUtils.setHuaweiBadge(context, 0);
} else if (RomUtils.isVivo()) {
BadgerUtils.setVivoBadge(context, 0);
} else if (RomUtils.isXiaomi() || RomUtils.isOppo()) {
BadgerUtils.setNotificationBadge(context, 0);
} else if (RomUtils.isSamsung()) {
BadgerUtils.setSamsungBadge(context, 0);
} else if (RomUtils.isLenovo()) {
BadgerUtils.setZukBadge(context, 0);
} else if (RomUtils.isHtc()) {
BadgerUtils.setHTCBadge(context, 0);
} else if (RomUtils.isSony()) {
BadgerUtils.setSonyBadge(context, 0);
}
}
}
3-3 机型判断工具类 无需关注、仅在3-2 中使用到
public final class RomUtils {
private static final String[] ROM_HUAWEI = {"huawei"};
private static final String[] ROM_VIVO = {"vivo"};
private static final String[] ROM_XIAOMI = {"xiaomi"};
private static final String[] ROM_OPPO = {"oppo"};
private static final String[] ROM_LEECO = {"leeco", "letv"};
private static final String[] ROM_360 = {"360", "qiku"};
private static final String[] ROM_ZTE = {"zte"};
private static final String[] ROM_ONEPLUS = {"oneplus"};
private static final String[] ROM_NUBIA = {"nubia"};
private static final String[] ROM_COOLPAD = {"coolpad", "yulong"};
private static final String[] ROM_LG = {"lg", "lge"};
private static final String[] ROM_GOOGLE = {"google"};
private static final String[] ROM_SAMSUNG = {"samsung"};
private static final String[] ROM_MEIZU = {"meizu"};
private static final String[] ROM_LENOVO = {"lenovo"};
private static final String[] ROM_SMARTISAN = {"smartisan"};
private static final String[] ROM_HTC = {"htc"};
private static final String[] ROM_SONY = {"sony"};
private static final String[] ROM_GIONEE = {"gionee", "amigo"};
private static final String[] ROM_MOTOROLA = {"motorola"};
private static final String VERSION_PROPERTY_HUAWEI = "ro.build.version.emui";
private static final String VERSION_PROPERTY_VIVO = "ro.vivo.os.build.display.id";
private static final String VERSION_PROPERTY_XIAOMI = "ro.build.version.incremental";
private static final String VERSION_PROPERTY_OPPO = "ro.build.version.opporom";
private static final String VERSION_PROPERTY_LEECO = "ro.letv.release.version";
private static final String VERSION_PROPERTY_360 = "ro.build.uiversion";
private static final String VERSION_PROPERTY_ZTE = "ro.build.MiFavor_version";
private static final String VERSION_PROPERTY_ONEPLUS = "ro.rom.version";
private static final String VERSION_PROPERTY_NUBIA = "ro.build.rom.id";
private final static String UNKNOWN = "unknown";
private static RomInfo bean = null;
private RomUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
/**
* Return whether the rom is made by huawei.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isHuawei() {
return ROM_HUAWEI[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by vivo.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isVivo() {
return ROM_VIVO[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by xiaomi.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isXiaomi() {
return ROM_XIAOMI[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by oppo.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isOppo() {
return ROM_OPPO[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by leeco.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isLeeco() {
return ROM_LEECO[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by 360.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean is360() {
return ROM_360[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by zte.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isZte() {
return ROM_ZTE[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by oneplus.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isOneplus() {
return ROM_ONEPLUS[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by nubia.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isNubia() {
return ROM_NUBIA[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by coolpad.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isCoolpad() {
return ROM_COOLPAD[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by lg.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isLg() {
return ROM_LG[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by google.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isGoogle() {
return ROM_GOOGLE[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by samsung.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isSamsung() {
return ROM_SAMSUNG[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by meizu.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isMeizu() {
return ROM_MEIZU[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by lenovo.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isLenovo() {
return ROM_LENOVO[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by smartisan.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isSmartisan() {
return ROM_SMARTISAN[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by htc.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isHtc() {
return ROM_HTC[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by sony.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isSony() {
return ROM_SONY[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by gionee.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isGionee() {
return ROM_GIONEE[0].equals(getRomInfo().name);
}
/**
* Return whether the rom is made by motorola.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isMotorola() {
return ROM_MOTOROLA[0].equals(getRomInfo().name);
}
/**
* Return the rom's information.
*
* @return the rom's information
*/
public static RomInfo getRomInfo() {
if (bean != null) return bean;
bean = new RomInfo();
final String brand = getBrand();
final String manufacturer = getManufacturer();
if (isRightRom(brand, manufacturer, ROM_HUAWEI)) {
bean.name = ROM_HUAWEI[0];
String version = getRomVersion(VERSION_PROPERTY_HUAWEI);
String[] temp = version.split("_");
if (temp.length > 1) {
bean.version = temp[1];
} else {
bean.version = version;
}
return bean;
}
if (isRightRom(brand, manufacturer, ROM_VIVO)) {
bean.name = ROM_VIVO[0];
bean.version = getRomVersion(VERSION_PROPERTY_VIVO);
return bean;
}
if (isRightRom(brand, manufacturer, ROM_XIAOMI)) {
bean.name = ROM_XIAOMI[0];
bean.version = getRomVersion(VERSION_PROPERTY_XIAOMI);
return bean;
}
if (isRightRom(brand, manufacturer, ROM_OPPO)) {
bean.name = ROM_OPPO[0];
bean.version = getRomVersion(VERSION_PROPERTY_OPPO);
return bean;
}
if (isRightRom(brand, manufacturer, ROM_LEECO)) {
bean.name = ROM_LEECO[0];
bean.version = getRomVersion(VERSION_PROPERTY_LEECO);
return bean;
}
if (isRightRom(brand, manufacturer, ROM_360)) {
bean.name = ROM_360[0];
bean.version = getRomVersion(VERSION_PROPERTY_360);
return bean;
}
if (isRightRom(brand, manufacturer, ROM_ZTE)) {
bean.name = ROM_ZTE[0];
bean.version = getRomVersion(VERSION_PROPERTY_ZTE);
return bean;
}
if (isRightRom(brand, manufacturer, ROM_ONEPLUS)) {
bean.name = ROM_ONEPLUS[0];
bean.version = getRomVersion(VERSION_PROPERTY_ONEPLUS);
return bean;
}
if (isRightRom(brand, manufacturer, ROM_NUBIA)) {
bean.name = ROM_NUBIA[0];
bean.version = getRomVersion(VERSION_PROPERTY_NUBIA);
return bean;
}
if (isRightRom(brand, manufacturer, ROM_COOLPAD)) {
bean.name = ROM_COOLPAD[0];
} else if (isRightRom(brand, manufacturer, ROM_LG)) {
bean.name = ROM_LG[0];
} else if (isRightRom(brand, manufacturer, ROM_GOOGLE)) {
bean.name = ROM_GOOGLE[0];
} else if (isRightRom(brand, manufacturer, ROM_SAMSUNG)) {
bean.name = ROM_SAMSUNG[0];
} else if (isRightRom(brand, manufacturer, ROM_MEIZU)) {
bean.name = ROM_MEIZU[0];
} else if (isRightRom(brand, manufacturer, ROM_LENOVO)) {
bean.name = ROM_LENOVO[0];
} else if (isRightRom(brand, manufacturer, ROM_SMARTISAN)) {
bean.name = ROM_SMARTISAN[0];
} else if (isRightRom(brand, manufacturer, ROM_HTC)) {
bean.name = ROM_HTC[0];
} else if (isRightRom(brand, manufacturer, ROM_SONY)) {
bean.name = ROM_SONY[0];
} else if (isRightRom(brand, manufacturer, ROM_GIONEE)) {
bean.name = ROM_GIONEE[0];
} else if (isRightRom(brand, manufacturer, ROM_MOTOROLA)) {
bean.name = ROM_MOTOROLA[0];
} else {
bean.name = manufacturer;
}
bean.version = getRomVersion("");
return bean;
}
private static boolean isRightRom(final String brand, final String manufacturer, final String... names) {
for (String name : names) {
if (brand.contains(name) || manufacturer.contains(name)) {
return true;
}
}
return false;
}
private static String getManufacturer() {
try {
String manufacturer = Build.MANUFACTURER;
if (!TextUtils.isEmpty(manufacturer)) {
return manufacturer.toLowerCase();
}
} catch (Throwable ignore) {/**/}
return UNKNOWN;
}
private static String getBrand() {
try {
String brand = Build.BRAND;
if (!TextUtils.isEmpty(brand)) {
return brand.toLowerCase();
}
} catch (Throwable ignore) {/**/}
return UNKNOWN;
}
private static String getRomVersion(final String propertyName) {
String ret = "";
if (!TextUtils.isEmpty(propertyName)) {
ret = getSystemProperty(propertyName);
}
if (TextUtils.isEmpty(ret) || ret.equals(UNKNOWN)) {
try {
String display = Build.DISPLAY;
if (!TextUtils.isEmpty(display)) {
ret = display.toLowerCase();
}
} catch (Throwable ignore) {/**/}
}
if (TextUtils.isEmpty(ret)) {
return UNKNOWN;
}
return ret;
}
private static String getSystemProperty(final String name) {
String prop = getSystemPropertyByShell(name);
if (!TextUtils.isEmpty(prop)) return prop;
prop = getSystemPropertyByStream(name);
if (!TextUtils.isEmpty(prop)) return prop;
if (Build.VERSION.SDK_INT < 28) {
return getSystemPropertyByReflect(name);
}
return prop;
}
private static String getSystemPropertyByShell(final String propName) {
String line;
BufferedReader input = null;
try {
Process p = Runtime.getRuntime().exec("getprop " + propName);
input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
String ret = input.readLine();
if (ret != null) {
return ret;
}
} catch (IOException ignore) {
} finally {
if (input != null) {
try {
input.close();
} catch (IOException ignore) {/**/}
}
}
return "";
}
private static String getSystemPropertyByStream(final String key) {
try {
Properties prop = new Properties();
FileInputStream is = new FileInputStream(
new File(Environment.getRootDirectory(), "build.prop")
);
prop.load(is);
return prop.getProperty(key, "");
} catch (Exception ignore) {/**/}
return "";
}
private static String getSystemPropertyByReflect(String key) {
try {
@SuppressLint("PrivateApi")
Class<?> clz = Class.forName("android.os.SystemProperties");
Method getMethod = clz.getMethod("get", String.class, String.class);
return (String) getMethod.invoke(clz, key, "");
} catch (Exception e) {/**/}
return "";
}
public static class RomInfo {
private String name;
private String version;
public String getName() {
return name;
}
public String getVersion() {
return version;
}
@Override
public String toString() {
return "RomInfo{name=" + name +
", version=" + version + "}";
}
}
}
?以上方案除、索尼、htc 、联想未验证过、其余都有验证。
|