-
Notifications
You must be signed in to change notification settings - Fork 28
using launch activity resets my app #14
Comments
For this part its intentional - as not every action needs to launch an activity, e.g. 'liking a post' action doesn't need to open the app as an example. In terms of it launching a fresh activity every-time I think this is down to the launch mode we use internally - we'll take a look. (cc @Ehesp I think this is the code in @LuisRodriguezLD as part of your app startup (or Activity in this case) you should be calling |
This is also happening for me and is undesirable in my case. When my calling app is in the background, I provide users with action buttons to either answer or decline a call on receipt of a notification. Here is my 'Answer' launch activity: actions: [
{
title: 'Answer',
pressAction: {
id: 'answer',
launchActivity: 'default',
},
}, However, because the app is in the background, it means the app has already been launched which means the user doesn't need to authenticate and event listeners in the app trigger router actions when an incoming call occurs (which also happens when the app is in the background). So what I need is for the user to be able to press 'Answer' and the launch action is to bring the app from the background, to the foreground and nothing else. Right now this almost behaves like What would be ideal in my case would be something like I am trying to migrate from custom native Java modules to Notifee for handling notifications and the behaviour I describe is what happens when I create and press a notification using this code: @ReactMethod
void createNotification(String notificationMessage, int notificationID, String contentText) {
ReactApplicationContext context = getReactApplicationContext();
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder;
Resources res = context.getResources();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
String CHANNEL_ID = "channel_ID_0";
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "channel",
NotificationManager.IMPORTANCE_HIGH);
channel.setDescription("incoming call");
manager.createNotificationChannel(channel);
builder = new NotificationCompat.Builder(context, CHANNEL_ID);
} else {
builder = new NotificationCompat.Builder(context);
}
// Flag indicating that if the described PendingIntent already exists, the
// current one should be canceled before generating a new one.
Intent activityIntent = new Intent(context, MainActivity.class);
activityIntent.putExtra("FromNotification", true);
PendingIntent action = PendingIntent.getActivity(context, 0, activityIntent, PendingIntent.FLAG_CANCEL_CURRENT);
builder.setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.ic_stat_icon_))
.setSmallIcon(R.drawable.ic_stat_icon_).setTicker("Large text!").setAutoCancel(true)
.setContentTitle(notificationMessage).setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_CALL).setContentText(contentText)
.setFullScreenIntent(action, true);
Notification notification = builder.build();
int notificationCode = notificationID;
manager.notify(notificationCode, notification);
} |
I wonder if we can provide the ability to pass something down which determines the launch behaviour - when building the library out we did have a chat about this, but it would make sense to let the user be in-control. Maybe something like an ENUM on JS side, which is sent to the intent. |
This would really help, thanks 👌🏼 |
Hey @whenmoon I've just had a play around, essentially under the hood we create and launch a new Intent when something happens. Right now, there are no flags on the intent which causes the activity to "relaunch". If I set it to cc @Salakar I remember we looked into this, can you remember a reason we decided to not use |
@Ehesp would you mind providing a code snippet of where to add this flag within the library as a workaround whilst we wait for 'official' support for it? Thanks |
This should be in a version later today / tomorrow as |
Hey,
Here's an example using import { AndroidStyle, AndroidLaunchActivityFlag } from '@notifee/react-native';
const notification = {
title: 'Testing SINGLE_TOP launch.',
body: 'Expand for a cat!',
android: {
channelId: 'foo',
pressAction: {
id: 'default',
launchActivity: 'default',
launchActivityFlags: [AndroidLaunchActivityFlag.SINGLE_TOP],
},
style: {
type: AndroidStyle.BIGPICTURE,
picture: 'https://icatcare.org/app/uploads/2018/07/Thinking-of-getting-a-cat.png',
},
},
}; |
Hi @Salakar, would it be possible to provide an example of how to use this where the app is launched / bought to foreground and app state stays intact? At the moment with this code: actions: [
{
title: 'Answer',
pressAction: {
id: 'answer',
launchActivity: 'default',
launchActivityFlags: [AndroidLaunchActivityFlag.SINGLE_TOP],
},
}, or using Thanks |
Hmm - I can't reproduce, I have it working https://developer.android.com/reference/android/content/Intent#FLAG_ACTIVITY_SINGLE_TOP is supposed to be the one / https://stackoverflow.com/a/19627387/9910298 I had the same problem as I integrated Notifee just now - no action on tapping a notification I naively popped up with no pressAction set - and after setting it like this, it works: APKUpdateService.VERSION_NOTIFICATION_ID = await notifee.displayNotification({
id: APKUpdateService.VERSION_NOTIFICATION_ID,
title: I18NService.translate('UpdateAvailableTitle'),
body: I18NService.translate('UpdateAvailableText'),
android: {
channelId: APKUpdateService.UPDATE_NOTIFICATION_CHANNEL_ID,
smallIcon: 'drawable/minilogo_bw',
pressAction: {
id: 'default',
launchActivity: 'default',
launchActivityFlags: [AndroidLaunchActivityFlag.SINGLE_TOP],
},
},
}); Maybe you have device developer setting "keep activities" set to false or similar? |
Hi @mikehardy, hmmm ok thinking about this I would bet that what's stopping it working for me is the fact that I have another notification set up to launch a custom React component. backgroundIncomingCallNotification.js: actions: [
{
title: 'Answer',
pressAction: {
id: 'answer',
launchActivity: 'default',
launchActivityFlags: [AndroidLaunchActivityFlag.SINGLE_TOP],
},
}, killedIncomingCallNotification.js: actions: [
{
title: 'Answer',
pressAction: {
id: 'answer',
mainComponent: 'app-router',
},
}, Then I obviously have the custom component registered etc as described here If you register a custom component for another notification does it still work? The fact that they have the same id doesn't matter right now as they have not been used together yet. I'll do some proper testing later cheers. |
Ok I've tried to test this as much as possible and I'm getting very inconsistent results unfortunately. Sometimes on pressing a
notifee.onBackgroundEvent(async ({ type, detail }) => {
const { notification, pressAction } = detail;
const cancelIncomingCallActions = async () => {
await notifee.cancelNotification(notification.id);
}
if (type === EventType.ACTION_PRESS && pressAction.id === 'answer') {
store.dispatch(answerCall());
cancelIncomingCallActions();
}
});
const backgroundIncomingCallNotification = async (
notificationTitle,
notificationBody,
notificationID,
) => {
const channelId = await notifee.createChannel({
id: notificationID,
name: 'Incoming Call',
importance: AndroidImportance.HIGH,
visibility: AndroidVisibility.PUBLIC,
});
try {
await notifee.displayNotification({
title: `<p style="color: #C9FB5C;"><b>${notificationTitle}</span></p></b></p> 👋`,
description: 'Description',
android: {
ongoing: true,
category: AndroidCategory.CALL,
channelId,
importance: AndroidImportance.HIGH,
visibility: AndroidVisibility.PUBLIC,
color: COL_BASE_YELLOW,
vibrationPattern: [300, 500],
smallIcon: 'ic_stat_icon_',
style: { type: AndroidStyle.BIGTEXT, text: `${notificationBody}` },
progress: {
max: 10,
current: 5,
indeterminate: true,
},
actions: [
{
title: 'Answer',
pressAction: {
id: 'answer',
launchActivity: 'default',
launchActivityFlags: [AndroidLaunchActivityFlag.SINGLE_TOP],
},
},
If steps 7 - 10 are repeated the the behaviour is consistent - the issue here is that the first time a notification is received, the app is re-mounted in the background before pressing a The ideal scenario is that the app is never remounted or re-rendered when using a press action. Obviously because the root app component is remounting, functions and so on are being called that you only want to call on first launch, like authentication so I'm having to use flags dispatched to the store to determine how the app has been launched (I would normally do this but am having to do more-so to try and manage this). Another strange but (I think) linked observation is that when 'reloading' the app from dev tools, I get these stacking up in the console as I mentioned in a comment above:
I also get other logs that I would only expect to see one of - I'm finding it hard to predictably recreate this but it's like the app or some part of it is running more than once at a time if that's even possible. Some of this could be down to my own logic that needs to be improved upon but one thing that's for sure is that app launch behaviour from press actions is unpredictable for me. I think I need to move these in to foreground services anyway as I have whole load of async stuff going on in the background. This is all on physical pixel devices. |
Sounds racy, I wonder if you whittled it down to the minimum viable app and made sure it was all the listeners etc were registered in App.js if that would improve things (i.e., you'd win the race consistently)? Without a reproduction it's going to be tough to reason about this, which is just stating the obvious of course. I was doing most of my testing on an emulator, and I'll move to physical devices next. If I notice anything in my implementation i'll mention it but mine is still behaving as expected |
@whenmoon I've noticed in your snippet above in backgroundIncomingCallNotification you're setting the channel id to the notification id so this would be creating a new channel everytime if these ids are unique, you're also not passing notificationID as the id to the notification that you're creating there, whether this is relevant I'm not sure |
Could you also try combining single top flag with other flags like clear top, and see what happens |
@mikehardy yep ok I'm going to work on this and try to remove anything that could have some kind of effect on it like you mention. @Salakar Whilst doing the above testing I was always using the same notification id every time as I base them on the user sending it so they can be identified but thanks for the observation - I'll fix this, will also try other flag combos and report back. |
@mikehardy @Salakar I've done a bunch of testing, foreground services, background events, different combinations of launch activity flags, moving listeners in to index.js, App.js, stripping out everything to test functionality one thing at a time, but whatever way I cook it, what I find as consistent, predictable and undesirable behaviour is:
You should be able to test this just by logging inside a function that gets called early on in your application and observing when it gets called. Then I have this problem which is related to the app registry (this is the line of RN code that handles the info log): You can see how Notifee is causing multiple calls / renders (launches) in what is in fact a single launch - my knowledge of the app registry is not sufficient to be able to explain exactly what's happening in the background. The desirable launch action is to bring the app from the background to the foreground (killed app is a slightly different scenario but let's stick to background for now) whilst still being able to hook in to methods / features like |
I've tested out https://github.com/zo0r/react-native-push-notification to see how it behaves and it does not effect the app in the same way as Notifee when using a press action when the app is in the background. I then modified the library to add |
Ok FYI, this zo0r/react-native-push-notification#1482 solves this issue for me and also this issue. Any chance of similar implementation in Notifee? This would complete the package for me (although as far as I know you're not planning to implement Telecom API / Alarm manager)! |
Hi, |
Making my handler method async fixed it for me messaging().setBackgroundMessageHandler(async (remoteMessage) => { |
@shubhamverma27 seems like you found a solution? May I assume this is an integration with react-native-firebase? Or perhaps it is an issue with any cloud message library. The reason I ask is the documentation for integration with cloud messaging might need a change to emphasize this more strongly |
@mikehardy yes, making it async seems to solve the issue. |
FWIW I've also tested message handling whilst the app is in a background state on Android a number of times, and it never reloaded the app anew. |
Android:
When the users minimizes the app they immediately get a notification.
If they click on that notification the app won't open unless I set
launchActivity: "default"
but when that happens the app opens up in like new, losing all of my state and router history
This is how I fire the notification:
And this is how I handle it:
If you need to know, I am using React Navigation and the Navigation Service pretty much just takes you to a certain page with parameters.
To summarize:
The notification won't bring up the app unless I set
launchActivity
but doing so resets the app and loads it fresh.Suggestion, maybe there is a better way to open the app(?)
The text was updated successfully, but these errors were encountered: