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;
}
}
亲测华为手机可行!
android 桌面图标添加数字角标的更多相关文章
- Android 为应用添加数字角标
今天在论坛上看到了一个帖子,终于搞清了我很久以来的一个困惑,android到底能不能实现ios的角标效果,QQ是怎么实现的.看了这个帖子顿时终于解除了我的困惑. 先说一个下大概的思路: 大家都知道an ...
- HTML页面仿iphone数字角标
做仿iphone样式的数字角标,用简单的css来实现 <html><head><title>角标数字</title><style type=&qu ...
- IOS开发 应用程序图标数字角标
其实实现这个功能很简单,只要调用UIApplication即可. 用法用例:[UIApplication sharedApplication].applicationIconBadgeNumber ...
- IOS 程序图标添加数字
+(void)setAppIconNumber:(NSInteger)num{ if ([UIParam getIOSVersion]>8.0) { UIUserNotificationSett ...
- ios uibutton加数字角标
http://www.jianshu.com/p/0c7fae1cadac 第一种:https://github.com/mikeMTOL/UIBarButtonItem-Badge第二种:https ...
- 在word文档中添加上角标和下角标
方法一 摘录:https://jingyan.baidu.com/article/02027811b4d2da1bcc9ce5f7.html 方法二 利用MathType数学公式编辑器 exe下载:h ...
- ShortcutBadgerDemo【安卓应用角标(badge)实现方案】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 本文主要使用的开源库是 leolin310148/ShortcutBadger,但是在其基础上做了一些修改. 什么是应用角标? 1. ...
- Android上的Badge,快速实现给应用添加角标
应用角标是iOS的一个特色,原生Android并不支持.或许是因为当时iOS的通知栏比较鸡肋(当然现在已经改进了很多),而Android的通知栏功能强大?所以才出现了一方依赖于数字角标,一方坚持强大的 ...
- apns关于APP数字角标的理解
前两天群里有兄弟在吐槽,做远程推送的时候:老板要求APP桌面图标的右上角显示红色未读数字(数字角标)要精准,有多少未读通知就显示数字几:但是后台的弟兄在发送推送通知的时候,每次的角标是1,然后要移动端 ...
随机推荐
- Django 常用的 Web 应用程序工具
Django 提供了多种开发 Web 应用程序所需的常用工具,如:缓存.日志.发送邮件.自定义认证等,更多可参考:<https://docs.djangoproject.com/zh-hans/ ...
- 程序员式优雅表白,教你用python代码画爱心
还能用python代码画爱心?还有这种操作?这是什么原理? 不相信python代码可以画爱心?先来一张效果图来看看效果吧! 用python代码画爱心的思路是怎样的? 1.怎么画心形曲线 2.怎么填满心 ...
- KVM虚拟机被OOM killer
一.线上环境的虚拟机被KVM物理机kill掉 Linux 内核根据应用程序的要求分配内存,通常来说应用程序分配了内存但是并没有实际全部使用,为了提高性能,这部分没用的内存可以留作它用,这部分内存是属于 ...
- seaborn(2)---画分类图/分布图/回归图/矩阵图
二.分类图 1. 分类散点图 (1)散点图striplot(kind='strip') 方法1: seaborn.stripplot(x=None, y=None, hue=None, data=No ...
- Spring Cloud 之 Consul 知识点:服务注册与发现(类似工具:Eureka、ZooKeeper、Etcd)
资料 网址 springcloud(十三):注册中心 Consul 使用详解 http://ityouknow.com/springcloud/2018/07/20/spring-cloud-cons ...
- SpringMVC+Mybatis学习
简单Web项目搭建: 一.流程 1. 导包 n个springMVC: 2个mybatis<其中一个是mybatis-spring>: 3个jackson包: 2. xml配置 web.xm ...
- 强制结束虚拟机 centos home 卷丢失导致无法挂载进入 emergency mode 紧急模式
参考文章: https://blog.51cto.com/13059784/2054378 xfs文件修复参考1:https://codeday.me/bug/20181112/367781.html ...
- python--递归函数讲解
递归算法是一种直接或间接调用自身算法的过程. 递归算法解决问题的特点: (1)递归就是在过程或函数里调用自身 (2)在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口. (3)递归算法解题通 ...
- jQuery中判断数组
判断数组里面是否包含某个元素可以使用 $.inArray("元素(字符串)",数组名称) 进行判断 ,当存在该元素(字符串)时,返回该元素在数组的下标,不存在时返回 -1 jQ=& ...
- base64文件隐写脚本
base64文件隐写脚本 base64 可以在文件中隐藏信息,记录一下提取脚本 ''' base64文件隐写脚本 import re import base64 b64chars = 'ABCDEFG ...