I am trying to send a background push notification through Parse.com that pings my server:
-(void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
[PFPush handlePush:userInfo];
if (application.applicationState == UIApplicationStateInactive) {
[PFAnalytics trackAppOpenedWithRemoteNotificationPayload:userInfo];
}
NSString *CustomData = [userInfo objectForKey:#"CustomField"];
// ping server to confirm the push notification is delivered, sometimes this is called but not always
[[DAL sharedInstance] log:CustomData onComplete:nil];
// do stuff
if([CustomData isEqualToString:#"CustomItem"])
{
// do stuff
}
When I send a push notification through Parse.com's REST API to https://api.parse.com/1/push with
{ "where":{"objectId":"[objectID]"}, "data":{"alert":"test","content-available":"1","CustomField":"CustomItem"} }
I get the alert and the server is pinged, but if I remove the alert
{ "where":{"objectId":"[objectID]"}, "data":{"content-available":"1","CustomField":"CustomItem"} }
nothing happens and the server is not pinged. How can I send the push notification invisibly and still ping the server?
Related
I am having absolutely no luck getting push notifications to work in iOS in a Xamarin Forms project.
In AppDelegate.cs, I am calling the following in the FinishedLaunching override:
MSNotificationHub.Start("Endpoint=sb://[redacted].servicebus.windows.net/;SharedAccessKeyName=DefaultListenSharedAccessSignature;SharedAccessKey=[redacted]",
"[redacted]");
After the user logs in further in the app lifecycle, I also register the user with their user tag as follows:
public async Task UpdateTags(string token)
{
await Task.Run(() =>
{
try
{
// No point registering tags until the user has signed in and we have a device token
if (CurrentAccount == null)
{
Console.WriteLine($"UpdateTags cancelled: Account is null");
return;
}
var tag = $"user:{CurrentAccount.UserName}";
Console.WriteLine($"Registering tag: {tag}");
MSNotificationHub.AddTag(tag);
}
catch (Exception e)
{
Console.WriteLine($"Error registering tag: {e.ToString()}");
}
});
}
I have properly configured the Apple (APNS) settings in the notification hub, using the Token authentication mode (verified the four fields several times). The certificate (signing identity) is "iOS Distribution", the identifier bundle matches exactly what I have in the configuration (not using wildcard), the key has Apple Push Notifications service (APNs) enabled, and the provisioning profile has Platform: iOS and Type: App Store.
I pushed the application to TestFlight, as I don't have access to a physical Mac (we use a Cloud mac for development). When I view the device logs from my personal iPhone with the app installed, I see the following when I run it:
<Notice>: Registered for push notifications with token: [redacted]
<Notice>: Registering tag: user:[redacted]
There are no instances of "Error registering tag" or "UpdateTags cancelled" in the logs at all, which tells me that the method calls are succeeding without an exception. However, when I attempt to send a test notification to either a blank/empty tag, or the specific tag for my test user, no notifications are received and the messaging simply shows "Message was successfully sent, but there were no matching targets."
Also, when I pull all of the registrations with var registrations = await hub.GetAllRegistrationsAsync(0);, I only see the FCM (Firebase/Android) registrations from my successful testing on the Android side of things.
I am at a complete loss and have hit a wall, as there are no exceptions being thrown, and seemingly no way to troubleshoot what is going on behind the scenes.
This is also my 2nd attempt - I was using a more complex SBNotificationHub implementation and had the same results - no exceptions and everything looked fine at face value.
Thanks to a comment pointing to another question, I have determined that all I needed to do was to ensure that my tag registration ran on the main UI thread. My updated code below is working:
public async Task UpdateTags(string token)
{
await Task.Run(() =>
{
Device.BeginInvokeOnMainThread(() =>
{
try
{
// No point registering tags until the user has signed in and we have a device token
if (CurrentAccount == null)
{
Console.WriteLine($"UpdateTags cancelled: Account: {Trico.OrbitalApp.App.CurrentAccount};");
return;
}
var tag = $"user:{CurrentAccount.UserName}";
Console.WriteLine($"Registering tag: {tag}");
MSNotificationHub.AddTag(tag);
}
catch (Exception e)
{
Console.WriteLine($"Error registering device: {e.ToString()}");
}
});
});
}
You can try implementing the MSInstallationLifecycleDelegate interface which will allow you to check and see if the installation is being saved on the back end with either success or failure.
// Set a listener for lifecycle management
MSNotificationHub.SetLifecycleDelegate(new InstallationLifecycleDelegate());
// Implementation of the lifecycle listener.
public class InstallationLifecycleDelegate : MSInstallationLifecycleDelegate
{
public InstallationLifecycleDelegate()
{
}
public override void DidFailToSaveInstallation(MSNotificationHub notificationHub, MSInstallation installation, NSError error)
{
Console.WriteLine($"Save installation failed with exception: {error.LocalizedDescription}");
}
public override void DidSaveInstallation(MSNotificationHub notificationHub, MSInstallation installation)
{
Console.WriteLine($"Installation successfully saved with Installation ID: {installation.InstallationId}");
}
}
I am writing an Xamarin.forms based app which is currently running on android platform. It is the first time I need to use push-notifications. I followed a guide from microsoft (https://learn.microsoft.com/de-de/xamarin/android/data-cloud/google-messaging/remote-notifications-with-fcm?tabs=vswin)") to implement the notifications.
The target android version is 8.1 API 27. The app runs on a Samsung tab active 2, which has android 8.1.
I configured the app as seen in the tutorial. I push the messages through a defined channel and this channel is subscribed in the app. The messages are pushed by a server which triggers the rest call for the FCM api. The first day I did some tests the transmission worked very good and I would say it was (nearly) reliable.
The next day I implemented some other features and wanted to test the push notifications again. Then: I was very confused, the most messages were not delivered or VERY VERY late. I am not sure if all messages were transmitted, there went may be some lost.
For me the FCM service is a big blackbox where I can delegate some work and then I need to hope that the messages will be transmitted. I am very confused now.
I paste here some code, but it is nearly what you can find in the tutorial:
My Questions:
What can I do? Is there something to get some more information from the FCM what my messages are currently doing? Or are there some problems with the code?
This is run in the mainActivity:
if (this.IsPlayServicesAvailable())
{
// Creates a notification channel
this.CreateNotificationChannel();
//Console.WriteLine("InstanceID token: " + FirebaseInstanceId.Instance.Token);
// Subscribe to notification token
FirebaseMessaging.Instance.SubscribeToTopic("channel");
Log.Debug(TAG, "Subscribed to remote notifications");
}
This checks if the channel can be created and creates it: (is called in the mainActivity)
private void CreateNotificationChannel()
{
// The app is not running on Android 8.0 or higher
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
return;
}
// Create a notification channel for publishing notifications
var channel = new NotificationChannel(CHANNEL_ID, "FCM Notifications", NotificationImportance.Default)
{
Description = "Firebase Cloud Messages appear in this channel"
};
var notificationManager = (NotificationManager)GetSystemService(Android.Content.Context.NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
This checks if playServices are available: (also called in mainActivity)
public bool IsPlayServicesAvailable()
{
int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.Success)
{
if (GoogleApiAvailability.Instance.IsUserResolvableError(resultCode))
{
Log.Debug(TAG, GoogleApiAvailability.Instance.GetErrorString(resultCode));
}
else
{
Log.Debug(TAG, "This device has no compatible Google Play services APK - Download an APK from the Google Play Store or to enable it in the device's system settings!");
Finish();
}
return false;
}
else
{
Log.Debug(TAG, "Google Play Services are available.");
return true;
}
}
The last snipped is the service to handle a notification and inform the user:
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class CustomFirebaseMessagingService : FirebaseMessagingService
{
// Logging Tag
private static readonly string TAG = "CustomFirebaseMessagingService";
/* Handles data messages and notifications messages if the app is in foreground.
*
* Apps only have 10 seconds in which to handle an incoming Firebase Cloud Message.
* Any work that takes longer than this should be scheduled for background execution using a library such as the 'Android Job Scheduler' or the 'Firebase Job Dispatcher'.
*
*/
public override void OnMessageReceived(RemoteMessage message)
{
Log.Debug(TAG, "Message from: " + message.From);
// If the message data payload is not empty, display a notification
if (message.Data.Count > 0)
{
Log.Debug(TAG, "Data Payload: " + message.Data.ToString());
this.SendNotification(message.Data);
}
}
// Converts the incoming FCM message into a local notification
private void SendNotification(IDictionary<string, string> data)
{
Console.WriteLine("Push Message received");
var intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
if (data.TryGetValue("message", out string message))
{
foreach (var key in data.Keys)
{
intent.PutExtra(key, data[key]);
}
var pendingIntent = PendingIntent.GetActivity(this, MainActivity.NOTIFICATION_ID, intent, PendingIntentFlags.OneShot);
var notificationBuilder = new NotificationCompat.Builder(this, MainActivity.CHANNEL_ID)
.SetSmallIcon(Resource.Drawable.NotificationIcon)
.SetContentTitle("TITEL")
.SetContentText(message)
.SetAutoCancel(true)
.SetContentIntent(pendingIntent);
var notificationManager = NotificationManagerCompat.From(this);
notificationManager.Notify(MainActivity.NOTIFICATION_ID, notificationBuilder.Build());
}
}
}
I am using unity 2018 with Firebase. I am working on Firebase Push Notification.The Push Notification Message is Received well.
But when my run my app running in foreground the push notification message is not received. But when my close my app. The push notification message is received.
What i have to do for Receiving Push Notification when my app is in Foreground?
You have to handle push notification manually in callback:
//Subscribe on application start
public void Start() {
Firebase.Messaging.FirebaseMessaging.MessageReceived += OnMessageReceived;
}
public void OnMessageReceived(object sender, Firebase.Messaging.MessageReceivedEventArgs e)
{
UnityEngine.Debug.Log("Received a new message from: " + e.Message.From);
if (e.Message.NotificationOpened == false)
{
// Show PopUp or Do something here
}
}
I am suffering from an issue. I wanted to get get userInfo or payload data when app is in suspended mode. I am able to get payload data when i tap on received notification. but i am not able to get userInfo data when app is in suspend more exited. Is there any way or method to get push notification data ? when app suspend more exited mode
i am using following method :
- (void)applicationWillEnterForeground:(UIApplication *)application
{
NSLog(#"notification active=%#",userInfo);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
flag=0;
if (application.applicationState == UIApplicationStateActive || application.applicationState == UIApplicationStateInactive || application.applicationState == UIApplicationStateBackground)
{
NSLog(#"notification active=%#",userInfo);
}
else
{
NSLog(#"notification inactive%#",userInfo);
}
application.applicationIconBadgeNumber = 0;
}
Having a problem / lack of knowledge with SignalR , I have a Hub client/server and a separate GUI app with intermittently will connect to the hub and send a message.
I either need the connection to be maintained or to disconnect after the message has been sent.
The problem I run into is that it will always send the first message but then get stuck sending the second message. I am unsure why this is.
public void SignalR_Connect(string message)
{
var connection = new HubConnection("http://site/signalr");
IHubProxy myHub = connection.CreateProxy("chat");
Console.WriteLine("Connection state is : " + connection.State.ToString());
connection.Start().ContinueWith(task =>
{
Console.WriteLine("Attempting to Connect");
if (task.IsFaulted)
{
Console.WriteLine("There was an error opening the connection:{0}", task.Exception.GetBaseException());
}
else
{
Console.WriteLine("Client Connected");
}
}).Wait();
//Sending message
myHub.Invoke("Send", message).ContinueWith(task =>
{
if (task.IsFaulted)
{
Console.WriteLine("There was an error calling send: {0}", task.Exception.GetBaseException());
Console.WriteLine(task.Status.ToString());
}
else
{
Console.WriteLine("Send Complete.");
}
}).Wait();
//Back round to get the next message.
//Method grabs next message in the MSMQ and sends it to SignalR_Connect method.
Read_Queue();
}
I have tried connection.stop() , implementing a close method on the hub to inform the server of the client leaving and setting the GlobalHost.Configuration.ConnectionTimeout but I am still getting the same behaviour.