case HONOR_MMS:
Log.d(TAG,“移除短信”);
break;
case QQ:
Log.d(TAG,“移除QQ消息”);
break;
case WX:
Log.d(TAG,“移除微信消息”);
break;
case IN_CALL:
Log.d(TAG,“移除来电”);
break;
default:break;
}
}
/**
- 监听断开
*/
@Override
public void onListenerDisconnected() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
// 通知侦听器断开连接 - 请求重新绑定
requestRebind(new ComponentName(this, NotificationListenerService.class));
}
}
}
这个类继承了NotificationListenerService,里面里面几个方法,都已经注释过了,这里设置通知栏上应用的包名,由于国产厂商对于Android做了定制化,因此各个厂商的系统App软件的包名就不会是一致的,例如我用的是荣耀,那么我监听到的通知短信是com.hihonor.mms,来电是com.android.incallui。这个地方需要开发者自行去适配。不过QQ和微信这种App的包名是固定的,可以放心使用。
下面将这个服务注册在AndroidManifest.xml中。
<service
android:name=“.NotifyService”
android:enabled=“true”
android:label=“测试通知服务”
android:permission=“android.permission.BIND_NOTIFICATION_LISTENER_SERVICE”>
服务配置完成了,下面进行具体的打开服务操作。
使用这个通知服务其实就是打开一个手机上应用的开关,效果上和打开蓝牙差不多,下面先写一个方法检查当前应用是否开启这个服务。方法代码如下:
/**
-
是否启用通知监听服务
-
@return
*/
public boolean isNLServiceEnabled() {
Set packageNames = NotificationManagerCompat.getEnabledListenerPackages(this);
if (packageNames.contains(getPackageName())) {
return true;
}
return false;
}
这里还对应一个方法就是设置服务是否运行,如下:
/**
-
切换通知监听器服务
-
@param enable
*/
public void toggleNotificationListenerService() {
PackageManager pm = getPackageManager();
pm.setComponentEnabledSetting(new ComponentName(getApplicationContext(), NotifyService.class),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
pm.setComponentEnabledSetting(new ComponentName(getApplicationContext(), NotifyService.class),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
}
现在方法有了需要一个地方去触发,通过按钮来进行,在activity_main.xml添加一个按钮。
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:context=“.MainActivity”>
<TextView
android:id=“@+id/textView”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:text=“Hello World!”
app:layout_constraintBottom_toBottomOf=“parent”
app:layout_constraintLeft_toLeftOf=“parent”
app:layout_constraintRight_toRightOf=“parent”
app:layout_constraintTop_toTopOf=“parent” />
<Button
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:text=“请求权限”
android:onClick=“requestPermission”
app:layout_constraintBottom_toBottomOf=“parent”
app:layout_constraintEnd_toEndOf=“parent”
app:layout_constraintStart_toStartOf=“parent”
app:layout_constraintTop_toBottomOf=“@+id/textView” />
</androidx.constraintlayout.widget.ConstraintLayout>
在MainActivity中添加一个方法:
private static final int REQUEST_CODE = 9527;
/**
-
请求权限
-
@param view
*/
public void requestPermission(View view) {
if (!isNLServiceEnabled()) {
startActivityForResult(new Intent(“android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS”), REQUEST_CODE);
} else {
showMsg(“通知服务已开启”);
toggleNotificationListenerService(true);
}
}
这个还有一个showMsg方法:
private void showMsg(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
然后是页面返回:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE) {
if (isNLServiceEnabled()) {
showMsg(“通知服务已开启”);
toggleNotificationListenerService(true);
} else {
showMsg(“通知服务未开启”);
toggleNotificationListenerService(false);
}
}
}
下面就可以先运行一下:
现在就可以测试数据,这里建议你找一个朋友给你发消息,保持电脑上没有登录微信和QQ,然后手机上的微信和QQ保持后台运行就可以了,下面让你的朋友给你发QQ消息、微信消息。
这是我这里测试的数据,控制打印出来:
QQ、微信、短信、来电都监听到了。
现在只是在NotifyService中可以打印出来,那么Activity并不知道,但是实际的UI操作又是在Activity里面,因此需要将消息传递到Activity,这种方式很多,我这里使用接口回调的方式来进行。下面新建一个接口,代码如下:
public interface NotifyListener {
/**
-
接收到通知栏消息
-
@param type
*/
void onReceiveMessage(int type);
/**
-
移除掉通知栏消息
-
@param type
*/
void onRemovedMessage(int type);
}
然后再写一个NotifyHelper帮助类,用于实现接口的回调处理。
public class NotifyHelper {
private static NotifyHelper instance;
public static final int N_MESSAGE = 0;
public static final int N_CALL = 1;
public static final int N_QQ = 2;
public static final int N_WX = 3;
private NotifyListener notifyListener;
public static NotifyHelper getInstance() {
if (instance == null) {
instance = new NotifyHelper();
}
return instance;
}
/**
-
收到消息
-
@param type 消息类型
*/
public void onReceive(int type) {
if (notifyListener != null) {
notifyListener.onReceiveMessage(type);
}
}
/**
-
移除消息
-
@param type 消息类型
*/
public void onRemoved(int type) {
if (notifyListener != null) {
notifyListener.onRemovedMessage(type);
}
}
/**
-
设置回调方法
-
@param notifyListener 通知监听
*/
public void setNotifyListener(NotifyListener notifyListener) {
this.notifyListener = notifyListener;
}
}
最后收到服务中收到通知进行调用。
移除通知进行调用
最后只要在MainActivity中实现接口。
这里实现接口,然后将收到的结果显示在TextView上,实现接口中的两个回调方法。
/**
-
收到通知
-
@param type 通知类型
*/
@Override
public void onReceiveMessage(int type) {
switch (type) {
case N_MESSAGE:
textView.setText(“收到短信消息”);
break;
case N_CALL:
textView.setText(“收到来电消息”);
break;
case N_WX:
textView.setText(“收到微信消息”);
break;
case N_QQ:
textView.setText(“收到QQ消息”);
break;
default:
break;
}
}
/**
-
移除通知
-
@param type 通知类型
*/
@Override
public void onRemovedMessage(int type) {
switch (type) {
case N_MESSAGE:
textView.setText(“移除短信消息”);
break;
case N_CALL:
textView.setText(“移除来电消息”);
break;
case N_WX:
textView.setText(“移除微信消息”);
break;
case N_QQ:
textView.setText(“移除QQ消息”);
break;
default:
break;
}
}
下面再运行一下:
可以看到,现在通过接口想消息类型的结果显示到页面上来了。
现在的很多带屏幕的手环都做到了这一点,可以显示消息内容,这个说起来很高大上,实际上很简单,还是之前的那个地方,那个位置,为了更够更好的显示内容,我还是用代码来说明一下。
首先在NotifyListener增加接口中的方法。
/**
-
接收到通知栏消息
-
@param sbn
*/
void onReceiveMessage(StatusBarNotification sbn);
/**
-
移除掉通知栏消息
-
@param sbn
*/
void onRemovedMessage(StatusBarNotification sbn);
与之前的方法中的参数不同,当然图方便也可以只用这个新增的,把之前的可以去掉,因为现在的这个拿到的信息要比之前多,只不过需要再对消息做进一步的处理。
接口方法写好了,在NotifyHelper中新增两个方法对刚才的接口方法进行调用。
最后
如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。
最后针对Android程序员,我这边给大家整理了一些资料,包括不限于高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
到通知栏消息
- @param sbn
*/
void onReceiveMessage(StatusBarNotification sbn);
/**
-
移除掉通知栏消息
-
@param sbn
*/
void onRemovedMessage(StatusBarNotification sbn);
与之前的方法中的参数不同,当然图方便也可以只用这个新增的,把之前的可以去掉,因为现在的这个拿到的信息要比之前多,只不过需要再对消息做进一步的处理。
接口方法写好了,在NotifyHelper中新增两个方法对刚才的接口方法进行调用。
最后
如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。
[外链图片转存中…(img-fv8hsxQb-1714693499892)]
最后针对Android程序员,我这边给大家整理了一些资料,包括不限于高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!