Flutter开发Android/iOS通知时触发PlatformException错误求助
运行支持Android和iOS的通知Demo时,Android端出现如下PlatformException错误:
PlatformException (PlatformException(error, null, null,
java.lang.IllegalArgumentException at
android.os.Parcel.createExceptionOrNull(Parcel.java:2429) at
android.os.Parcel.createException(Parcel.java:2409) at
android.os.Parcel.readException(Parcel.java:2392) at
android.os.Parcel.readException(Parcel.java:2334) at
android.app.INotificationManager$Stub$Proxy.createNotificationChannels(INotificationManager.java:3933)
at
android.app.NotificationManager.createNotificationChannels(NotificationManager.java:928)
at
android.app.NotificationManager.createNotificationChannel(NotificationManager.java:916)
at
com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.setupNotificationChannel(FlutterLocalNotificationsPlugin.java:999)
at
com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.createNotification(FlutterLocalNotificationsPlugin.java:203)
at
com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.showNotification(FlutterLocalNotificationsPlugin.java:1035)
at
com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.show(FlutterLocalNotificationsPlugin.java:1376)
at
com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.onMethodCall(FlutterLocalNotificationsPlugin.java:1245)
at
io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:262)
at
io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295)
at
io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319)
at
io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown
Source:12) at android.os.Handler.handleCallback(Handler.java:938) at
android.os.Handler.dispatchMessage(Handler.java:99) at
android.os.Looper.loopOnce(Looper.java:201) at
android.os.Looper.loop(Looper.java:288) at
android.app.ActivityThread.main(ActivityThread.java:7842) at
java.lang.reflect.Method.invoke(Native Method) at
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Caused by: android.os.RemoteException: Remote stack trace: at com.android.internal.util.Preconditions.checkArgument(Preconditions.java:44)
at
com.android.server.notification.PreferencesHelper.createNotificationChannel(PreferencesHelper.java:833)
at
com.android.server.notification.NotificationManagerService$11.createNotificationChannelsImpl(NotificationManagerService.java:3714) at
com.android.server.notification.NotificationManagerService$11.createNotificationChannels(NotificationManagerService.java:3735)
at
android.app.INotificationManager$Stub.onTransact(INotificationManager.java:1548)
))
相关代码:
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:rxdart/subjects.dart'; import 'package:timezone/timezone.dart' as tz; import 'package:timezone/data/latest.dart' as tz; class LocalNotificationService { LocalNotificationService(); final _localNotificationService = FlutterLocalNotificationsPlugin(); Future intialize() async { tz.initializeTimeZones(); const AndroidInitializationSettings androidInitializationSettings = AndroidInitializationSettings('@drawable/ic_stat_circle_notifications'); IOSInitializationSettings iosInitializationSettings = IOSInitializationSettings( requestAlertPermission: true, requestBadgePermission: true, requestSoundPermission: true, onDidReceiveLocalNotification: onDidReceivLocalNotification, ); final InitializationSettings settings = InitializationSettings( android: androidInitializationSettings, iOS: iosInitializationSettings, ); await _localNotificationService.initialize( settings, onSelectNotification: onSelectNotification, ); } Future _NotificationDetails() async { const AndroidNotificationDetails androidNotificationDetails = AndroidNotificationDetails( '', '', importance: Importance.max, priority: Priority.max, playSound: true, ); const IOSNotificationDetails iosNotificationDetails = IOSNotificationDetails(); return const NotificationDetails( android: androidNotificationDetails, ); } Future showNotification({ required int id, required String title, required String body, }) async { final details = await _NotificationDetails(); await _localNotificationService.show( id, title, body, details, ); } Future showSchedualedNotification({ required int id, required String title, required String body, required int seconds, }) async { final details = await _NotificationDetails(); await _localNotificationService.zonedSchedule( id, title, body, tz.TZDateTime.from( DateTime.now().add(Duration(seconds: seconds)), tz.local, ), details, androidAllowWhileIdle: true, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, ); } void onDidReceivLocalNotification( int id, String? title, String? body, String? payload) { print('id $id'); } void onSelectNotification(String? payload) { print('paylod $payload'); } }
错误原因
从错误栈的Caused by部分可以看到,错误源于Preconditions.checkArgument,说明传入的参数不符合Android系统要求。结合代码分析,问题出在AndroidNotificationDetails的构造参数上:你给channelId和channelName都传了空字符串'',而Android系统要求通知渠道的ID和名称不能为空,否则会触发IllegalArgumentException。
解决办法
修改_NotificationDetails方法中的AndroidNotificationDetails实例,给channelId和channelName传入非空值:
Future _NotificationDetails() async { const AndroidNotificationDetails androidNotificationDetails = AndroidNotificationDetails( 'default_notification_channel', // 非空的渠道ID,建议唯一标识 '默认通知渠道', // 非空的渠道名称,用户可见 importance: Importance.max, priority: Priority.max, playSound: true, ); const IOSNotificationDetails iosNotificationDetails = IOSNotificationDetails(); return const NotificationDetails( android: androidNotificationDetails, iOS: iosNotificationDetails, // 补充iOS参数,避免遗漏 ); }
注意:
channelId必须是唯一的字符串,建议使用反向域名格式(比如com.yourapp.notifications)避免冲突channelName是用户在系统设置中能看到的渠道名称,需要清晰易懂- 同时补充
iOS参数到NotificationDetails中,确保iOS端配置完整
内容的提问来源于stack exchange,提问作者Eng Raggad

