Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix app crashing when receiving multiple push notifications #208

Merged
merged 5 commits into from Nov 10, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -26,24 +26,37 @@ public class FirebaseMessagingReceiver extends BroadcastReceiver {
@Nullable
private PendingResult asyncProcessingPendingResult = null;

@Nullable
private BackgroundMessageProcessingCompleteReceiver backgroundMessageProcessingCompleteReceiver = null;

@Override
public void onReceive(Context context, Intent intent) {
final Boolean isApplicationInForeground = isApplicationInForeground(context);
final RemoteMessage message = new RemoteMessage(intent.getExtras());
final RemoteMessage.Notification notification = message.getNotification();
final boolean isDataMessage = !message.getData().isEmpty();
if (!isDataMessage) {
// Do not send a RemoteMessage without any data, to be consistent with iOS:
// it doesn't call `didReceiveRemoteNotification` in this case.
Log.d(TAG, "Not sending message to dart side because it is a notification message without any data.");
return;
}
setupFlutterApplicationProcessingCompletionReceiver(context);
sendMessageToFlutterApplication(context, intent);
}

/**
* Launches a broadcast receiver ([BackgroundMessageProcessingCompleteReceiver]) so that the
* enclosing receiver (FirebaseMessagingReceiver), can be informed when the Flutter
* application completes. The Flutter application also has a receiver
* (PushMessagingEventHandlers.BroadcastReceiver) to listen to messages from this receiver
* (FirebaseMessagingReceiver).
*/
private void setupFlutterApplicationProcessingCompletionReceiver(Context context) {
// Wait for Flutter application to process message
// At the end of the receiver's execution time (and user's application processing the message)
// , Firebase messaging library will automatically create a notification.
// , Firebase messaging library will automatically create a notification.
// On iOS, the notification may be shown before the message is processed by the application.
// goAsync() also increases the execution time from 10s/ 20s (depending on API level) to 30s
new BackgroundMessageProcessingCompleteReceiver(context);
asyncProcessingPendingResult = goAsync();
if (backgroundMessageProcessingCompleteReceiver == null) {
backgroundMessageProcessingCompleteReceiver = new BackgroundMessageProcessingCompleteReceiver(context);
asyncProcessingPendingResult = goAsync();
}
}

private void sendMessageToFlutterApplication(Context context, Intent intent) {
final RemoteMessage message = new RemoteMessage(intent.getExtras());
final Boolean isApplicationInForeground = isApplicationInForeground(context);

if (isApplicationInForeground) {
// Send message to Dart side app already running
Expand All @@ -59,9 +72,10 @@ public void onReceive(Context context, Intent intent) {
// No existing Flutter Activity is running, create a FlutterEngine and pass it the RemoteMessage
new PushBackgroundIsolateRunner(context, this, message);
}

}

Boolean isApplicationInForeground(final Context context) {
private Boolean isApplicationInForeground(final Context context) {
final ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
// This only shows processes for the current android app.
final List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
Expand All @@ -80,6 +94,9 @@ Boolean isApplicationInForeground(final Context context) {
return false;
}

/**
* A dynamic broadcast receiver registered to listen to a `PUSH_ON_BACKGROUND_MESSAGE_PROCESSING_COMPLETE`
*/
class BackgroundMessageProcessingCompleteReceiver extends BroadcastReceiver {
BackgroundMessageProcessingCompleteReceiver(final Context context) {
final IntentFilter filter = new IntentFilter();
Expand All @@ -89,6 +106,11 @@ class BackgroundMessageProcessingCompleteReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
if (backgroundMessageProcessingCompleteReceiver != null) {
LocalBroadcastManager.getInstance(context).unregisterReceiver(backgroundMessageProcessingCompleteReceiver);
backgroundMessageProcessingCompleteReceiver = null;
}

String action = intent.getAction();
if (action.equals(PUSH_ON_BACKGROUND_MESSAGE_PROCESSING_COMPLETE)) {
finish();
Expand Down
Expand Up @@ -51,7 +51,6 @@ private void register(Context context) {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Bundle intentExtras = intent.getExtras();
RemoteMessage message = new RemoteMessage(intent.getExtras());
switch (action) {
case PUSH_ON_MESSAGE_RECEIVED:
Expand Down
1 change: 1 addition & 0 deletions example/lib/main.dart
Expand Up @@ -142,6 +142,7 @@ class _MyAppState extends State<MyApp> {

Future<void> createAblyRest() async {
final clientOptions = ably.ClientOptions.fromKey(_apiKey)
..clientId = Constants.clientId
..logLevel = ably.LogLevel.verbose
..logHandler = ({msg, exception}) {
print('Custom logger :: $msg $exception');
Expand Down