android 桌面图标添加数字角标

时间:2023-05-26 12:29:26

是否支持角标并不与手机厂商有关,而是你当前使用的launcher开发厂商有关。

方法实现:

import android.app.Application;
import android.app.Notification;
import android.content.Intent;
import android.support.annotation.NonNull; /**
*谷歌
*/
public class GoogleModelImpl implements IconBadgeNumModel {
private static final String NOTIFICATION_ERROR = "google not support before API O"; @Override
public Notification setIconBadgeNum(@NonNull Application context, Notification notification, int count) throws Exception {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O) {
throw new Exception(NOTIFICATION_ERROR);
}
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", Utils.getInstance().getLaunchIntentForPackage(context)); // com.test. badge.MainActivity is your apk main activity // if (Utils.getInstance().canResolveBroadcast(context, intent)) {
context.sendBroadcast(intent);
// } else {
// throw new Exception(UNABLE_TO_RESOLVE_INTENT_ERROR_ + intent.toString());
// } return notification;
} }
import android.app.Application;
import android.app.Notification;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull; /**
* https://developer.huawei.com/consumer/cn/devservice/doc/30802
* <p>
* 华为
*/
public class HuaWeiModelImpl implements IconBadgeNumModel {
@Override
public Notification setIconBadgeNum(@NonNull Application context, Notification notification, int count) throws Exception {
Bundle bunlde = new Bundle();
bunlde.putString("package", context.getPackageName()); // com.test.badge is your package name
bunlde.putString("class", Utils.getInstance().getLaunchIntentForPackage(context)); // com.test. badge.MainActivity is your apk main activity
bunlde.putInt("badgenumber", count);
context.getContentResolver().call(Uri.parse("content://com.huawei.android.launcher.settings/badge/"), "change_badge", null, bunlde);
return notification;
}
}
import android.app.Application;
import android.app.Notification;
import android.support.annotation.NonNull;
//魅族
public class MeizuModelImpl implements IconBadgeNumModel {
private static final String NOTIFICATION_ERROR = "not support : meizu"; @Override
public Notification setIconBadgeNum(@NonNull Application context, Notification notification, int count) throws Exception {
if (true) {
throw new Exception(NOTIFICATION_ERROR);
}
return null;
}
}
import android.app.Application;
import android.app.Notification;
import android.support.annotation.NonNull; /**
* 以下是oppo客服原文(其中没有说明3.3中日活量和总下载量的标准)
* <p>
* 亲,您可以通过邮件的形式提交申请,邮件形式如下:
* <p>
* 1.主题:“申请开放OPPO手机应用角标权限——(应用名称)”
* <p>
* 2.收件人:devtec@oppo.com
* <p>
* 3.正文:应用角标申请所需材料
* 以下为应用角标申请所需材料:
* 1.应用方申请人基本信息(姓名、邮箱、手机、微信);
* 2.应用方厂商介绍(不少于200字);
* 3.申请应用近一个月内IOS与安卓系统的平均日活量及总下载量介绍;
* 4.申请应用产品主要功能介绍(不少于100字);
* 5.申请应用期望角标出现的全部场景。(即哪些类的消息需要出现角标,需全部列出)
* <p>
* 您这边以邮件的形式申请接入角标后,OPPO方审核人员将在接收日期10个工作日内给出审核结果。感谢您对OPPO开放平台的关注与信任,还
* 请您耐心等待的哦~
*/
public class OPPOModelImpl implements IconBadgeNumModel {
private static final String NOTIFICATION_ERROR = "not support : oppo"; @Override
public Notification setIconBadgeNum(@NonNull Application context, Notification notification, int count) throws Exception {
if (true) {
throw new Exception(NOTIFICATION_ERROR);
}
return null;
}
}
import android.app.Application;
import android.app.Notification;
import android.content.Intent;
import android.support.annotation.NonNull; import static com.demo.badges.Utils.UNABLE_TO_RESOLVE_INTENT_ERROR_; /**
* 没有找到官方文档说明,只有网上的方法
* <p>
* Galaxy S8/SM-G9500/android 8.0
* Galaxy Galaxy Note8/SM-N9500/android 8.0
* 三星
*/
public class SamsungModelImpl implements IconBadgeNumModel {
private static final String NOTIFICATION_ERROR = "not support : samsung"; @Override
public Notification setIconBadgeNum(@NonNull Application context, Notification notification, int count) throws Exception {
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", Utils.getInstance().getLaunchIntentForPackage(context)); if (Utils.getInstance().canResolveBroadcast(context, intent)) {
context.sendBroadcast(intent);
} else {
throw new Exception(UNABLE_TO_RESOLVE_INTENT_ERROR_ + intent.toString());
}
return notification;
}
}
import android.app.Application;
import android.app.Notification;
import android.support.annotation.NonNull; /**
* 网上查到了此段代码,但在vivo X21A[android-8.1.0/Funtouch OS_4.0]真机上并未测试成功。
* 在vivo开发者平台上与人工客服联系后,对方回复暂时没有公开的方法可以设置,也没有渠道可以申请,只有vivo特别指定的应用可以实现(微信、微博等)
*/
public class VIVOModelImpl implements IconBadgeNumModel {
private static final String NOTIFICATION_ERROR = "not support : vivo"; @Override
public Notification setIconBadgeNum(@NonNull Application context, Notification notification, int count) throws Exception {
if (true) {
throw new Exception(NOTIFICATION_ERROR);
}
return null;
}
}
import android.app.Application;
import android.app.Notification;
import android.support.annotation.NonNull; import java.lang.reflect.Field;
import java.lang.reflect.Method; /**
* https://dev.mi.com/console/doc/detail?pId=939
* <p>
* 必须发送通知
*/
public class XiaoMiModelImpl implements IconBadgeNumModel {
private static final String NOTIFICATION_ERROR = "Xiaomi phones must send notification"; @Override
public Notification setIconBadgeNum(@NonNull Application context, Notification notification, int count) throws Exception {
if (notification == null) {
throw new Exception(NOTIFICATION_ERROR);
}
Field field = notification.getClass().getDeclaredField("extraNotification");
Object extraNotification = field.get(notification);
Method method = extraNotification.getClass().getDeclaredMethod("setMessageCount", int.class);
method.invoke(extraNotification, count);
return notification;
}
}
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import java.util.List; public class Utils {
public static final String UNABLE_TO_RESOLVE_INTENT_ERROR_ = "unable to resolve intent: "; private static Utils instance; public static Utils getInstance() {
if (instance == null) {
instance = new Utils();
}
return instance;
} public boolean canResolveBroadcast(Context context, Intent intent) {
PackageManager packageManager = context.getPackageManager();
List<ResolveInfo> receivers = packageManager.queryBroadcastReceivers(intent, 0);
return receivers != null && receivers.size() > 0;
} public String getLaunchIntentForPackage(Context context) {
return context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).getComponent().getClassName();
}
}
import android.app.Application;
import android.app.Notification;
import android.support.annotation.NonNull; public interface IconBadgeNumModel {
Notification setIconBadgeNum(@NonNull Application context, Notification notification, int count) throws Exception;
}
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import java.util.HashMap;
import java.util.Map; public class LauncherHelper {
public final static String GOOGLE = "google";
public final static String HUAWEI = "huawei";
public final static String MEIZU = "meizu";
public final static String XIAOMI = "xiaomi";
public final static String OPPO = "oppo";
public final static String VIVO = "vivo";
public final static String SAMSUNG = "samsung"; private static Map<String, String> launcherMap; static {
launcherMap = new HashMap<>();
launcherMap.put("com.huawei.android.launcher", HUAWEI);
launcherMap.put("com.miui.home", XIAOMI);
launcherMap.put("com.sec.android.app.launcher", SAMSUNG);
launcherMap.put("com.google.android.apps.nexuslauncher", GOOGLE);
} @Nullable
public String getLauncherTypeByName(@NonNull String launcherName) {
return launcherMap.get(launcherName);
} @Nullable
public String getLauncherPackageName(@NonNull Context context) {
final Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
final ResolveInfo res = context.getPackageManager().resolveActivity(intent, 0);
if (res.activityInfo == null) {
// should not happen. A home is always installed, isn't it?
return null;
}
if (res.activityInfo.packageName.equals("android")) {
return null;
} else {
return res.activityInfo.packageName;
}
}
}
import android.app.Application;
import android.app.Notification;
import android.os.Build;
import android.support.annotation.NonNull;
import android.text.TextUtils; import java.util.HashMap;
import java.util.Map; public class IconBadgeNumManager implements IconBadgeNumModel {
private static final String NOT_SUPPORT_PHONE = "not support your phone [ Build.MANUFACTURER is null ]";
private static final String NOT_SUPPORT_MANUFACTURER_ = "not support ";
private static final String NOT_SUPPORT_LAUNCHER = "not support your launcher [ default launcher is null ]";
private static final String NOT_SUPPORT_LAUNCHER_ = "not support ";
private Map<String, IconBadgeNumModel> iconBadgeNumModelMap;
private LauncherHelper launcherHelper; public IconBadgeNumManager() {
this.launcherHelper = new LauncherHelper();
iconBadgeNumModelMap = new HashMap<>();
} @Override
public Notification setIconBadgeNum(@NonNull Application context, Notification notification, int count) throws Exception {
IconBadgeNumModel iconBadgeNumModel = getSetIconBadgeNumModel(context);
return iconBadgeNumModel.setIconBadgeNum(context, notification, count);
} /**
* 根据手机类型获取相应Model
*
* @deprecated 判断当前launcher更加准确
*/
@Deprecated
@NonNull
private IconBadgeNumModel getIconBadgeNumModelByManufacturer() throws Exception {
if (TextUtils.isEmpty(Build.MANUFACTURER)) {
throw new Exception(NOT_SUPPORT_PHONE);
}
switch (Build.MANUFACTURER.toLowerCase()) {
case MobileBrand.HUAWEI:
return new GoogleModelImpl();
case MobileBrand.XIAOMI:
return new XiaoMiModelImpl();
case MobileBrand.VIVO:
return new VIVOModelImpl();
case MobileBrand.OPPO:
return new OPPOModelImpl();
case MobileBrand.SAMSUNG:
return new SamsungModelImpl();
case MobileBrand.MEIZU:
return new MeizuModelImpl();
case MobileBrand.GOOGLE:
return new GoogleModelImpl();
default:
throw new Exception(NOT_SUPPORT_MANUFACTURER_ + Build.MANUFACTURER);
}
} /**
* 根据手机当前launcher获取相应Model
*/
@NonNull
private IconBadgeNumModel getIconBadgeNumModelByLauncher(@NonNull String launcherType) throws Exception {
switch (launcherType) {
case LauncherHelper.HUAWEI:
return new HuaWeiModelImpl();
case LauncherHelper.XIAOMI:
return new XiaoMiModelImpl();
case LauncherHelper.VIVO:
return new VIVOModelImpl();
case LauncherHelper.OPPO:
return new OPPOModelImpl();
case LauncherHelper.SAMSUNG:
return new SamsungModelImpl();
case LauncherHelper.MEIZU:
return new MeizuModelImpl();
case LauncherHelper.GOOGLE:
return new GoogleModelImpl();
default:
throw new Exception(NOT_SUPPORT_LAUNCHER_ + launcherType);
}
} @NonNull
private IconBadgeNumModel getSetIconBadgeNumModel(@NonNull Application context) throws Exception {
String launcherName = launcherHelper.getLauncherPackageName(context);
if (TextUtils.isEmpty(launcherName)) {
throw new Exception(NOT_SUPPORT_LAUNCHER);
}
String launcherType = launcherHelper.getLauncherTypeByName(launcherName);
if (TextUtils.isEmpty(launcherType)) {
throw new Exception(NOT_SUPPORT_LAUNCHER_ + launcherName);
}
if (iconBadgeNumModelMap.containsKey(launcherType)) {
return iconBadgeNumModelMap.get(launcherType);
}
IconBadgeNumModel iconBadgeNumModel = getIconBadgeNumModelByLauncher(launcherType);
iconBadgeNumModelMap.put(launcherType, iconBadgeNumModel);
return iconBadgeNumModel;
}
}

