Android取消广播的方法名,去除Android中的角标

为了MarkDown输入的方便, 文中的标点都是英文标点, 带来不便敬请谅解.

角标本来是iOS上的东东, 在原生Android中是没有的. 但是现在各大手机厂商几乎都自己实现了这个功能, 这让Android的碎片化更加严重. 在我看来, 安卓的通知栏可以很好地通知用户各种消息了, 非得学iOS将角标加入到系统来真是画蛇添足! 而且, 我相信很多用户对这些角标的显示十分地厌烦, 不得不挨个点开有角标的App来消去角标(包括我自己). 能不能一键把所有讨厌的角标消除掉呢? 自己来试试吧.

本文中的代码是使用Kotlin写的,如果难以理解请先学习一下Kotlin的简单语法

三星

三星里的角标是通过一个内置的应用BadgeProvider来实现的,可以在应用管理器中找到.

807768a3ba2e449f3dc804fdb1ce0299.png

理论上来讲强制停止这个App就可以让角标不再显示, 但是人家是三星的内置应用, 你强制停止了待会又会自动启动起来,就是这么流氓. 如果root了将其卸载了估计能有用, 但是我没试验过.

既然强制停止这个App没有用, 那就想想别的办法吧. 目前有两种方法:

通过广播

发送一个Action为”android.intent.action.BADGE_COUNT_UPDATE”的广播,并且将包名/LAUNCHER Activity和角标的数目一起发送出去. 三星的系统中一个BroadcastReceiver会接收这个广播并且将角标加到对应的App上.代码如下:

1

2

3

4

5

6

7

8

9

10fun sendToSamSumg(context: Context, packageName: String, className: String, number: Int) {

Log.d(TAG, "packageName:$packageName")

Log.d(TAG, "className:$className")

Log.d(TAG, "number:$number")

val badgeIntent = Intent(Actions.ACTION_SUMSUNG)

badgeIntent.putExtra("badge_count", number)

badgeIntent.putExtra("badge_count_package_name", packageName)

badgeIntent.putExtra("badge_count_class_name", className)

context.sendBroadcast(badgeIntent)

}

这样的话,如果我们只要在Manifest文件里注册一个接收这个Action的BroadcastReceiver, 理论上来讲任何时候都可以收到对应的广播,然后再发一条badge_count为0的广播就应该可以自动将角标给消去了.但是在我的s6手机上实验发现过一段时间后进程会被杀死再也收不到广播了,可能是三星对系统做了什么更改.

既然自动消除的路走不通了,那就来手动消除吧. 我们可以遍历系统中安装的所有App, 得到其包名和启动Activity, 并依次对其发送badge_count为0的广播.

1

2

3

4

5

6

7

8

9

10

11fun sendToSamSungAllBroadCast(context: Context, number: Int, test: Boolean) {

val intent = Intent(Intent.ACTION_MAIN)

intent.addCategory(Intent.CATEGORY_LAUNCHER);

val list = context.packageManager.queryIntentActivities(intent, PackageManager.GET_ACTIVITIES);

for (resolveInfo in list) {

val activityName = resolveInfo.activityInfo.name

val packageName = resolveInfo.activityInfo.applicationInfo.packageName

sendToSamSumg(context, packageName, activityName, number, test)

}

}

实验了一下可以达到目的,但是效率很差, 一方面手机中装的App一般会很多,另一方面广播的效率比较差,所以需要好几秒才能完成整个过程.那有没有更好的办法了呢? 回答是Yes! 看下面的方法:

通过ContentProvider

三星系统中的角标数目都是存储在一个Uri为”content://com.sec.badge/apps”的ContentProvider里的, 这个ContentProvider 包含以下的几个属性:

_id

package

class

badgecount

icon

extraData

通过访问和修改这个ContentProvider里面的badgecount属性,就可以获取或者更改对应App的角标数目.

但是首先需要申请读写的权限:

1

2

这个ContentProvider只会存储需要显示角标的App,当一个App显示过一次角标后就会被存储起来, 并不会包含其它的App, 所以需要遍历的App数目相对较少. 我们需要做的就是遍历ContentProvider里面所有的App并且将其badgecount置为0就可以消除掉所有的角标.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24fun sendToSamSungAllContentResolver(context: Context, number: Int) {

val uri = Uri.parse("content://com.sec.badge/apps")

val contentResolver = context.contentResolver

val c: Cursor? = contentResolver.query(uri, null, null, null, null) ?: return

try {

var where = "package in ("

while (c!!.moveToNext()) {

val pkg = c.getString(1)

val clazz = c.getString(2)

val badgeCount = c.getInt(3)

Log.d(TAG, "package: $pkg, class: $clazz, badgeCount: $badgeCount")

where += "'$pkg',"

}

where += "' ')"

Log.d(TAG, "update $where to number: $number")

val cv = ContentValues()

cv.put("badgeCount", number)

contentResolver.update(Uri.parse("content://com.sec.badge/apps"), cv, where, null)

} catch (e: Exception) {

Log.e(TAG, e.toString())

c!!.close()

}

}

相比于上面的方法,这种方法去除角标效率极大地得到了提高,瞬间就可以清除掉所有的角标. 为了方便,我们创建一个Widget放在桌面上,这样一点击就可以把所有的角标都清除掉.

效果图如下:

4e0ede69f67baaa83f3d1e96ba543e65.gif

Sony

索尼需要显示一个角标需要发送一个Action为”com.sonyericsson.home.action.UPDATE_BADGE”的广播,同样也需要申请权限

1

2

发送广播的Intent包含4种数据,分别是包名/启动Activity/是否显示角标/角标数目.需要注意的是角标数目是字符串类型的而不是Int类型.

1

2

3

4

5

6

7

8

9fun sendToSony(context: Context, packageName: String, className: String, number: Int) {

Log.d(TAG, "sendToSony $packageName")

val intent = Intent(Actions.ACTION_SONY);

intent.putExtra("com.sonyericsson.home.intent.extra.badge.ACTIVITY_NAME", className);

intent.putExtra("com.sonyericsson.home.intent.extra.badge.SHOW_MESSAGE", number != 0);

intent.putExtra("com.sonyericsson.home.intent.extra.badge.MESSAGE", number.toString());

intent.putExtra("com.sonyericsson.home.intent.extra.badge.PACKAGE_NAME", packageName);

context.sendBroadcast(intent);

}

通过上面的方法我们就可以让一个App的启动图标上显示角标.如果我们发送的number为0,当然就可以将角标给消去.所以要达到一键消除所有角标的效果就必须得遍历所有的App,这点不像三星可以直接操作ContentProvider.

1

2

3

4

5

6

7

8

9

10fun sendToSonyAll(context: Context, number: Int) {

val intent = Intent(Intent.ACTION_MAIN)

intent.addCategory(Intent.CATEGORY_LAUNCHER);

val list = context.packageManager.queryIntentActivities(intent, PackageManager.GET_ACTIVITIES);

for (resolveInfo in list) {

val activityName = resolveInfo.activityInfo.name

val packageName = resolveInfo.activityInfo.applicationInfo.packageName

sendToSony(context, packageName, activityName, number)

}

}

Htc

Htc同索尼一样,也是发送广播,Action为”com.htc.launcher.action.SET_NOTIFICATION”,同样也需要申请权限:

1

2

要以消除角标的话也需要遍历所有的App.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19fun sendToHtc(context: Context, packageName: String, className: String, number: Int) {

Log.d(TAG, "sendToHtc $packageName,number:$number")

val setNotificationIntent = Intent(Actions.ACTION_HTC);

val localComponentName = ComponentName(packageName, className);

setNotificationIntent.putExtra("com.htc.launcher.extra.COMPONENT", localComponentName.flattenToShortString());

setNotificationIntent.putExtra("com.htc.launcher.extra.COUNT", number);

context.sendBroadcast(setNotificationIntent);

}

fun sendToHtcAll(context: Context, number: Int) {

val intent = Intent(Intent.ACTION_MAIN)

intent.addCategory(Intent.CATEGORY_LAUNCHER);

val list = context.packageManager.queryIntentActivities(intent, PackageManager.GET_ACTIVITIES);

for (resolveInfo in list) {

val packageName = resolveInfo.activityInfo.applicationInfo.packageName

val activityName = resolveInfo.activityInfo.name

sendToHtc(context, packageName, activityName, number)

}

}

本文的代码见GitHub

To be continued…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值