I have Notification Hub setup correctly with FCM and my Android app. The problem is when my app is in foreground the notification never shows but debugger catches on OnPushNotificationReceived so I know the setup is working. Also when the app is backgrounded or not running the notification pops up. I think it has to do with the code which I got from:
https://learn.microsoft.com/en-us/azure/notification-hubs/xamarin-notification-hubs-push-notifications-android-gcm
Here is my code:
public void OnPushNotificationReceived(Context context, INotificationMessage message)
{
var intent = new Intent(context, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
var pendingIntent = PendingIntent.GetActivity(context, 0, intent, PendingIntentFlags.OneShot);
var notificationBuilder = new NotificationCompat.Builder(context, MainActivity.CHANNEL_ID);
notificationBuilder.SetContentTitle(message.Title)
.SetSmallIcon(Resource.Drawable.ic_launcher)
.SetContentText(message.Body)
.SetAutoCancel(true)
.SetShowWhen(false)
.SetContentIntent(pendingIntent);
var notificationManager = NotificationManager.FromContext(context);
notificationManager.Notify(0, notificationBuilder.Build());
}
Any help would be much appreciated
I found the issue to be because no NotificationChannel existed so I created it in the contrstructor:
public AzureListener()
{
var channel = new NotificationChannel(MainActivity.CHANNEL_ID, "General", NotificationImportance.Default);
var notificationManager = NotificationManager.FromContext(Application.Context);
notificationManager.CreateNotificationChannel(channel);
}
It worked after I added this.
Related
I have referred to this question already : Stopping and restarting foreground service scanning with altbeacon
My requirement is to restart the beacon scan depending on API response containing scanTime and waitTime. I would have started a scan with default config and once i receive API response from server i need to restart the scan with new config. So this is the code i have. Is this valid to just stop and then start the scan again? Will this have any adverse effect?
public void reconnect(int scanTimeInMills, int waitTimeInMillis) {
try {
if (beaconManager != null) {
beaconManager.stopRangingBeaconsInRegion(ALL_REGION);
beaconManager.unbind(this);
}
beaconManager = null;
beaconManager = BeaconManager.getInstanceForApplication(MyApplication.getInstance());
beaconManager.getBeaconParsers().add(new BeaconParser()
.setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
beaconManager.setForegroundScanPeriod(scanTimeInMills);
beaconManager.setBackgroundScanPeriod(scanTimeInMills);
beaconManager.setBackgroundBetweenScanPeriod(waitTimeInMillis);
beaconManager.setForegroundBetweenScanPeriod(waitTimeInMillis);
if (!beaconManager.isBound(this)) {
String channelName = "App Notification Service";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel chan = new NotificationChannel(
String.valueOf(Constant.APP_CLOCKIN_NOTIIFICATION_ID), channelName,
NotificationManager.IMPORTANCE_DEFAULT);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) WrkspotApplication.getInstance()
.getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);
}
Intent intent = new Intent(MyApplication.getInstance(), HomeScreenActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(
MyApplication.getInstance(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT
);
NotificationCompat.Builder notificationBuilder = new Builder(
MyApplication.getInstance())
.setLargeIcon(BitmapFactory
.decodeResource(MyApplication.getInstance().getResources(),
R.mipmap.ic_launcher))
.setSmallIcon(R.drawable.ic_logo_notification)
.setContentTitle(getApplicationContext().getString(R.string.app_name))
.setContentText(
getApplicationContext().getString(R.string.you_are_clocked_in))
.setStyle(new BigTextStyle().bigText(
getApplicationContext().getString(R.string.you_are_clocked_in)))
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setChannelId(String.valueOf(Constant.APP_CLOCKIN_NOTIIFICATION_ID));
beaconManager.enableForegroundServiceScanning(notificationBuilder.build(),
Constant.APP_CLOCKIN_NOTIIFICATION_ID);
beaconManager.bind(this);
}
} catch (Exception e) {
Log.e(getClass().getSimpleName(), String.valueOf(e.getMessage()));
}
}
This really does not require all that code. Just use:
beaconManager.setForegroundScanPeriod(scanTimeInMills);
beaconManager.setForegroundBetweenScanPeriod(waitTimeInMillis);
beaconManager.setBackgroundMode(false);
beaconManager.updateScanPeriods();
You do not need to set both foreground and background scan periods. Just do not use BackgroundPowerSaver, and you can leave it in foreground mode all the time.
All the complex logic binding and unbinding shown in the question can cause trouble because it starts and stops the scanning process. This is an asynchronous operation, and it can lead to race conditions. Best to keep it simple.
Im trying to deploy my app with notifications but it's giving me the biggest headache in the world. All other questions ive seen with regards to this seem outdated.
I set up APNs to be sent from a nodeJS script that I have running. When running in my sandbox everything was working well. As soon as I sent my app to TestFlight, notifications stopped sending. My script is still Successfully sending to the Notification Id registered with my phone but im assuming its not the correct production Id. If anyone canhelp get me sending production notifications it would be greatly appreciated! Thank you
APN Server code
var options = {
token: {
key: "AuthKey_6V27D43P5R.p8",
keyId: "3Z6SEF7GE5",
teamId: "ASQJ3L7765"
},
production: true
};
var apnProvider = new apn.Provider(options);
function SendIOSNotification(token, message, sound, payload, badge){
var deviceToken = token; //phone notification id
var notification = new apn.Notification(); //prepare notif
notification.topic = 'com.GL.Greek-Life'; // Specify your iOS app's Bundle ID (accessible within the project editor)
notification.expiry = Math.floor(Date.now() / 1000) + 3600; // Set expiration to 1 hour from now (in case device is offline)
notification.badge = badge; //selected badge
notification.sound = sound; //sound is configurable
notification.alert = message; //supports emoticon codes
notification.payload = {id: payload}; // Send any extra payload data with the notification which will be accessible to your app in didReceiveRemoteNotification
apnProvider.send(notification, deviceToken).then(function(result) { //send actual notifcation
// Check the result for any failed devices
var subToken = token.substring(0, 6);
console.log("Succesfully sent message to ", subToken);
}).catch( function (error) {
console.log("Faled to send message to ", subToken);
})
}
i've written an Azure function and connected the output to a notification-hub to send push notifications using APNS. It works fine as long as i send the notification to all registered devices, but i don't know how to use tags in order to address a specific user. If i try to use a tag, i get an error message saying "Exception while executing function: Functions.SendSinglePushNotification. Microsoft.Azure.WebJobs.Host: Error while handling parameter notification after function returned:. Microsoft.Azure.NotificationHubs: notification.Tag property should be null."
Here's my code so far:
#r "Microsoft.Azure.NotificationHubs"
#r "Newtonsoft.Json"
using System;
using Microsoft.Azure.NotificationHubs;
using Newtonsoft.Json;using
Microsoft.Azure.WebJobs.Host.Bindings.Runtime;
public static void Run(HttpRequestMessage req, TraceWriter log,Binder
binder, out AppleNotification notification)
{
string user = "Test";
string tagExpression = "Test";
string userTag = req.GetQueryNameValuePairs()
.FirstOrDefault(q => string.Compare(q.Key, "userid", true) == 0)
.Value;
string apnsNotificationPayload = "{\"aps\": {\"alert\": \"Test: (" + user + ")\" }}";
notification = new AppleNotification(apnsNotificationPayload);
}
I was trying to use notification = new
AppleNotification(apnsNotificationPayload,tagExpression);
but that does not work. How can i achieve that?
Thanks a lot and best regards
I had similar issue. Eventually, what worked for me was constructing Notification client manually. I am developing functions in Visual Studio, so my code is slightly different from yours.
[FunctionName("MyFunction")]
public static async Task Run([ServiceBusTrigger("queuename", AccessRights.Listen, Connection =
"<connection-settings-name>")] string myQueueItem, TraceWriter log)
{
log.Info($"C# Queue trigger function processed: {myQueueItem}");
var notificationHubSas = "<DefaultFullSharedAccessSignature from Azure portal>";
var notificationHubName = "myhub";
var nhClient = NotificationHubClient.CreateClientFromConnectionString(notificationHubSas, notificationHubName);
var tags = "";
await nhClient.SendTemplateNotificationAsync(<notification payload>, tags);
}
I am currently using the connectivity plugin to detect network status. What I am trying to do is when I want to send data and the device is offline I start a background task using the messaging service and respective platform specific code as shown here.
The problem I am having is the Android service has a callback that continues being called even after I have stopped the service. The code below assigns a delegate to CrossConnectivity.Current.ConnectivityChanged and should stop the service after it sends the required data when network connection is restored.
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
...
Task.Run(() =>
{
CrossConnectivity.Current.ConnectivityChanged += delegate
{
if (CrossConnectivity.Current.IsConnected)
{
if (!App.ServerManager.IsUserLoggedIn())
App.ServerManager.LoginUserAsync(Constants.__User);
//send our data
foreach (SampleItem s in sList)
{
try
{
//query to see if it exists on the server
App.ServerManager.GetSamplesAsync();
Task t = App.ServerManager.SaveSampleAsync(s);
}
catch (Exception e)
{
Console.WriteLine(#" ERROR {0}", e.Message);
}
}
// Instantiate the builder and set notification elements:
Notification.Builder builder = new Notification.Builder(this)
.SetContentTitle("Jarver Industries")
.SetContentText("Samples Successfuly Sent!")
.SetDefaults(NotificationDefaults.Sound)
.SetSmallIcon(Resource.Drawable.banner);
// Build the notification:
Notification notification = builder.Build();
// Get the notification manager:
NotificationManager notificationManager =
GetSystemService(Context.NotificationService) as NotificationManager;
// Publish the notification:
const int notificationId = 19900203;
notificationManager.Notify(notificationId, notification);
MessagingCenter.Send<BackgroundDataFinishedMessage>(this, "Done");
StopSelf();
}
};
});
return StartCommandResult.Sticky;
}
I am sure I am doing something wrong on a .NET level, but I am unsure what alternatives there are.
This question already has answers here:
Can't send push notifications using the server API
(4 answers)
Closed 6 years ago.
I am having trouble sending push notifications via Firebase through HTTP Request to my iOS device after the app is killed. When the app is in the foreground or active in the background everything work as expected. But if I kill the app it won't work. I am able to send notifications to my app through the Firebase console if the app is killed, so I believe something must be wrong with the code I am using.
This is my code for sending the push notification:
private void SendPushNotification(string devicetoken, string header, string content, string pushdescription)
{
var textNotification = new
{
to = devicetoken,
notification = new
{
title = header,
text = content,
content_available = true,
sound = "enabled",
priority = "high",
id = pushdescription,
},
project_id = "rrp-mobile",
};
var senderId = "212579566459";
var notificationJson = Newtonsoft.Json.JsonConvert.SerializeObject(textNotification);
using (var client = new WebClient())
{
client.Encoding = Encoding.UTF8;
client.Headers[HttpRequestHeader.ContentType] = "application/json";
client.Headers[HttpRequestHeader.Authorization] = "key=AIfrSyAtgsWCMH4s_bOyj-Us4CrdsifHv-GqElg";
client.Headers["Sender"] = $"id={senderId}";
client.Headers[HttpRequestHeader.ContentType] = "application/json";
client.UploadString("https://fcm.googleapis.com/fcm/send", "POST", notificationJson);
}
}
Am I forgetting something here? This works for sending push notifications to Android devices both in foreground, background and when app is killed, and like I said also to iOS devices in foreground and background.
The only issue is sending push notifications to iOS devices when the app has been killed. Does anyone have any idea as to how I would solve this issue?
I just realized my mistake, and it was very simple. I am posting this here because I believe this may be an easy thing to miss.
var textNotification = new
{
to = devicetoken,
notification = new
{
title = header,
text = content,
content_available = true,
sound = "enabled",
**priority = "high",**
id = pushdescription,
},
project_id = "rrp-mobile",
};
You need to make sure that the priority property is defined outside the "notification" scope, like this:
var textNotification = new
{
to = devicetoken,
**priority = "high",**
notification = new
{
title = header,
text = content,
content_available = true,
sound = "enabled",
id = pushdescription,
},
project_id = "rrp-mobile",
};
This will make your push notifications deliver even if the app is killed.