测试:

import android.content.Intent;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View; import com.demo.badges.LauncherHelper; public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG, Build.MANUFACTURER);
Log.e(TAG, new LauncherHelper().getLauncherPackageName(this)); findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent i = new Intent(MainActivity.this, MyService.class);
startService(i);
}
});
findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent i = new Intent(MainActivity.this, MyService.class);
stopService(i);
}
});
}
}
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.os.IBinder;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat; import com.demo.badges.IconBadgeNumManager; public class MyService extends Service {
IconBadgeNumManager setIconBadgeNumManager;
private boolean isStop;
private int count;
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (!isStop) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count += 2;
sendIconNumNotification();
}
}
}); public MyService() {
setIconBadgeNumManager = new IconBadgeNumManager(); } @Override
public int onStartCommand(Intent intent, int flags, int startId) {
isStop = false;
thread.start();
return super.onStartCommand(intent, flags, startId);
} @Override
public void onDestroy() {
super.onDestroy();
isStop = true;
} @Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
} private void sendIconNumNotification() {
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (nm == null) return;
String notificationChannelId = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = createNotificationChannel();
nm.createNotificationChannel(notificationChannel);
notificationChannelId = notificationChannel.getId();
}
Notification notification = null;
try {
notification = new NotificationCompat.Builder(this, notificationChannelId)
.setSmallIcon(getApplicationInfo().icon)
.setWhen(System.currentTimeMillis())
.setContentTitle("title")
.setContentText("content num: " + count)
.setTicker("ticker")
.setAutoCancel(true)
.setNumber(count)
.build();
notification = setIconBadgeNumManager.setIconBadgeNum(getApplication(), notification, count); nm.notify(32154, notification);
} catch (Exception e) {
e.printStackTrace();
}
} @RequiresApi(api = Build.VERSION_CODES.O)
private static NotificationChannel createNotificationChannel() {
String channelId = "test";
NotificationChannel channel = null;
channel = new NotificationChannel(channelId,
"Channel1", NotificationManager.IMPORTANCE_DEFAULT);
channel.enableLights(true); //是否在桌面icon右上角展示小红点
channel.setLightColor(Color.RED); //小红点颜色
channel.setShowBadge(true); //是否在久按桌面图标时显示此渠道的通知
return channel;
}
}

android 桌面图标添加数字角标

亲测华为手机可行!