Closed rcarvalho closed 4 years ago
same problem
same here on android.
Same +1
Please fix!
I got it working following this fix https://github.com/zo0r/react-native-push-notification/issues/333#issuecomment-316811908
I had to modify it a little bit to match the bundle I was receiving. In your MainActivity.java:
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName()) {
@Nullable
@Override
protected Bundle getLaunchOptions() {
Intent mainIntent = getIntent();
String dataValue = "";
Bundle initialProps = new Bundle();
if (mainIntent != null) {
Bundle bundle = mainIntent.getExtras();
if (bundle != null) {
JSONObject data = getPushData(bundle.getString("data"));
if (data != null) {
try {
dataValue = data.toString();
} catch (Exception e) {
// no-op
}
} else {
}
}
}
initialProps.putString("pushData", dataValue); // Read this inside your Root component in React native
return initialProps;
}
};
}
Modify your notification object and add a click_action key.
},....
notification: {
title: "Hello, World",
icon: "ic_launcher",
body: "This is a notification that will be displayed if your app is in the background.",
click_action: "OPEN_MAIN_ACTIVITY"
}
Add an intent-filter in your Manifest inside your activity, the action name must be the same as the one you specified in your notification object.
<intent-filter>
<action android:name="OPEN_MAIN_ACTIVITY" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
When you click your notification, it will open the activity where you added the intent-filter, read the notification data and send it through your initialProps
@omarcarreon thanks for the detailed solution. I will try it out. A question: how and where do you initialize your PushNotification object? I use Sagas, and initialize it every time the user logs in and/or opens the app has a valid session token. In other words, it is not initialized in the main/root component of my app. Should I change this?
Thanks!
No problem! I haven't used Sagas but I don't initialize PushNotification in the root component because I handle the notification after my Home component finished rendering. But if you need to handle your notification before, you can initialize it in your root component. It depends on what do you want to do with your notification
@omarcarreon Thanks! I will try it today!
@omarcarreon Can you show getPushData
method?
I've got
MainActivity.java:35: error: cannot find symbol
JSONObject data = getPushData(bundle.getString("data"));`
^
symbol: method getPushData(String)
1 error
:app:compileDebugJavaWithJavac FAILED
@omarcarreon +1 I am having the same issue. Could you please provide the getPushData method?
I've tried this. onNotification is not fired . Please help @omarcarreon
import com.facebook.react.ReactActivityDelegate;
import android.os.Bundle;
import org.json.JSONObject;
import org.json.JSONException;
import android.content.Intent;
import android.support.annotation.Nullable;
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName()) {
@Nullable
@Override
protected Bundle getLaunchOptions() {
Intent mainIntent = getIntent();
String dataValue = "";
Bundle initialProps = new Bundle();
if (mainIntent != null) {
Bundle bundle = mainIntent.getExtras();
if (bundle != null) {
try {
JSONObject data = new JSONObject(bundle.getString("data"));
if (data != null) {
try {
dataValue = data.toString();
} catch (Exception e) {
// no-op
}
}
}
catch (JSONException e) {
e.printStackTrace();
}
}
}
initialProps.putString("pushData", dataValue); // Read this inside your Root component in React native
return initialProps;
}
};
}
@MEDLJosh @kesha-antonov sorry, it's the same method used in the RNPushNotificationListenerService.java
private JSONObject getPushData(String dataString) {
try {
return new JSONObject(dataString);
} catch (Exception e) {
return null;
}
}
@kesha-antonov onNotification will not be fired. That function only works for me to handle foreground push notifications. And to handle background and when app's killed I use this fix to send the notification data to my initialProps. In my index.android.js I can access them with this.props
@omarcarreon I was able to get the code snippet to run and not crash when receiving a payload. I am having difficulty determining if I have actually received the payload in initialProps. Do you know how to print the values of initial props in my Main.js?
@MEDLJosh Yes, in your index.js you can use console.log(this.props)
or enable the Remote Debugger to see them in your console.
@omarcarreon Thank you for your help! I was able to get the pushData loaded into my initial props!
@omarcarreon Thank you! I was able to get push data!
I was able to receive notifications from my server that talks to GCM and get "onNotification" being invoked in my Android app in all states (app active, app in background, app inactive), without doing any changes in the Android-specific code -- fully relying only on the react-native-push-notification system.
My app is bootstrapped from the traditional Ignite template, and I followed some of the tips from this great post (and the author is very proactive in answering questions there!): https://shift.infinite.red/react-native-node-js-and-push-notifications-e851b279a0cd (adapted to the specific needs of my app). The key thing for me was to make sure that PushNotification.configure(...) was being called whenever the "App.js" file was executed --- this is important because of the details below :)
In order to make it work, I followed the instructions in the trouble shooting section "Silent remove push notifications" (see this https://github.com/zo0r/react-native-push-notification/blob/master/trouble-shooting.md#3-silent-remote-push-notifications) --- this part of the instructions states that:
If your Android app is not running when a silent notification is received then this library will start it. It will be started in the background however, and if the OS starts your app in this way it will not start the react-native lifecycle. This means that if your notification delivery code relies on the react-native lifecycle then it will not get invoked in this situation. You need to structure your app in such a way that PushNotification.configure gets called as a side effect of merely importing the root index.android.js file.
In my server side, I send the message to my server using the following JSON payload:
data = {
"to": theTokenOfTheUser
"data": {
"myAppMessage": jsonPayloadThatIWantToSend
}
}
then, the notification comes to my app with a field called "myappmessage",with my payload. Then, my app decides what to do (notifies the user with a local notification, dispatch redux store actions, etc).
As I said, when the App.js includes my Config file that has the call to configure(...), it means that configure(...) run as a side-effect of importing index.android.js.
The only issue I still have is that, when the app is inactive and gets invoked by the notification system, it runs a different lifecycle (apparently not the react lifecycle), and then the configure(...) call -- only in this particular case of the app not being active --- is called before the app is fully rendered, and this means that the Redux store and its middlewares are not necessarily ready, so if you want to call store.dispatch() it might not work well ... there are some discussions about this here: https://github.com/reactjs/redux/issues/1240 -- in my case, I'm doing a setTimeout hack as suggested, until there's a better solution to this :)
Thanks everyoe for the great discussion on this issue!
@fredbt I wish I could get mine to work the way yours is working. My build.gradle in my Android project's entry file is called index.android.js. The first bit of code that I have is my Push.configure. When I click on a notification on my device and my app is closed, I see my app start up. But, I never get an onNotification callback. Attached is my code. Was wondering if you see anything wrong with it. Thanks in advance.
import ReactNative, { AppRegistry } from 'react-native'
import PushNotification from 'react-native-push-notification'
import Config from './config'
import { registerDevice } from './src/app/user/actions/user'
import './src/services/sentry'
import Root from './src/root'
console.log("EXECUTING index.android.js")
PushNotification.configure({
onRegister: (device) => { console.log("REGISTER DEVICE", device); registerDevice(device.token, device.os) },
onNotification: (notification) => { console.log("RECEIVED PUSH NOTIFICATION", notification) },
senderID: Config.androidPushSenderId,
requestPermissions: false
})
AppRegistry.registerComponent('MainComponent', () => Root)
@rcarvalho
a few suggestions: I would move this code to its own file, let's say NotificationsConfig.js
console.log("EXECUTING index.android.js")
PushNotification.configure({
onRegister: (device) => { console.log("REGISTER DEVICE", device); registerDevice(device.token, device.os) },
onNotification: (notification) => { console.log("RECEIVED PUSH NOTIFICATION", notification) },
senderID: Config.androidPushSenderId,
requestPermissions: false
})
then include it from your ./src/root. I think it might a side-effect of running index.android.js but still should be inside the app itself (in this case, your root). Not sure about this, but my index.android.js has nothing, only the registerComponent call:
import './App/Config/ReactotronConfig'
import { AppRegistry } from 'react-native'
import App from './App/Containers/App'
AppRegistry.registerComponent('MyApp', () => App)
in the header of my App.js file (equivalent to your root file), I have:
` import '../NotificationsConfig'
`
Other than that: what's the format of the notification sent by your server to GCM (assuming that you're assuming GCM as bridge for notifications). Did you follow the instructions for silent notifications? Is silent notifications what you're trying to achieve?
Moreover, this piece of code:
onRegister: (device) => { console.log("REGISTER DEVICE", device); registerDevice(device.token, device.os) },
might not work because of what I explained about the middlewares. You might have to wrap it around a timeout call.
Hope this helps!
@fredbt Are you using silent notifications? Maybe that's why. I don't want it to be silent. I want an alert that is visible to the user so that they can click on it and come back into the app. This all works in iOS, but just not in Android. And by works, I mean the following occurs, which is what I expect:
1) When my app is running I receive a onNotification without a visible display in the OS 2) When my app is backgrounded, the user receives a visible OS notification, clicks on the notification, changes the app back to an active state, and my onNotification handler is called 3) When my app is closed, the user receives a visible OS notification, clicks on it, the app is launched and I receive a call to onNofication
I really want this same behavior for Android as I get in iOS and I'm just not seeing that it is working in the same way, if at all.
Sorry to beat this thread like a dead horse, but I just verified that all 3 states work on Android for silent notifications; starting from inactive, backgrounded or active. But, not for visible notifications.
Cool @rcarvalho ... yeah the name "silent notification" is not the best one, but apparently it's exactly what you were looking for.
I guess we can assume it's working for you now?
@fredbt No, I'm actually looking for visible alerts; not silent alerts. So, it still doesn't work for me. However, I found a way to do it in a kind of hacky way; by basically sending a silent notification and then receiving that and sending a local notification on the client. I was going to create a blog post about it and repost it for others.
Here's my blog post in case any of you are interested: https://product.farewell.io/visible-react-native-push-notifications-that-work-on-both-ios-and-android-5e90badb4a0f
@rcarvalho Your link is borked, can you fix?
@jamonholmgren Fixed
@rcarvalho FYI, I struggled with this issue for several days, before discovering that it was due to a quirk with our splash screen setup, which is detailed in https://github.com/zo0r/react-native-push-notification/issues/122
Thank you so much for that post @rcarvalho, the only problem I have is that I am not sure how to find out whether the user opened the app by clicking the notification or not. Did you maybe find any solution to this?
Thanks, @robinheinze. I'll check it out.
@CptFabulouso, you shouldn't get an onNotification call when you just open the app. The only time it gets called is if the user clicks on the notification.
@rcarvalho According to debugger, If Iam in app and receive notification, it gets called twice, when it is received and when it is clicked. If Iam out of the app (or is killed) it gets called when it is received, but not when clicked.
@CptFabuloso are you talking about Android? And, are you making sure to send a data only message from the server side? If you just do that one thing, a pure server data only push without the additional local push I explained in my blog post, you should see that you get one notification in all states when the notification is received. It is the additional local notification that will enable a callback notification when the visible banner is clicked.
@rcarvalho yes, android. I followed your blog post and have set everything as you do, also on the server side. I can see how the localNotification is called when the silentNotification incomes, but I have no idea why the callback is not invoked when the banner is clicked. If I close the app with debugger on and console log everything, this is what gets logged. Also My RootScreen is your AppContainer.
const Root = () => {
return (
<Provider store={store}>
<RootScreen />
</Provider>
)
}
PushService INIT
PushService.js:60 PushService CONFIGURE
PushService.js:68 PushService CONFIGURE onNotification {foreground: false, subject: "Some subject", google.sent_time: 1505142177612, userInteraction: false, id: "-2143814905", …}
PushService.js:10 PushService.onNotification (inside INIT) {foreground: false, subject: "Some subject", google.sent_time: 1505142177612, userInteraction: false, id: "-2143814905", …}
-Here I click on the notification-
infoLog.js:17 Running application "..." with appParams: {"rootTag":1}. __DEV__ === true, development-level warning are ON, performance optimizations are OFF
RootScreen.js:303 render Root Screen
RootScreen.js:118 Root Screen Did Mount
PushService.js:54 PushService SET CALLBACKS
RootScreen.js:303 render Root Screen
It may be relevant, that if I reload the app at this point, I receive the original notification and also it's callback in my handleOnPushNotification (userInteraction is true in second case).
PushService INIT
PushService.js:60 PushService CONFIGURE
infoLog.js:17 Running application "..." with appParams: {"rootTag":1}. __DEV__ === true, development-level warning are ON, performance optimizations are OFF
RootScreen.js:303 render Root Screen
RootScreen.js:118 Root Screen Did Mount
PushService.js:54 PushService SET CALLBACKS
PushService.js:68 PushService CONFIGURE onNotification {foreground: true, subject: "Some subject", google.sent_time: 1505142327607, userInteraction: false, id: "-269905516", …}
RootScreen.js:83 Handle on push notification {foreground: true, subject: "Some subject", google.sent_time: 1505142327607, userInteraction: false, id: "-269905516", …}
PushService.js:68 PushService CONFIGURE onNotification {foreground: false, subject: "Some subject", google.sent_time: 1505142327607, smallIcon: "ic_notification", userInteraction: true, …}
RootScreen.js:83 Handle on push notification {foreground: false, subject: "Some subject", google.sent_time: 1505142327607, smallIcon: "ic_notification", userInteraction: true, …}
RootScreen.js:72 Handle on push register
RootScreen.js:303 render Root Screen
When you get the notification callback, does it come from the init function, or where you handle notifications in AppContainer?
Also my handleOnPushNotification
handleOnPushNotification(notification){
console.log("Handle on push notification", notification)
PushNotification.localNotification({
title: notification.subject,
message: notification.body,
smallIcon: notification.icon ? notification.icon : "ic_notification",
color: Colors.primaryColor,
vibrate: true,
vibration: 300,
...notification
})
}
Does something seem fishy to you? Also thank you very much for your time looking into this
@CptFabulouso the only time that the app should receive the onNotification call within init is when the application is turned off. If the app is just backgrounded setCallback has been called and you should receive the notification in AppContainer.
I'm just using local notifications and really want to be able to pass some data when the notification is clicked. I followed @omarcarreon suggestion, calling the schedule function as follows.
PushNotification.localNotificationSchedule({ message "hello" playSound false date t notification {title "test title" } data { ... } click_action "OPEN_MAIN_ACTIVITY" userInfo {tag "tag"}} })
In the MainActivity.java I'm trying various things to get any data out of the extras but it's not there. Any idea what could be wrong here?
Also, it's a bit of a pain to have to get the app into a state where it's backgrounded before I can test... is there any way of forcing an app into the background?
Help appreciated!
I followed every instruction I could find and finally got it working, onNotification was being called upon receiving a remote notification and also after opening it from background and killed app states. However, the next morning it stopped working. No code has been changed. Same device, same apk, on opening the notification onNotification is not being called when it was received in app background state.
@jurgenphotek @CptFabulouso I am having the issue too. Were you able to resolve this?
Unfortunatelly no. I switched to this library intstead
Does the fact that you receive the notification on an Android device means that this library can catch it and interpret its data?
As at 2019-06 for version 3.1.3
it's found that at least a channel entry in the Android App's AndroidManifest.xml is required for proper functioning of onNotification especially for non-foreground and killed-app situations and your notification type is purely Data message:
<application ...>
...
<meta-data android:name="com.dieam.reactnativepushnotification.notification_channel_name"
android:value="default_channel"/>
<meta-data
android:name="com.dieam.reactnativepushnotification.notification_channel_description"
android:value="this is the default channel"/>
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 30 days if no further activity occurs. Thank you for your contributions.
I had same issue and solved by another simple solution.
By modifying handler of back button in MainActivity.java, I made the back button also act like center button which makes the app go home(background).
Here is the code and link where I got idea!
@Override
public void invokeDefaultOnBackPressed() {
moveTaskToBack(true);
}
iOS works for me. But, for some reason I'm not receiving the onNotification on Android at all. My code is basically the same as the sample code for Android integration. There are two scenarios I would like to outline and each have their different challenges:
1) Clicking on a push notification when app is backgrounded I never receive the onNotification call. My app comes up and I see the splash image, but my app just seems to hang there. This is strange because if I click on my backgrounded app, my app comes up fine in the last state that I left it.
2) Clicking on a push notification an app when the app is closed This launches the app fine, but I never get the onNotification call