1. Demand background
Once, when a foreign customer used our company's watch, he reported that after the Android phone was connected to the watch, other people's messages could not be received. After a few days of discussion, he finally wrote a demo for the customer.
2. Implementation steps
Plugin and version used: flutter_notification_listener: ^1.3.2.
Note: When listening to message notifications, you must open the message notification permission of the corresponding application, otherwise you will not be able to monitor
- Initialize the receiving port
- Set the receiving port name
- Initialize NotificationsListener
- get port name
- Perform logical operations in port monitoring
- open monitor
3. Code sharing
1. Install flutter_notification_listener
Add the following to the pubspec.yaml file:
dependencies:
flutter_notification_listener: ^1.3.2
2. Register the service in the android > src > main > AndroidManifest.xml file
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<service android:name="im.zoe.labs.flutter_notification_listener.NotificationsHandlerService"
android:label="Flutter Notifications Handler"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
3. Use flutter_notification_listener
class _NotificationPage extends State<NotificationPage> {
int _firmwareVersion = -1;
bool started = true;
bool _loading = false;
ReceivePort port = ReceivePort();
bool hasPort = false;
@override
void initState() {
super.initState();
initPlatformState();
}
/// 这里一定要是静态方法
static void _notificationCallback(NotificationEvent evt) {
SendPort? send = IsolateNameServer.lookupPortByName("_listener_");
if (send == null) print("can't find the sender");
send?.send(evt);
}
Future<void> initPlatformState() async {
if (Platform.isAndroid) {
if (hasPort) {
IsolateNameServer.removePortNameMapping("_listener_");
}
hasPort = IsolateNameServer.registerPortWithName(port.sendPort, "_listener_");
NotificationsListener.initialize(callbackHandle: _notificationCallback);
port.listen((message) => onData(message));
var isR = await NotificationsListener.isRunning;
setState(() {
started = isR!;
});
}
}
void onData(NotificationEvent event) {
/// 这里进行逻辑操作
if (_firmwareVersion != -1) {
widget.blePlugin.sendMessage(
MessageBean(
message: event.text.toString(),
type: BleMessageType.qq,
versionCode: _firmwareVersion,
isHs: true,
isSmallScreen: true,
),
);
}
}
/// 开启监听
void startListening() async {
setState(() {
_loading = true;
});
var hasPermission = await NotificationsListener.hasPermission;
if (!hasPermission!) {
NotificationsListener.openPermissionSettings();
return;
}
var isR = await NotificationsListener.isRunning;
if (!isR!) {
await NotificationsListener.startService(
foreground: true,
title: "Listener Running",
description: "Welcome to having me"
);
}
setState(() {
started = true;
_loading = false;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text("Notification"),
),
body: Center(
child: ListView(children: [
Text("firmwareVersion: $_firmwareVersion"),
Text("started: $started"),
Text("loading: $_loading"),
ElevatedButton(onPressed: startListening, child: const Text("start"),),
ElevatedButton(
child: const Text("queryFirmwareVersion"),
onPressed: () async {
String firmwareVersion = await widget.blePlugin.queryFirmwareVersion;
int index = firmwareVersion.lastIndexOf('-');
String subString = firmwareVersion.substring(index);
String version = '';
subString.replaceAllMapped(RegExp(r'\d'), (Match m) {
version += m[0]!;
return m[0]!;
});
setState(() {
_firmwareVersion = int.parse(version);
});
}),
]))));
}
}