• android 桌面图标添加数字角标



    是否支持角标并不与手机厂商有关,而是你当前使用的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;
        }
    }

     亲测华为手机可行!

  • 相关阅读:
    在IIS上部署 .Net Core 3.0 项目踩坑实录
    .net core3.0部署Linux服务器 使用Docker容器和Nginx反代理教程
    播放器 AxWindowsMediaPlayer控件的使用
    Github下载慢和下载过程中断等情况的解决方案
    GitHub第一次上传遇到的问题
    DataGridView && 增加复选框(checkbox)方法
    努力
    绘图:drawImage一个用法
    Tuple<T1,T2,.........T> 元组简单使用
    随机的标识符GUID
  • 原文地址:https://www.cnblogs.com/loaderman/p/11949985.html
Copyright © 2020-2023  润新知