Merge pull request #1074 from dluksza/android-notification-action-background-handler
Implement handling of Android actions in background
This commit is contained in:
commit
640d7aa7ae
|
@ -294,9 +294,11 @@ public class DisplayNotificationTask extends AsyncTask<Void, Void, Void> {
|
|||
}
|
||||
|
||||
private NotificationCompat.Action createAction(Bundle action, Class intentClass, Bundle notification) {
|
||||
boolean runInBackground = action.containsKey("runInBackground") && action.getBoolean("runInBackground");
|
||||
String actionKey = action.getString("action");
|
||||
PendingIntent actionIntent = createIntent(intentClass, notification, actionKey);
|
||||
|
||||
PendingIntent actionIntent = runInBackground ?
|
||||
createBroadcastIntent(notification, actionKey) :
|
||||
createIntent(intentClass, notification, actionKey);
|
||||
int icon = getIcon(action.getString("icon"));
|
||||
String title = action.getString("title");
|
||||
|
||||
|
@ -334,10 +336,21 @@ public class DisplayNotificationTask extends AsyncTask<Void, Void, Void> {
|
|||
}
|
||||
|
||||
String notificationId = notification.getString("notificationId");
|
||||
|
||||
return PendingIntent.getActivity(context, notificationId.hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
private PendingIntent createBroadcastIntent(Bundle notification, String action) {
|
||||
Intent intent = new Intent(context, RNFirebaseBackgroundNotificationActionReceiver.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
|
||||
String notificationId = notification.getString("notificationId") + action;
|
||||
|
||||
intent.setAction("io.invertase.firebase.notifications.BackgroundAction");
|
||||
intent.putExtra("action", action);
|
||||
intent.putExtra("notification", notification);
|
||||
return PendingIntent.getBroadcast(context, notificationId.hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
private RemoteInput createRemoteInput(Bundle remoteInput) {
|
||||
String resultKey = remoteInput.getString("resultKey");
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
package io.invertase.firebase.notifications;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.facebook.react.HeadlessJsTaskService;
|
||||
import com.facebook.react.ReactApplication;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
|
||||
import io.invertase.firebase.Utils;
|
||||
|
||||
public class RNFirebaseBackgroundNotificationActionReceiver extends BroadcastReceiver {
|
||||
static boolean isBackgroundNotficationIntent(Intent intent) {
|
||||
return intent.getExtras() != null && intent.hasExtra("action") && intent.hasExtra("notification");
|
||||
}
|
||||
|
||||
static WritableMap toNotificationOpenMap(Intent intent) {
|
||||
Bundle extras = intent.getExtras();
|
||||
WritableMap notificationMap = Arguments.makeNativeMap(extras.getBundle("notification"));
|
||||
WritableMap notificationOpenMap = Arguments.createMap();
|
||||
notificationOpenMap.putString("action", extras.getString("action"));
|
||||
notificationOpenMap.putMap("notification", notificationMap);
|
||||
return notificationOpenMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (!isBackgroundNotficationIntent(intent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Utils.isAppInForeground(context)) {
|
||||
WritableMap notificationOpenMap = toNotificationOpenMap(intent);
|
||||
|
||||
ReactApplication reactApplication = (ReactApplication)context.getApplicationContext();
|
||||
ReactContext reactContext = reactApplication.getReactNativeHost().getReactInstanceManager().getCurrentReactContext();
|
||||
|
||||
Utils.sendEvent(reactContext, "notifications_notification_opened", notificationOpenMap);
|
||||
} else {
|
||||
Intent serviceIntent = new Intent(context, RNFirebaseBackgroundNotificationActionsService.class);
|
||||
serviceIntent.putExtras(intent.getExtras());
|
||||
context.startService(serviceIntent);
|
||||
HeadlessJsTaskService.acquireWakeLockNow(context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package io.invertase.firebase.notifications;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
import com.facebook.react.HeadlessJsTaskService;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.jstasks.HeadlessJsTaskConfig;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static io.invertase.firebase.notifications.RNFirebaseBackgroundNotificationActionReceiver.isBackgroundNotficationIntent;
|
||||
import static io.invertase.firebase.notifications.RNFirebaseBackgroundNotificationActionReceiver.toNotificationOpenMap;
|
||||
|
||||
public class RNFirebaseBackgroundNotificationActionsService extends HeadlessJsTaskService {
|
||||
@Override
|
||||
protected @Nullable HeadlessJsTaskConfig getTaskConfig(Intent intent) {
|
||||
if (isBackgroundNotficationIntent(intent)) {
|
||||
WritableMap notificationOpenMap = toNotificationOpenMap(intent);
|
||||
|
||||
return new HeadlessJsTaskConfig(
|
||||
"RNFirebaseBackgroundNotificationAction",
|
||||
notificationOpenMap,
|
||||
60000,
|
||||
true
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1277,6 +1277,7 @@ declare module 'react-native-firebase' {
|
|||
semanticAction?: SemanticAction;
|
||||
showUserInterface?: boolean;
|
||||
title: string;
|
||||
runInBackground?: boolean;
|
||||
|
||||
constructor(action: string, icon: string, title: string);
|
||||
|
||||
|
@ -1284,6 +1285,7 @@ declare module 'react-native-firebase' {
|
|||
setAllowGenerateReplies(allowGeneratedReplies: boolean): Action;
|
||||
setSemanticAction(semanticAction: SemanticAction): Action;
|
||||
setShowUserInterface(showUserInterface: boolean): Action;
|
||||
setRunInBackground(runInBackground: boolean): Action;
|
||||
}
|
||||
|
||||
class RemoteInput {
|
||||
|
|
|
@ -16,6 +16,7 @@ export default class AndroidAction {
|
|||
_semanticAction: SemanticActionType | void;
|
||||
_showUserInterface: boolean | void;
|
||||
_title: string;
|
||||
_runInBackground: boolean | void;
|
||||
|
||||
constructor(action: string, icon: string, title: string) {
|
||||
this._action = action;
|
||||
|
@ -52,6 +53,10 @@ export default class AndroidAction {
|
|||
return this._title;
|
||||
}
|
||||
|
||||
get runInBackground(): ?boolean {
|
||||
return this._runInBackground;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param remoteInput
|
||||
|
@ -102,6 +107,16 @@ export default class AndroidAction {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param runInBackground
|
||||
* @returns {AndroidAction}
|
||||
*/
|
||||
setRunInBackground(runInBackground: boolean): AndroidAction {
|
||||
this._runInBackground = runInBackground
|
||||
return this;
|
||||
}
|
||||
|
||||
build(): NativeAndroidAction {
|
||||
if (!this._action) {
|
||||
throw new Error('AndroidAction: Missing required `action` property');
|
||||
|
@ -119,6 +134,7 @@ export default class AndroidAction {
|
|||
semanticAction: this._semanticAction,
|
||||
showUserInterface: this._showUserInterface,
|
||||
title: this._title,
|
||||
runInBackground: this._runInBackground
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -145,6 +161,9 @@ export const fromNativeAndroidAction = (
|
|||
if (nativeAction.showUserInterface) {
|
||||
action.setShowUserInterface(nativeAction.showUserInterface);
|
||||
}
|
||||
if (nativeAction.runInBackground) {
|
||||
action.setRunInBackground(nativeAction.runInBackground);
|
||||
}
|
||||
|
||||
return action;
|
||||
};
|
||||
|
|
|
@ -136,6 +136,7 @@ export type NativeAndroidAction = {|
|
|||
semanticAction?: SemanticActionType,
|
||||
showUserInterface?: boolean,
|
||||
title: string,
|
||||
runInBackground?: boolean,
|
||||
|};
|
||||
|
||||
export type NativeAndroidNotification = {|
|
||||
|
|
Loading…
Reference in New Issue