flutter_local_notifications icon indicating copy to clipboard operation
flutter_local_notifications copied to clipboard

Exception NoSuchMethodError

Open zagalaga opened this issue 2 years ago • 13 comments

With plugin version 9.6.1 I see the following crash for some users, I was not able to replicate it myself. Does anybody know if this is a bug or if I am doing something wrong?

Fatal Exception: java.lang.NoSuchMethodError: No static method e(Landroid/content/Context;)Landroidx/core/app/n; in class Landroidx/core/app/n; or its super classes (declaration of 'androidx.core.app.n' appears in /data/app/~~v8yhhqH2FHoMiGDXLA-pgQ==/androidx.test.tools.crawler-WljZg1GOGnOmmNq4rJSXqg==/base.apk) at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.getNotificationManager(FlutterLocalNotificationsPlugin.java) at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.cancelAllNotifications(FlutterLocalNotificationsPlugin.java:2) at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.onMethodCall(FlutterLocalNotificationsPlugin.java:323) at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:17) at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:18) at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0(DartMessenger.java:20) at io.flutter.embedding.engine.dart.DartMessenger.$r8$lambda$TsixYUB5E6FpKhMtCSQVHKE89gQ(DartMessenger.java) at io.flutter.embedding.engine.dart.DartMessenger$$InternalSyntheticLambda$0$ceffc6bae7d364cb48afaf1aaebd60bf9050360d0efb9035ebc54f0851df0a05$0.run(DartMessenger.java: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:7839) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)

zagalaga avatar Jul 03 '22 06:07 zagalaga

I'm having a similar issue too (Flutter 2.10.5 / Dart 2.16.2).

I uploaded my app to the Google Play Store and the Pre-launch report brought up this crash report:

java.lang.NoSuchMethodError: No static method e(Landroid/content/Context;)Landroidx/core/app/i; in class Landroidx/core/app/i; or its super classes (declaration of 'androidx.core.app.i' appears in base.apk)
	at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.getNotificationManager(Unknown Source:0)
	at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.cancelAllNotifications(Unknown Source:2)
	at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.onMethodCall(Unknown Source:323)
	at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(Unknown Source:17)
	at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(Unknown Source:18)
	at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0(Unknown Source:20)
	at io.flutter.embedding.engine.dart.DartMessenger.a(Unknown Source:0)
	at io.flutter.embedding.engine.dart.a.run(Unknown Source:12)
	at android.os.Handler.handleCallback(Handler.java:873)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at androidx.test.espresso.base.Interrogator.loopAndInterrogate(Interrogator.java:10)
	at androidx.test.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:7)
	at androidx.test.espresso.base.UiControllerImpl.loopMainThreadUntilIdle(UiControllerImpl.java:16)
	at androidx.test.espresso.ViewInteraction.doPerform(ViewInteraction.java:3)
	at androidx.test.espresso.ViewInteraction.-$$Nest$mdoPerform(Unknown Source:0)
	at androidx.test.espresso.ViewInteraction$1.call(ViewInteraction.java:6)
	at androidx.test.espresso.ViewInteraction$1.call(ViewInteraction.java:1)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at android.os.Handler.handleCallback(Handler.java:873)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loop(Looper.java:193)
	at android.app.ActivityThread.main(ActivityThread.java:6669)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

tnaseem avatar Jul 05 '22 00:07 tnaseem

Difficult for me to say what is going with a minimal app and steps to reproduce this. Things that come mind are if Proguard rules were configured correctly or perhaps that are other settings your apps needs based on your situation that may not be applicable to all apps e.g. enabling multidex

MaikuB avatar Jul 07 '22 10:07 MaikuB

Thanks for your reply. I did check the Proguard rules and, as far as I can see, it's set up correctly I think. It's below, if want want to take a look - See if there's anything I've missed!

## Flutter wrapper
-keep class io.flutter.app.** { *; }
-keep class io.flutter.plugin.**  { *; }
-keep class io.flutter.util.**  { *; }
-keep class io.flutter.view.**  { *; }
-keep class io.flutter.**  { *; }
-keep class io.flutter.plugins.**  { *; }
-dontwarn io.flutter.embedding.**

## Gson rules
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# For using GSON @Expose annotation
-keepattributes *Annotation*

# Gson specific classes
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }

# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * implements com.google.gson.TypeAdapter
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer

# Prevent R8 from leaving Data object members always null
-keepclassmembers,allowobfuscation class * {
  @com.google.gson.annotations.SerializedName <fields>;
}

# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher.
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken

tnaseem avatar Jul 07 '22 22:07 tnaseem

