I developing an Ionic 2 app and testing on Android emulator.
When the app is in background and the notification has no title, no message and content-available=1 the notification should be sent directly to app notification handler. But its not happening.
I can receive notifications with the app in foreground.
If I have a title and a message I receive the notification in the notification area. But I need to send the notification directly to the app in silent mode, without pass by the notification area.
Here is my code to send push notifications:
{
"delay_while_idle": true,
"priority": "high",
"sound": "default",
"color": "FFFF00",
//payload
"data": {
"content-available": "1",
"some_var": "some_value",
"ohter_var": "other_value",
}
}
How could I sent silent notifications to my Android app?
Android GCM and FCM both also work when app background.
For that you need to add below service classes at manifest with intent Filter.
<!-- [START gcm_listener] -->
<service
android:name=".gcm.GcmListener"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service
android:name=".gcm.TokenRefreshService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
<service
android:name=".gcm.RegistrationIntentService"
android:exported="false" />
<!-- [END gcm_listener] -->
public class GcmListener extends GcmListenerService {
}
public class TokenRefreshService extends InstanceIDListenerService {
#Override
public void onTokenRefresh() {
super.onTokenRefresh();
Intent intent = new Intent(this, RegistrationIntentService.class);
startService(intent);
}
}
To get token:
public class RegistrationIntentService extends IntentService {
// TODO: Rename actions, choose action names that describe tasks that this
private String TAG = "RegistrationIntentService";
public RegistrationIntentService() {
super("RegistrationIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
InstanceID instanceID = InstanceID.getInstance(this);
String token = instanceID.getToken("PRODUCT_ID",
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
}
}
Related
I've managed to get this working in the past, but its suddenly stopped working and I don't know what to check in order to get it working again. I am trying to get push notifications working using Firebase Cloud Messaging through Localytics. I am testing using the Localytics Rapid Push Notification Test module. The device pairs ok but when I send the notification nothing happens on the device.
1) I've regenerated my google-services.json file and pasted into the root of my folder.
2) I'm pretty sure my Android Manifest is fine:
<meta-data android:name="LOCALYTICS_APP_KEY" android:value="{HIDDEN FROM STACK OVERFLOW}" />
<activity android:name="com.localytics.android.PushTrackingActivity" android:exported="true" />
<receiver android:name="com.localytics.android.ReferralReceiver" android:exported="true">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="{HIDDEN FROM STACK OVERFLOW}" />
</intent-filter>
</receiver>
3) My implementation of FirebaseInstanceIdService gets called ok as I can debug it:
[Service]
[IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
public class MyFirebaseIIDService : FirebaseInstanceIdService
{
const string TAG = "MyFirebaseIIDService";
public override void OnTokenRefresh()
{
var refreshedToken = FirebaseInstanceId.Instance.Token;
Log.Debug(TAG, "Refreshed token: " + refreshedToken);
Localytics.PushRegistrationId = refreshedToken;
SendRegistrationToServer(refreshedToken);
}
void SendRegistrationToServer(string token)
{
// Add custom implementation, as needed.
}
}
4) My implementation of FirebaseMessagingService never ever gets called!
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class MyFirebaseMessagingService : FirebaseMessagingService
{
const string _tag = "MyFirebase";
public override void OnMessageReceived(RemoteMessage message)
{
Log.Debug(_tag, "Remote Message Received");
}
}
5) In my MainActivity I am calling Localytics.RegisterPush(); within the OnCreate() override.
Can someone please help? Thanks in advance!
In my Android app I need to handle receiving of Firebase push notification messages, so that I can manipulate their ids (so that all notifications display rather than replacing each other) and so that I can display an app icon (setting it with a meta-data element in Android manifest doesn't work.)
I've creating a messaging service to handle receiving messages:
[Service (Name = "com.rpr.mobile.droid.LocalyticsFirebaseMessagingService")]
[IntentFilter (new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class LocalyticsFirebaseMessagingService : FirebaseMessagingService {
private static int notificationId = 0;
public override void OnMessageReceived (RemoteMessage message) {
if (!message.Data.ContainsKey ("ll")) {
base.OnMessageReceived (message);
} else {
var body = message.GetNotification ().Body;
if (!String.IsNullOrEmpty (body)) {
var mainIntent = new Intent (this, typeof (IntentActivity));
var deepLinkUrl = "";
if (message.Data.TryGetValue ("ll_deep_link_url", out deepLinkUrl))
mainIntent.SetData (Android.Net.Uri.Parse (deepLinkUrl));
var launchIntent = PendingIntent.GetActivity (this, 1, mainIntent, PendingIntentFlags.UpdateCurrent);
var builder = new NotificationCompat.Builder (this)
.SetSmallIcon (Resource.Drawable.logo_blue_small)
.SetContentTitle (GetString (Resource.String.application_name))
.SetContentText (body)
.SetStyle (new NotificationCompat.BigTextStyle ().BigText (body))
.SetContentIntent (launchIntent)
.SetDefaults (-1)
.SetAutoCancel (true);
var notificationManager = NotificationManagerCompat.From (this);
notificationManager.Notify (notificationId++, builder.Build ());
}
}
}
}
And I've defined it in the application section of my Android manifest:
<service android:name="com.rpr.mobile.droid.LocalyticsFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
However, when I receive a push notification this code is never called, even when the app is in the foreground. I had similar code that worked fine for GCM push notifications, but I'm having no luck for Firebase. What am I missing?
You have to add the below code to your android manifest file inside application section:
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
and in your class you have to add like this
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class MessagingService : FirebaseMessagingService
and this is the code to get the token
[Service]
[IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
public class IDService : FirebaseInstanceIdService
also you have to add the google-services.json file to your project with the build action GoogleServicesJson
I have a problem with FCM functionality. When the phone is awake everything is working (notifications are received when the app is in foreground, background or even if the app is dead).
The problem starts when the phone is entering deep sleep.
As I remember wakelocks are not mandatory with FCM.
I'm pushing "data" type notification with "priority":"high" which should wake up the device.
Problem is that notifications will be received when the phone will awake.
public class FCMCallbackService extends FirebaseMessagingService {
private static final String TAG = "FCMCallbackService";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Intent i = new Intent(this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
}
public class FCMInitializationService extends FirebaseInstanceIdService {
#Override
public void onTokenRefresh() {
...
}
}
In manifest:
<service android:name="gcmpush.FCMInitializationService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service android:name="gcmpush.FCMCallbackService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
How can I wake application using push if the phone is sleeping? What is missing?
BDW - if I'm connected to WiFi and phone will go to sleep, but the application is not working - will it use WiFi to receive push? FCM can start the dead application. But if the app is dead, WiFi lock is not acquired. Can in such case device communicate with FCM Server?
The following message will not call your onMessageReceived() when your app is in the background or killed, and you can't customize your notification.
{
"to": "/topics/journal",
"notification": {
"title" : "title",
"text": "data!",
"icon": "ic_notification"
}
}
but instead using this will work
{
"to": "/topics/dev_journal",
"data": {
"text":"text",
"title":"",
"line1":"Journal",
"line2":"some data"
}
}
See ref link here
I am using FCM for notification and it is working good in all scenarios in Foreground and background. My problem is when I am logout from my application and another user send me message, I am not getting any notification as I am logout which is fine, but when I again login in my application I want to receive that old unread notification so how to do this any help would be appreciated following is the code I used
public class FirebaseIDService extends FirebaseInstanceIdService {
private static final String TAG = "FirebaseIDService";
Context ctx = this;
#Override
public void onTokenRefresh() {
// Get updated InstanceID token.
try {
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "FCM Service";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
Log.e("remote", remoteMessage.getData().get("type") + "");
Log.e("remoteMessage", remoteMessage.getData() + "");
Log.e("remoteMessagebody", remoteMessage.getData().get("body") + "");
// handling other data also according to my app which i am not mentioning
}
}
I have used this code for fetching old notification but didnot worked
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
and in manifest
<service
android:name=".MyFirebaseMessagingService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name=".FirebaseIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
and in gradle
compile 'com.google.firebase:firebase-messaging:9.2.1'
An FCM message has its own lifetime -- 4 weeks default, could be modified by setting time_to_live in your payload. After that time, the message would be discarded.
What you could do is implement that each notif is saved in a your Server DB, if it is not read yet and you detect that the user re-logs in, re-send them as push notifications, or simply retrieve them in your app and display them as notifications.
I am trying to setup push notifications to my app containing both data and notification payloads as described in the official reference. I want both payloads so that I will get an automatic notification when my app is in the background, and the app can handle things itself while in the foreground.
The onMessageReceived() method in my GcmListenerService is not called when both payloads are included and the app is in the foreground. I have to leave out the notification payload for it to work.
When the app is in the background, it works fine. I get a notification and can open the app when the notification is clicked and do whatever I want from there.
I have looked at this question, but they were trying to get a notification when the app is in foreground. I realize I won't get a notification in that case, I just want to get the data.
Relevant portion of AndroidManifest.xml:
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="arkenterprises.garage_o_matic.gcm" />
</intent-filter>
</receiver>
<service
android:name=".MyGcmListenerService"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
MyGcmListenerService.java:
public class MyGcmListenerService extends GcmListenerService {
private static final String TAG = "MyGcmListenerService";
#Override
public void onMessageReceived(String from, Bundle data) {
Log.d(TAG, "Data: " + data);
String message = data.getString("message");
String doorStatus = data.getString("DoorStatus");
String time = data.getString("time");
Bundle notification = data.getBundle("notification");
Log.d(TAG, "From: " + from);
Log.d(TAG, "Message: " + message);
Log.d(TAG, "DoorStatus: " + doorStatus);
Log.d(TAG, "Time: " + time);
Log.d(TAG, "Notification: " + notification);
}
Server code that sends the message:
nowString = datetime.datetime.now().strftime("%c")
gcmSendURL = 'https://gcm-http.googleapis.com/gcm/send'
gcmHeaders = {'Authorization': 'key=' + API_KEY, 'Content-Type': 'application/json'}
gcmDataPayload = {'message': 'Garage door opened', 'DoorStatus': 'Open', 'time': nowString}
gcmNotificationPayload = {'title': 'Garage Door Has Opened', 'body': 'Garage door opened at {}'.format(nowString), 'icon': 'ic_door_open_notification2'}
print('Garage door opened at {}'.format(nowString))
gcmPayload = {'to': regIDs[0].strip(), 'priority': 'high', 'delay_while_idle': False, 'time_to_live': 86400, 'data': gcmDataPayload}
# gcmPayload = {'to': regIDs[0].strip(), 'priority': 'high', 'delay_while_idle': False, 'time_to_live': 86400, 'notification': gcmNotificationPayload}
# gcmPayload = {'to': regIDs[0].strip(), 'priority': 'high', 'delay_while_idle': False, 'time_to_live': 86400, 'content_available': True, 'data': gcmDataPayload, 'notification': gcmNotificationPayload}
print("\nPayload: {}".format(gcmPayload))
r = requests.post(gcmSendURL, headers=gcmHeaders, json=gcmPayload)
print("\nRequest response: " + r.text)
Yes, you can send messages that have both notification and data payloads.
I found this Stack overflow ticket related to your inquiry, It says that Intent filters will always fire your manifested application as per standard android behavior. Make sure that your logic flow is able to handle the fact that your launch may come from places. Try to implement 'GcmMessageHandler' your application must check saved state and sees if user needs to see screen and automatically show notifications.
I had some strange behaviour with samples, but in final I resolved that by removing implementation of GcmListenerService and adding implementation of GcmReceiver.
public class MyGcmReceiver extends GcmReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
}
};
and manifest
<receiver
android:name=".MyGcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</receiver>