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

addNotificationResponseReceivedListener or useLastNotificationResponse is not firing when app is killed #11933

Closed
Terspychore opened this issue Feb 12, 2021 · 21 comments
Labels
Notifications pending closure awaiting final response before closing

Comments

@Terspychore
Copy link

Terspychore commented Feb 12, 2021

Summary

Both useLastNotificationResponse hook and addNotificationResponseReceivedListener isn't firing when my expo app is killed. Working only in background and foreground. My expo-notifications package is up-to-date : "^0.9.0".

Managed or bare workflow? If you have ios/ or android/ directories in your project, the answer is bare!

managed

What platform(s) does this occur on?

Android, iOS

SDK Version (managed workflow only)

40.0.1

Environment

Expo CLI 4.1.6 environment info:
System:
OS: macOS 10.15.5
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 14.8.0 - ~/.nvm/versions/node/v14.8.0/bin/node
npm: 6.14.7 - ~/.nvm/versions/node/v14.8.0/bin/npm
SDKs:
iOS SDK:
Platforms: iOS 14.4, DriverKit 20.2, macOS 11.1, tvOS 14.3, watchOS 7.2
IDEs:
Android Studio: 4.1 AI-201.8743.12.41.7042882
Xcode: 12.4/12D4e - /usr/bin/xcodebuild
npmPackages:
expo: ^40.0.1 => 40.0.1
react: 16.13.1 => 16.13.1
react-dom: 16.13.1 => 16.13.1
react-native: https://github.com/expo/react-native/archive/sdk-40.0.1.tar.gz => 0.63.2
react-native-web: ~0.13.12 => 0.13.18
npmGlobalPackages:
expo-cli: 4.1.6
Expo Workflow: managed

Reproducible demo or steps to reproduce from a blank project

Notifications.setNotificationHandler({
	handleNotification: async () => ({
		shouldShowAlert: true,
		shouldPlaySound: false,
		shouldSetBadge: false,
	}),
});

Notifications.addNotificationResponseReceivedListener((response) => {
  console.log("received response!", response);
});

const handlePush = async ({ notification }) => {
	console.log("navigate");
}


export default function App() {


	const lastNotificationResponse = Notifications.useLastNotificationResponse();

	React.useEffect(() => {
		console.log(lastNotificationResponse);
					if (lastNotificationResponse && lastNotificationResponse.actionIdentifier === Notifications.DEFAULT_ACTION_IDENTIFIER) {
					handlePush(lastNotificationResponse);
			}
	}, [lastNotificationResponse]);
@Terspychore Terspychore added the needs validation Issue needs to be validated label Feb 12, 2021
@artsnr1
Copy link

artsnr1 commented Feb 19, 2021

Same here (using v 0.9.0). It is triggering when both expo and app (inside expo) are killed (removed from recent apps) but it isn't triggering when only app is killed. And also not working in production. Terspychore did you find a workaround.

@ruiqbarbosa
Copy link

I am facing the exactly same problem. When the application is killed the addNotificationResponseReceivedListener event is never triggered.

@jparksecurity
Copy link

jparksecurity commented Feb 23, 2021

I have the same issue here.

I was able to fix this on Android by puting Notifications.addNotificationResponseReceivedListener inside of useLayoutEffect

I haven't tested it on a blank project, so IDK if it works only for my case.

If anyone knows a workaround for iOS, please share it with us.

P.S.
it seems duplicated #11343 . I guess we have to wait to update expo. Ref: #11343 (comment)

@endronk
Copy link

endronk commented Feb 25, 2021

Same here, using:

  • Android
  • SDK 40
  • expo-notifications 0.8.2 and 0.9.0

It also doesn't work on my project when using Notifications.addNotificationResponseReceivedListener inside of useLayoutEffect.

@endronk
Copy link

endronk commented Feb 25, 2021

I'm afraid that there won't be any solution for this on Android...

The Android framework advises that apps that have been stopped (not in background) should not be started without explicit user interaction. FCM follows this recommendation and thus does not deliver messages to stopped apps. What I believe is happening on the devices in question is that apps that are swiped from the recents list are being stopped and thus not receiving messages from FCM.

firebase/quickstart-android#41 (comment)

When an app is in a Force Stopped / Force Killed state most events including FCM messages for push notifications will not be received.

https://documentation.onesignal.com/docs/notifications-show-successful-but-are-not-being-shown#the-app-is-force-stopped

I tried killing my WhatsApp and yeah, I didn't receive any notification when someone sent me a message.

@Terspychore
Copy link
Author

Terspychore commented Feb 28, 2021

Same here (using v 0.9.0). It is triggering when both expo and app (inside expo) are killed (removed from recent apps) but it isn't triggering when only app is killed. And also not working in production. Terspychore did you find a workaround.

No workaround still. Working only when app is in background and foreground. Please Expo enlighten us ! 🙂

@cruzach
Copy link
Contributor

cruzach commented Mar 3, 2021

@jparksecurity is correct- fixes for this have landed and are published for the bare workflow in expo-notifications@0.10.0, but if you are on the managed workflow you will need to wait until SDK 41 is released (we'll be opening up the SDK 41 beta within the next few weeks, so you don't have very long to wait)

@cruzach cruzach added pending closure awaiting final response before closing and removed needs validation Issue needs to be validated labels Mar 3, 2021
@cruzach cruzach closed this as completed Mar 3, 2021
@islamouzou
Copy link
Contributor

@jparksecurity is correct- fixes for this have landed and are published for the bare workflow in expo-notifications@0.10.0, but if you are on the managed workflow you will need to wait until SDK 41 is released (we'll be opening up the SDK 41 beta within the next few weeks, so you don't have very long to wait)

Will this include the fix for startLocationUpdatesAsync() ???

@cruzach
Copy link
Contributor

cruzach commented Mar 4, 2021

yes, you can view that issue and relevant PR for more details #11536

@islamouzou
Copy link
Contributor

The issue is still there SDK 42 (managed ), using the addNotificationResponseReceivedListener or the new hook even if it's the first line in App.js , same results , However sometimes it works .

@bondansebastian
Copy link

I still experienced this issue on SDK 44 (managed)

@dfabreguette
Copy link

I also have same issue, using SDK 42 in bare workflow, and associated expo-notifications v0.12.3. Using addNotificationResponseReceivedListener, useLastNotificationResponse hook (or getLastNotificationResponseAsync equivalent) gives always the same response : null.
This is always returning null, not just when the app is killed.
For some reasons, I've struggled upgrading SDK to 43 (due to unimodules migration).
Will the 43 SDK ugprade solve the problem ?

@entiendoNull
Copy link
Contributor

On SDK43 I was unsuccessful to capture the event with addNotificationResponseReceivedListener on Android when the app was killed. I tried to register the listener in a useLayoutEffect instead of an useEffect but that changed nothing.

Desperately I tried the useLastNotificationResponse out instead of manually register eventListeners and I was able to receive and handle notifications on Android when the app was in a "killed" state.

My original approach was to register addNotificationReceivedListener and addNotificationResponseReceivedListener for both iOS and Android.

  • On iOS I was able to capture and handle events on all app states (foreground, background and killed).
  • On Android I was able to capture and handle events in the foreground, background.

My final approach:

  • addNotificationReceivedListener and addNotificationResponseReceivedListener was used to capture and handle events on iOS as that seemed to work perfectly.
  • addNotificationReceivedListener and useLastNotificationResponse was used to capture and handle events on Android.

It certainly seems like the addNotificationResponseReceivedListener problem is still not resolved.

@appsgenie
Copy link

On SDK43 I was unsuccessful to capture the event with addNotificationResponseReceivedListener on Android when the app was killed. I tried to register the listener in a useLayoutEffect instead of an useEffect but that changed nothing.

Desperately I tried the useLastNotificationResponse out instead of manually register eventListeners and I was able to receive and handle notifications on Android when the app was in a "killed" state.

My original approach was to register addNotificationReceivedListener and addNotificationResponseReceivedListener for both iOS and Android.

  • On iOS I was able to capture and handle events on all app states (foreground, background and killed).
  • On Android I was able to capture and handle events in the foreground, background.

My final approach:

  • addNotificationReceivedListener and addNotificationResponseReceivedListener was used to capture and handle events on iOS as that seemed to work perfectly.
  • addNotificationReceivedListener and useLastNotificationResponse was used to capture and handle events on Android.

It certainly seems like the addNotificationResponseReceivedListener problem is still not resolved.

How did you use useLastNotificationResponse? Was it in same place as addNotificationReceivedListener for Android? And do you know how to get that working with class components?

@chen-rn
Copy link

chen-rn commented Mar 12, 2023

I still experienced this issue on SDK 44 (managed)

Were you able to fix this? Can someone confirm if this is fixed March 2023?

@berataras
Copy link

September 2023 and still not working... When will it be resolved?

@Louay17
Copy link

Louay17 commented Sep 8, 2023

I still experienced this issue on SDK 44 (managed)

Were you able to fix this? Can someone confirm if this is fixed March 2023?

I confirm its working!
@berataras @chen-rn make sure you are calling addNotificationResponseRecievedListener early in your app’s startup as @cruzach mentioned here expo-forum

@dmrugalski
Copy link

For me solution above didn't want to work, but I solve that problem in other way.

Thats my response from different thread.

still an issue on Android even with initializing addNotificationResponseReceivedListener before any other react code

I believe it's not the case. I struggled with that for a long time but looks like I found a solution that work in my case. To solve my problem I use getLastNotificationResponseAsync() not in main file (App.tsx) but in one of its child so after loading few libs and initialization some of the code. To be clear,

I use it in getInitialURL() function (of course only for android, iOS works OK for me.

const linking = {
  prefixes: [...],
  async getInitialURL() {
    if (Platform.OS === 'android') {
      const lastNotificationResponse = Notifications.getLastNotificationResponseAsync();
      lastNotificationResponse.then(response => {
        if (!!response) {
          storeNotificationFromStartup(response.notification);
        }
      })
    }
  }
}
<NavigationContainer ref={navigationRef}
                     linking={linking}>
  [...]
</NavigationContainer>

in storeNotificationFromStartup I save it into AsyncStorage and read that after API calls and initialization my app with data from backend.

@AnhTP-Corize
Copy link

@dmrugalski seems it's not working for me. When I kill app and then tap into noti, lastNotificationReponse returns null

@berataras
Copy link

this is my last way and it's worked for me.

"expo": "^49.0.0",
"expo-notifications": "~0.20.1",

src/app/_layout.tsx:

function StackScreens() {
    import { useLastNotificationResponse } from 'expo-notifications';
    const lastNotificationResponse = useLastNotificationResponse();
  
    useEffect(() => {
      if (lastNotificationResponse) {
        let data = lastNotificationResponse?.notification?.request?.content?.data;
  
        if (data) {
          //code
        }
      }
    }, [lastNotificationResponse]);
    
    return (
        <Stack
          initialRouteName="(tabs)"
        >
       ...
    )
}

@hemasai03
Copy link

hemasai03 commented Aug 8, 2024

Project - Expo Managed React native
My Expo version is "expo": "~51.0.14", "react-native": "0.74.2",

I used expo notifications@~0.28.9 for push notifications

addNotificationResponseReceivedListener is working fine when app is in foreground ,once app is killed or removed from background , it is not working properly .

import { useState, useEffect, useRef } from 'react'
import * as Device from 'expo-device'
import * as Notifications from 'expo-notifications'

import Constants from 'expo-constants'

export interface PushNotificationState {
expoPushToken?: Notifications.ExpoPushToken
notification?: Notifications.Notification
}

export const usePushNotifications = (): PushNotificationState => {
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldPlaySound: true,
shouldShowAlert: true,
shouldSetBadge: false
})
})
const intializestore = useInitializeStore()
const homestore = useHomeStore()
const navigation = useNavigation<NativeStackNavigationProp>()
const [expoPushToken, setExpoPushToken] = useState<
Notifications.ExpoPushToken | undefined

()

const [notification, setNotification] = useState<
Notifications.Notification | undefined

()

const notificationListener = useRef<Notifications.Subscription>()
const responseListener = useRef<Notifications.Subscription>()

const handleNotificationResponse = (response) => {
const { screen,params } = response.notification.request.content.data

console.log(screen,params);

navigation.navigate(screen,params);
// navigation.navigate('CommunicateWithAdmin')

}

async function registerForPushNotificationsAsync() {
let token
if (Device.isDevice) {
const { status: existingStatus } =
await Notifications.getPermissionsAsync()
let finalStatus = existingStatus

  if (existingStatus !== 'granted') {
    const { status } = await Notifications.requestPermissionsAsync()
    finalStatus = status
  }
  if (finalStatus !== 'granted') {
    console.log('Failed to get push token for push notification')
    return
  }

  token = await Notifications.getExpoPushTokenAsync({
    projectId: Constants.expoConfig?.extra?.eas.projectId
  })
} else {
  console.log('Must be using a physical device for Push notifications')
}

if (Platform.OS === 'android') {
  Notifications.setNotificationChannelAsync('default', {
    name: 'default',
    importance: Notifications.AndroidImportance.MAX,
    vibrationPattern: [0, 250, 250, 250],
    lightColor: '#FF231F7C'
  })
}

console.log(token.data)

const data1 = {
  essObKey: intializestore?.initializeData?.mostRecentUserOnBoardings,
  essUserKey: intializestore?.initializeData?.userkey,
  token: token.data,
  deviceInfo: Device.osName,
  platform: Platform.OS,
  deviceversion: Device.osVersion,
  device: Device.brand
}
console.log('api calling happen')
await homestore.postfirebasetoken(data1)

return token

}

useEffect(() => {
registerForPushNotificationsAsync().then((token) => {
setExpoPushToken(token)
})
//foregorund
notificationListener.current =
Notifications.addNotificationReceivedListener((notification) => {
setNotification(notification)
})
//background
responseListener.current =
Notifications.addNotificationResponseReceivedListener((response) => {
handleNotificationResponse(response)
})

return () => {
  Notifications.removeNotificationSubscription(
    notificationListener.current!
  )

  Notifications.removeNotificationSubscription(responseListener.current!)
}

}, [])

return {
expoPushToken,
notification
}
}
this is my code.
can anyone please tell me the solution?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Notifications pending closure awaiting final response before closing
Projects
None yet
Development

No branches or pull requests