My Notifications class helper, in case it's useful. You'll see a few Crashlytics logs in there, as I was trying to determine where it was crashing. In each case, it was crashing in the init() function with the call to await flutterLocalNotificationsPlugin.initialize()

import 'dart:async';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/material.dart';

import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:timezone/data/latest.dart' as tz;
import 'package:timezone/timezone.dart' as tz;

import 'package:whitu/helpers/native_timezone.dart';

FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
NotificationAppLaunchDetails notificationAppLaunchDetails;

// Notification channels
class NotificationChannel {
  final String id;
  final String name;
  final String description;

  const NotificationChannel({this.id, this.name, this.description});
}

// Singleton notifications helper.
class Notifications {

  // Singleton.
  static final Notifications _instance = new Notifications.internal();
  factory Notifications() => _instance;

  Notifications.internal();

  // Notification channels.
  static const NotificationChannel appChannel = NotificationChannel(
    id: 'Main', name: 'Main App Notifications', description: 'App notifications');

  static const NotificationChannel dailyChannel = NotificationChannel(
    id: 'Daily', name: 'Daily Reminders', description: 'Receive daily reminders');

  // Cancel notifications.
  Future<void> cancel({@required int id}) async => await flutterLocalNotificationsPlugin.cancel(id);
  Future<void> cancelAll() async => await flutterLocalNotificationsPlugin.cancelAll();

  // Initialise on create. We should only do this once.
  Future<void> init() async {

    FirebaseCrashlytics.instance.log("notifications: Get local time zone.");
    await _getLocalTimeZone();

    notificationAppLaunchDetails = await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();

    // Initialise the plugin. app_icon.png needs to be a added as a drawable resource in
    // android/app/src/main/res/drawable.
    FirebaseCrashlytics.instance.log("notifications: Add Android initialisation settings.");
    var initializationSettingsAndroid = AndroidInitializationSettings('notification_icon');

    // Ask for permissions on iOS, on app start.
    FirebaseCrashlytics.instance.log("notifications: Add iOS initialisation settings.");
    var initializationSettingsIOS = IOSInitializationSettings(
      requestSoundPermission: true,
      requestBadgePermission: true,
      requestAlertPermission: true,
      onDidReceiveLocalNotification: _onDidReceiveLocalNotification,
    );

    FirebaseCrashlytics.instance.log("notifications: Apply Android/iOS initialisation settings.");

    var initializationSettings = InitializationSettings(
      android: initializationSettingsAndroid,
      iOS: initializationSettingsIOS,
    );

    FirebaseCrashlytics.instance.log("notifications: Initialise the notifications.");
    
    // What we should call when the user taps on the notification.
    await flutterLocalNotificationsPlugin.initialize(
      initializationSettings,
      onSelectNotification: _onSelectNotification,
    );
  }

  // Display a simple notification.
  Future<void> show({
    int id = 0,
    @required String title,
    String body,
    String payload,
  }) async {
    BigTextStyleInformation style = _styleText(title: title, body: body);
    await flutterLocalNotificationsPlugin.show(
      id, title, body, _notificationDetails(appChannel, style), payload: payload);
  }

  Future<void> showDaily({
    int id = 0,
    @required Time time,
    @required String title,
    String body,
    String payload,
  }) async {
    BigTextStyleInformation style = _styleText(title: title, body: body);
    await flutterLocalNotificationsPlugin.zonedSchedule(
      id,
      title,
      body,
      _nextInstanceOfTime(time),
      _notificationDetails(dailyChannel, style),
      payload: payload,
      matchDateTimeComponents: DateTimeComponents.time,
      androidAllowWhileIdle: true,
      uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime,
    );
  }

  // Get the next occurrence of the specified notification time.
  tz.TZDateTime _nextInstanceOfTime(Time time) {
    final tz.TZDateTime now = tz.TZDateTime.now(tz.local);
    tz.TZDateTime scheduledDate =
    tz.TZDateTime(tz.local, now.year, now.month, now.day, time.hour, time.minute);

    // Add a day, if the time has already passed.
    if (scheduledDate.isBefore(now)) {
      scheduledDate = scheduledDate.add(const Duration(days: 1));
    }

    return scheduledDate;
  }

  // Retrieve the phone's current time zone.
  Future<void> _getLocalTimeZone() async {
    tz.initializeTimeZones();
    final String timezoneName = await NativeTimezone.getLocalTimezone();
    tz.setLocalLocation(tz.getLocation(timezoneName));
  }

  // Callback for handling when a notification is triggered while the app is in the foreground.
  Future<void> _onDidReceiveLocalNotification(int id, String title, String body, String payload) async {
    if (payload != null) {
      debugPrint('iOS notification payload: ${payload ?? 'None'}');
    }
  }

