导入第三方角标库ShortcutBadge
这个库使用各手机厂商系统的角标展示,比较推荐使用。但是小米手机使用的是notification进行推送,区别其他厂商,三方文档有对小米适配,但是使用demo还是无法在小米手机显示角标。
原因是:app在打开状态下进行推送,系统会认为推送完成,所以不展示。
解决方案:在app关闭后,进行延时推送。并且点击进入app后,角标会自动消失
修改demo中BadgeIntentService
public class BadgeIntentService extends IntentService {
private static final String NOTIFICATION_CHANNEL = "me.leolin.shortcutbadger.example";
private int notificationId = 0;
public BadgeIntentService() {
super("BadgeIntentService");
}
private NotificationManager mNotificationManager;
@Override
public void onCreate() {
super.onCreate();
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
int badgeCount = intent.getIntExtra("badgeCount", 0);
mNotificationManager.cancel(notificationId);
notificationId++;
Notification.Builder builder = new Notification.Builder(getApplicationContext())
.setContentTitle("12")
.setContentText("12")
.setSmallIcon(R.drawable.ic_launcher);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
setupNotificationChannel();
builder.setChannelId(NOTIFICATION_CHANNEL);
}
Notification notification = builder.build();
try {
Class miuiNotificationClass = Class.forName("android.app.MiuiNotification");
Object miuiNotification = miuiNotificationClass.newInstance();
Field field = miuiNotification.getClass().getDeclaredField("messageCount");
field.setAccessible(true);
field.set(miuiNotification, 121);// 设置信息数
field = notification.getClass().getField("extraNotification");
field.setAccessible(true);
field.set(notification, notificationId);
} catch (Exception e) {
}
ShortcutBadger.applyNotification(getApplicationContext(), notification, badgeCount);
mNotificationManager.notify(notificationId, notification);
}
}
@TargetApi(Build.VERSION_CODES.O)
private void setupNotificationChannel() {
// 通知渠道的id
String id = "1";
// 用户可以看到的通知渠道的名字.
CharSequence name = "notification channel";
// 用户可以看到的通知渠道的描述
String description = "notification description";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel(NOTIFICATION_CHANNEL, name, importance);
// 配置通知渠道的属性
mChannel.setDescription(description);
// 设置通知出现时的闪灯(如果 android 设备支持的话)
mChannel.enableLights(true);
mChannel.setLightColor(Color.RED);
// 设置通知出现时的震动(如果 android 设备支持的话)
mChannel.enableVibration(true);
mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
//最后在notificationmanager中创建该通知渠道
mNotificationManager.createNotificationChannel(mChannel);
}
}
关闭App后延时启动Service
MainActivity.class
launchNotification.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int badgeCount = 0;
try {
badgeCount = Integer.parseInt(numInput.getText().toString());
} catch (NumberFormatException e) {
Toast.makeText(getApplicationContext(), "Error input", Toast.LENGTH_SHORT).show();
}
final int newcount = badgeCount;
finish();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
startService(
new Intent(MainActivity.this, BadgeIntentService.class).putExtra("badgeCount", newcount)
);
}
},1000);
}
});
开启后会一直展示角标,需要调用removeCount关闭
ShortcutBadger.applyCount(context, badgeCount);
ShortcutBadger.removeCount(context);
由于没有使用阿里云推送方案(以后可以考虑加),所以还是在app结束后启动service,所以监听app结束是关键,引入ContextHolder加载activity,监听所有Activity都关闭则程序关闭,启动service
public class ContextHolder {
private volatile static ContextHolder instance;
private Application mContext;
private Activity mTopActivity;
private ActLifecycle mLifecycle;
private OnAppCloseCallBack mAppCloseCallBack;
private ArrayList mTasks=new ArrayList<>();
private ContextHolder() {
}
public static ContextHolder getInstance() {
if (instance == null) {
synchronized (ContextHolder.class) {
if (instance == null) {
instance = new ContextHolder();
}
}
}
return instance;
}
public void setAppCloseCallBack(OnAppCloseCallBack callback) {
this.mAppCloseCallBack = callback;
}
public Context getApplicationContext() {
return mContext;
}
public Activity getTopActivity() {
return mTopActivity;
}
public void init(Application application) {
release();
mContext = application;
mLifecycle = new ActLifecycle();
mContext.registerActivityLifecycleCallbacks(mLifecycle);
}
private void release() {
mTopActivity = null;
mTasks.clear();
if (mLifecycle != null && mContext != null) {
mContext.unregisterActivityLifecycleCallbacks(mLifecycle);
mContext = null;
mLifecycle = null;
}
}
//
private class ActLifecycle implements Application.ActivityLifecycleCallbacks {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
mTopActivity = activity;
mTasks.add(activity);
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
mTopActivity = activity;
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
mTasks.remove(activity);
int count = mTasks.size();
if (count <= 0) {
Log.i("ContextHolder", "All Activity Destroyed");
mTopActivity = null;
mContext.unregisterActivityLifecycleCallbacks(mLifecycle);
if(mAppCloseCallBack!=null){
mAppCloseCallBack.onAppClose();
}
}
}
}
public void closeAllActivity(){
for (int i = mTasks.size()-1; i >=0 ; i--) {
mTasks.get(i).finish();
}
mTasks.clear();
}
//
public interface OnAppCloseCallBack{
void onAppClose();
}
}
MyApplication实现ContextHolder.OnAppCloseCallBack
private void initContext() {
ContextHolder.getInstance().init(this);
ContextHolder.getInstance().setAppCloseCallBack(this);
}
@Override
public void onAppClose() {
startService(
new Intent(getContext(), BadgeService.class)
);
}
BadgeService.class
private static final String NOTIFICATION_CHANNEL = "com.neabea.service";
private int notificationId = 101;
private NotificationManager mNotificationManager;
private SharedPreferencesUtil sharedPreferencesUtil;
@Override
public void onCreate() {
super.onCreate();
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
sharedPreferencesUtil = new SharedPreferencesUtil(this);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (sharedPreferencesUtil != null) {
//获取本地角标数值
int badgeCount = sharedPreferencesUtil.getMessageCount();
if (badgeCount == 0) {
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
if (!Build.MANUFACTURER.equalsIgnoreCase("Xiaomi")) {
ShortcutBadger.applyCount(this, badgeCount);
} else {
mNotificationManager.cancel(notificationId);
Intent intentAct = new Intent(this, WelcomeActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intentAct, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder builder = new Notification.Builder(MyApplication.getContext())
.setContentTitle("有未读消息需要您查看")
.setContentText("点击查看详情")
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setSmallIcon(R.mipmap.ic_launcher);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
setupNotificationChannel();
builder.setChannelId(NOTIFICATION_CHANNEL);
}
Notification notification = builder.build();
ShortcutBadger.applyNotification(getApplicationContext(), notification, badgeCount);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mNotificationManager.notify(notificationId, notification);
stopSelf();
}
}, 1000 * 10);
}
}
return super.onStartCommand(intent, flags, startId);
}
@TargetApi(Build.VERSION_CODES.O)
private void setupNotificationChannel() {
// 用户可以看到的通知渠道的名字.
CharSequence name = "notification badge";
// 用户可以看到的通知渠道的描述
String description = "notification description badge";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel(NOTIFICATION_CHANNEL, name, importance);
// 配置通知渠道的属性
mChannel.setDescription(description);
// 设置通知出现时的闪灯(如果 android 设备支持的话)
mChannel.enableLights(true);
mChannel.setLightColor(Color.RED);
//最后在notificationmanager中创建该通知渠道
mNotificationManager.createNotificationChannel(mChannel);
}
}