Skip to content

Commit

Permalink
Merge pull request #208 from ably/fix/push-back-button-background
Browse files Browse the repository at this point in the history
Fix app crashing when receiving multiple push notifications
  • Loading branch information
ben-xD committed Nov 10, 2021
2 parents 9f67171 + 15044ee commit 9c9a51c
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 15 deletions.
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

0 comments on commit 9c9a51c

Please sign in to comment.