  // Calback for when the notification has been tapped on.
  Future<void> _onSelectNotification(String payload) async {
    if (payload != null) {
      debugPrint('nNotification payload: ${payload ?? 'None'}');
    }
  }

  BigTextStyleInformation _styleText({String title, String body}) {
    return BigTextStyleInformation(
      body,
      htmlFormatBigText: true,
      contentTitle: title,
      htmlFormatContentTitle: true,
    );
  }
  // Platform channel specifics.
  NotificationDetails _notificationDetails(
    NotificationChannel channel,
    BigTextStyleInformation styleInformation,
  ) {
    var androidPlatformChannelSpecifics = AndroidNotificationDetails(
      channel.id, channel.name,
      channelDescription: channel.description,
      styleInformation: styleInformation,
      importance: Importance.high,
      priority: Priority.high,
      ticker: 'ticker',
    );

    var iOSPlatformChannelSpecifics = IOSNotificationDetails();
    return NotificationDetails(
      android: androidPlatformChannelSpecifics,
      iOS: iOSPlatformChannelSpecifics,
    );
  }
}

tnaseem avatar Jul 07 '22 22:07 tnaseem

The rules look fine to me for the gson stuff. Not sure about the Flutter ones. One thing to note is logs point to an error where it looks like it can't resolve a method within the Android APIs themselves as opposed to something from this plugin so not something I can help with

MaikuB avatar Jul 07 '22 22:07 MaikuB

@tnaseem providing Dart code won't help with these issues, which is why I mentioned a minimal app and that could be a link to a GitHub repo

MaikuB avatar Jul 07 '22 22:07 MaikuB

No worries. I'll get it done after the weekend and see if it still happens. I'll need to run the test on Firebase TestLab to see if it shows up the crashes then. Only seems to happen on a few of their test devices.

tnaseem avatar Jul 07 '22 22:07 tnaseem

I am using the latest GSON rules and it is still happening

zagalaga avatar Jul 10 '22 06:07 zagalaga

This also started showing for me in crashlytics:

Fatal Exception: java.lang.NoSuchMethodError: No static method e(Landroid/content/Context;)Landroidx/core/app/l; in class Landroidx/core/app/l; or its super classes (declaration of 'androidx.core.app.l' appears in base.apk)
       at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.getNotificationManager(FlutterLocalNotificationsPlugin.java)
       at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.cancelAllNotifications(FlutterLocalNotificationsPlugin.java:2)
       at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.onMethodCall(FlutterLocalNotificationsPlugin.java:323)
       at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:17)
       at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:18)
       at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0(DartMessenger.java:20)
       at io.flutter.embedding.engine.dart.DartMessenger.$r8$lambda$TsixYUB5E6FpKhMtCSQVHKE89gQ(DartMessenger.java)
       at io.flutter.embedding.engine.dart.DartMessenger$$InternalSyntheticLambda$0$ceffc6bae7d364cb48afaf1aaebd60bf9050360d0efb9035ebc54f0851df0a05$0.run(DartMessenger.java:12)
       at android.os.Handler.handleCallback(Handler.java:873)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:214)
       at android.app.ActivityThread.main(ActivityThread.java:7050)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)

No code changes or new release, started appearing 6 days ago

armandojimenez avatar Jul 11 '22 05:07 armandojimenez

Found this, looks related: https://issuetracker.google.com/issues/238234609

armandojimenez avatar Jul 11 '22 05:07 armandojimenez

That's interesting, in Crashlytics mine appears on those same devices mentioned in the last comment on that thread. ie.:

  • Galaxy S20 5G
  • Galaxy 8
  • AQUOS sense2 SH-01L
  • Pixel 5

(https://issuetracker.google.com/issues/238234609#comment6)

tnaseem avatar Jul 11 '22 10:07 tnaseem

That's interesting, in Crashlytics mine appears on those same devices mentioned in the last comment on that thread. ie.:

  • Galaxy S20 5G
  • Galaxy 8
  • AQUOS sense2 SH-01L
  • Pixel 5

(https://issuetracker.google.com/issues/238234609#comment6)

That's my comment 😅, I confirmed later that this only happens when the pre release report is running

ArmandoJimenezOS avatar Jul 13 '22 19:07 ArmandoJimenezOS

Looks like this is to do with an issue outside of the plugin. Will keep this open for now so others know about this.

MaikuB avatar Jul 23 '22 00:07 MaikuB

According to the comment at https://issuetracker.google.com/issues/237785592#comment96, this has been fixed by the Google team so will close this

MaikuB avatar Aug 29 '22 10:08 MaikuB