pushy / pushy-flutter

The official Pushy SDK for Flutter apps.
Apache License 2.0
21 stars 19 forks source link

backgroundNotificationListener not called when app built with --split-debug-info is killed. #44

Closed oexza closed 2 years ago

oexza commented 2 years ago

Pushy Flutter's notify method displays primitive notification. It is rigid and not customisable. Currently, if the app is dismissed from or killed calling a third party notification library does not work. (i'm using flutter_local_notifications specifically). i.e the below code should work even when app is killed or in background:

Future<void> backgroundNotificationListener(Map<String, dynamic> data) async {
  print('Received notification: $data');

  //initialise and call third party library here to display notification even when app is in background or killed,
  //instead of calling Pushy.notify
}

the above block only works if app is in foreground. One way to solve this would be to expand Pushy's notify method to be more customisable, but given the rich feature set of third party notification libraries, it may be better to find a way to make them work together.

pushy commented 2 years ago

Hi @oexza, Thanks for reaching out. We'd be glad to assist.

The correct approach in customizing the notification is indeed to use the flutter_local_notifications package, as you have done.

However, the issue you're facing with notifications not being displayed when your app is killed is not due to the use of this package over Pushy.notify(). We believe it is because of an improper declaration of the backgroundNotificationListener method signature.

You declared the method as follows:

Future<void> backgroundNotificationListener(Map<String, dynamic> data) async {

Whereas, as per the Pushy Flutter SDK docs, the declaration must be as follows (notice the missing async and Future<void> modifiers):

void backgroundNotificationListener(Map<String, dynamic> data) {

Furthermore, it is absolutely crucial that this method be placed in main.dart, outside any Widget class (e.g. right after import statements), for it to be accessible to the Flutter background isolate that is spawned when your app is killed, to execute the method without an activity / widget context.

Please confirm the above and retry your tests after making the requested changes, and let us know if the issue is resolved.

oexza commented 2 years ago

Hi @pushy thanks for replying. I just found out that it is a deeper problem. backgroundNotificationListener is not being called at all in release mode when app is killed! This is true regardless of the method signature.

oexza commented 2 years ago

and this is the error being thrown:

E/flutter (26755): [ERROR:flutter/shell/common/shell.cc(93)] Dart Unhandled Exception: NoSuchMethodError: No top-level getter '_isolate' declared.
E/flutter (26755): Receiver: top-level
E/flutter (26755): Tried calling: _isolate, stack trace: Warning: This VM has been configured to produce stack traces that violate the Dart standard.
E/flutter (26755): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
E/flutter (26755): pid: 26755, tid: 26971, name Unknown
E/flutter (26755): build_id: 'eeb20483baa6496efe323ac8622388f6'
E/flutter (26755): isolate_dso_base: bf649000, vm_dso_base: bf649000
E/flutter (26755): isolate_instructions: bf718830, vm_instructions: bf715000
E/flutter (26755):     #00 abs bf73ff07 virt 000f6f07 _kDartIsolateSnapshotInstructions+0x276d7
E/flutter (26755): 
E/flutter (26755): [ERROR:flutter/runtime/dart_isolate.cc(681)] Could not resolve main entrypoint function.
E/flutter (26755): [ERROR:flutter/runtime/dart_isolate.cc(165)] Could not run the run main Dart entrypoint.
E/flutter (26755): [ERROR:flutter/runtime/runtime_controller.cc(381)] Could not create root isolate.
E/flutter (26755): [ERROR:flutter/shell/common/shell.cc(580)] Could not launch engine with configuration.
oexza commented 2 years ago

flutter version is 2.10.5

pushy commented 2 years ago

Hi @oexza, Thanks for the further information.

We find that problems in release mode are usually caused by ProGuard. Can you please confirm whether the following lines are present in your android/app/proguard-rules.pro file?

-dontwarn me.pushy.**
-keep class me.pushy.** { *; }
-keep class androidx.core.app.** { *; }
-keep class android.support.v4.app.** { *; }
oexza commented 2 years ago

Yes it is present. All instructions followed to the letter. @pushy You can try it yourself.

oexza commented 2 years ago

@pushy any luck?

pushy commented 2 years ago

Hi @oexza, Thanks for confirming.

Would you be able to share the entire contents of your lib/main.dart file? Feel free to send it via e-mail to support@pushy.me if you prefer not to share it here.

oexza commented 2 years ago

@pushy to make this easier I have uploaded a repo here https://github.com/oexza/test-pushy its basically the default flutter starter app with pushy integrated. To experience the bug run:

flutter build apk --no-shrink --split-debug-info=~/Desktop/find --no-sound-null-safety --split-per-abi and install the resulting apk. Kill the app and send a notification from the pushy console.

oexza commented 2 years ago

@pushy sorry for the continuous push, but this issue is the sole reason we cannot launch our app.

pushy commented 2 years ago

Hi @oexza, Thanks for providing the sample project, and for your patience.

We were able to reproduce the issue, and narrowed it down to the --split-debug-info=~/Desktop/find parameter in your flutter build apk command. After omitting this parameter, the issue is no longer reproducible, and the app receives notifications after being killed.

Please omit this parameter from your command, and let us know if it resolves the issue.

oexza commented 2 years ago

Thanks @pushy! So the issue arises when the dart code is built with --split-debug-info. Without it, everything works fine. But this is still a problem to be solved. I doubt that the issue should be closed since there's no where in the documentation that says that this plugin does not work with obfuscated dart code (assuming that there is no solution to making it work). I would suggest you re-open it.

pushy commented 2 years ago

Hi @oexza, Correct. Unfortunately, it is an upstream issue with Flutter not supporting background isolate functionality when enabling Dart code obfuscation (see https://github.com/flutter/flutter/issues/98475).

Since it is an upstream issue with Flutter, it must be resolved by the Flutter team. For the time being, you will not be able to use the Pushy Flutter SDK with Dart code obfuscation enabled. We apologize for the inconvenience.

oexza commented 2 years ago

Hi @pushy thanks. take a look at this https://github.com/dart-lang/sdk/issues/49181 I may be wrong, but it looks like something needs to change within pushy-flutter to recognise @pragma('vm:entry-point') or @pragma('custom-pushy-entry') without which it will not work with obfuscated code.

pushy commented 2 years ago

Hi @oexza, We attempted to add the @pragma('vm:entry-point') annotation, but it did not resolve the issue. You're welcome to experiment with this further if you'd like, by modifying pushy_flutter.dart accordingly.

For the time being, the Pushy Flutter SDK will not support building APKs with Dart code obfuscation. We apologize for the inconvenience.

oexza commented 2 years ago

Hi @pushy I did take your advice and dug further, and I think I figured it out. here's the PR https://github.com/pushy/pushy-flutter/pull/45 with the fix. It turns out that the isolate entry point needed to just be annotated with @pragma('vm:entry-point') and the problem goes away.

pushy commented 2 years ago

Hi @oexza, Thanks for the PR. When we build using the aforementioned @pragma('vm:entry-point') annotation, it breaks functionality of both obfuscated and non-obfuscated isolate background execution.

It might have to do with the Flutter version we're using. Therefore, at this time, we will not be merging the PR. However, we're glad you were able to resolve the issue and get obfuscated builds to work for you.

pushy commented 2 years ago

Hi @oexza , Thanks for your patience.

We believe commit https://github.com/pushy/pushy-flutter/commit/57a2178dadb5fccee84861438dc258bc43050f90 has now resolved this issue.

1) Please update the Pushy Flutter SDK in your app by editing the pubspec.yaml in the root directory of your project and updating the pushy_flutter package version to 2.0.9:

pushy_flutter: 2.0.9

2) Run flutter pub get to fetch the new version of our SDK.

3) Please add the following line of code to your lib/main.dart, right above the void backgroundNotificationListener() method declaration:

@pragma('vm:entry-point')

Please run your app again with --split-debug-info and let us know if the problem is indeed resolved.