How to disable Firebase push notifications in Unity from client side application? - firebase

I have integrated Firebase into Unity project and it all works. I would like to integrate disabling of push notifications if user wants to disable them in his app. I haven't found solution in code for this, also there is one unanswered question same as mine, so I am posting new one just in case someone has come with a solution for this.

I managed to do this by using Firebase Messaging Topic and calling SubscribeAsync() and UnsubscribeAsync().
private void Start()
{
if ( notificationsAreOn )
InitFirebaseMessaging();
else
DisableFirebase();
}
private void DisableFirebase()
{
Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith( task =>
{
var dependencyStatus = task.Result;
if ( dependencyStatus == Firebase.DependencyStatus.Available )
{
FirebaseAnalytics.SetAnalyticsCollectionEnabled( false );
Firebase.Messaging.FirebaseMessaging.UnsubscribeAsync("VeryCoolTopic");
Firebase.Messaging.FirebaseMessaging.TokenReceived += null;
Firebase.Messaging.FirebaseMessaging.MessageReceived += null;
}
else
{
UnityEngine.Debug.LogError(
System.String.Format("Could not resolve all Firebase dependencies: {0}", dependencyStatus)
);
}
});
}
private void InitFirebaseMessaging()
{
Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith( task =>
{
var dependencyStatus = task.Result;
if ( dependencyStatus == Firebase.DependencyStatus.Available )
{
FirebaseAnalytics.SetAnalyticsCollectionEnabled( true );
Firebase.Messaging.FirebaseMessaging.SubscribeAsync("VeryCoolTopic");
Firebase.Messaging.FirebaseMessaging.TokenReceived += OnTokenReceived;
Firebase.Messaging.FirebaseMessaging.MessageReceived += OnMessageReceived;
}
else
{
UnityEngine.Debug.LogError(
System.String.Format("Could not resolve all Firebase dependencies: {0}", dependencyStatus)
);
}
});
}
Then in the Firebase console when creating a message, use Topic as a target instead of User Segment.
You could also use disable whole Firebase by deleting the Firebase token using DeleteTokenAsync() but I haven't tested this because the the method with using subscribe and unsubscribe worked for me.

There are two types of messages that you can send with FCM: notifications messages, and data messages.
If your app is active, notification messages are delivered to your application code, which can decide what to do with it. When the app is not active, notification messages are automatically displayed by the system. There is not way to suppress this behavior.
Data messages are always delivered to your application code, which can decide what to do with them.
So if you want to allow the user to suppress the display of messages, you'll want to only send data messages, and then display them from within your application code.
Note that alternatively, you can find a way to not deliver messages to a user who has disabled notifications. How exactly to do this depends on your implementation. For example: if you're sending directly to FCM Instance ID tokens, you can skip the tokens of users who have disabled push notifications. And if you're using topic subscription to send messages, you can create a topic that users subscribe to to disable notifications, and then create conditions to exclude delivery to that topic.

Related

iOS Push Notifications with Azure Notification Hub

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}");
}
}

Xamarin Forms iOS - Saving a user tag in Azure Notification Hubs works in AppDelegate but not in a service

I'm currently trying to get push notifications working for my mobile app using Azure Notification Hubs. Android is working fine and the initial iOS set up in AppDelegate works ok with a sample tag.
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
if (deviceToken == null)
{
return;
}
SBNotificationHub hub = new SBNotificationHub(CommonConstants.LISTEN_CONNECTION_STRING, CommonConstants.NOTIFICATION_HUB_NAME);
// update registration with Azure Notification Hub
hub.UnregisterAll(deviceToken, async (error) =>
{
if (error != null)
{
System.Diagnostics.Debug.WriteLine($"Unable to call unregister {error}");
return;
}
string[] tags = new[] { "iostestpush" };
NSSet userTags = new NSSet(tags);
hub.RegisterNative(deviceToken, userTags, (error) =>
{
if (error != null)
{
System.Diagnostics.Debug.WriteLine($"Unable to call register {error}");
return;
}
});
var templateExpiration = DateTime.Now.AddDays(120).ToString(System.Globalization.CultureInfo.CreateSpecificCulture("en-US"));
hub.RegisterTemplate(deviceToken, "defaultTemplate", CommonConstants.APN_TEMPLATE_BODY, templateExpiration, userTags, (errorCallback) =>
{
if (errorCallback != null)
{
System.Diagnostics.Debug.WriteLine($"RegisterTemplateAsync error: {errorCallback}");
}
});
});
}
The issue I'm having is I need to register the UserId after a successful login. So I set up a service with the above code, saved the token to the device as string so it can be retrieved in the service and turned back into an NSData token
NSData deviceToken = new NSData(token, NSDataBase64DecodingOptions.None);
After a successful login I send the token string and the tag array to my service.
string[] userTag = new[] { loginResponse.UserId.ToString() };
await this._azureReg.SendRegistrationToServer(deviceToken, userTag);
Which, other than turning the token back into NSData and the user tag into an NSSet, is the same as above other than the name change. But Azure is claiming there is no registration even though my output shows
Registered for push notifications with token: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
I thought it was the string conversion back and forth, so tested that in the AppDelegate and it worked fine.
So, I'm at a loss at how to register the UserId after a successful login and why it works in one place but not the other.
I hope that's clear and thanks for any advice in advance.
You probably ran into the same bug as me and several others.
Basically SBNotificationHub method overloads like UnregisterAll and RegisterTemplate with the callback signature do not work when you use them off the main thread, using the libraries to date. I was also using a Service for the same purpose (to handle push across platforms with different tags, especially for user id) but my implementation involved switching off the main thread for this.
The bug we logged and is now being addressed is here: https://github.com/Azure/azure-notificationhubs-ios/issues/95
The solution, for now, is to ditch SBNotificationHub completely. The Xamarin / Azure documentation is out of date, and SBNOtificationHub is legacy code. The recommended library is MSNotificationHub. https://github.com/azure/azure-notificationhubs-xamarin
As workarounds you can use the SBNotificationHub method overloads that do not involve callbacks (they return an error message instead) or the workaround in the 95 issue above.

Xamarin android: Async await calls not working when app open by clicking push notification

When I open app by tapping on FCM push notification, The API service calls I am making by using await keyword those are not working. Entire app not returning data.
Code for API calling
var result = await objHomework.GetHomeWorksForStudentPagesAsync(studentId.ToString());
result returning null. if app already open, everything working fine. See the Image below screenshot of app
Notification messages are delivered to OnMessageReceived callback only when the app is in the foreground.
Override the HandleIntent Method of the FirebaseMessageService to work for background as well
public override void HandleIntent(Intent intent)
{
try
{
if (intent.Extras != null)
{
var builder = new RemoteMessage.Builder("MyFirebaseMessagingService");
foreach (string key in intent.Extras.KeySet())
{
builder.AddData(key, intent.Extras.Get(key).ToString());
}
this.OnMessageReceived(builder.Build());
}
else
{
base.HandleIntent(intent);
}
}
catch (Exception)
{
base.HandleIntent(intent);
}
}
Actually, I was missing some keys which is necessary for service call authentication in my project. I am getting those keys in MaiActivity but notification click even starting app from somewhere else therefore keys values was null and service calls was not happening.

Push Notification using RHMAP

I am trying to send push notification using RHMAP to iOS devices. Can anyone please let me know how to send push notification to specific device ID using RHMAP. I am able to send notification to all the devices but not to a specific device.
I couldn't find anything regarding this in RHMAP documentation also.
RHMAP has a lot of documented material and examples about push notifications.
The information that you are looking for is in the section "2.3.4.2. Recipient filtering"[1] of the Product features documentation.
"alias - user identification, such as a user name or an e-mail representing a single person (with possibly multiple devices). Intended to enable a unicast communication model."
For more information and examples you can check to fh.push client API[2] and fh.push cloud API[3]. There you can find the following example with filter criteria in the push notifications.
Push a message for specific deviceType in a specific Client App
var message = {
alert: "hello from FH"
},
options = {
apps: ["3uzl1ebi6utciy56majgqlj8"], // list of App IDs
criteria: {
deviceType: "android"
}
};
$fh.push(message, options,
function (err, res) {
if (err) {
console.log(err.toString());
} else {
console.log("status : " + res.status);
}
});
In the example above, for you implement your method using alias, you need to change the deviceType for alias as the following example.
alias: [] // Set here the alias that you are looking for
The following is an example for Android.
import com.feedhenry.sdk.PushConfig;
..........
......
...
private void register() {
PushConfig p = new PushConfig();
p.setAlias("my-alias");
FH.pushRegister(p, new FHActCallback() {
#Override
public void success(FHResponse fhResponse) {
startActivity(new Intent(RegisterActivity.this, MessagesActivity.class));
}
#Override
public void fail(FHResponse fhResponse) {
Toast.makeText(getApplicationContext(),
fhResponse.getErrorMessage(), Toast.LENGTH_SHORT).show();
finish();
}
});
}
[1] - https://access.redhat.com/documentation/en-us/red_hat_mobile_application_platform_hosted/3/html-single/product_features/#sending-notifications
[2] - https://access.redhat.com/documentation/en-us/red_hat_mobile_application_platform_hosted/3/html-single/client_api/#fh-push
[3] - https://access.redhat.com/documentation/en-us/red_hat_mobile_application_platform_hosted/3/html-single/cloud_api/#fh-push
You can set an alias for the device and use that alias to send the notification to it.
As you don't mention which SDK (Objective-C, Swift, Cordova) are you using I can't help you on how to set the alias as it's different for each of them, if you provide more information I can try to help you.

How to Implement PUSH NOTIFICATION in Windows Universal App 10?

This may be a duplicate question. But I did not find any solution yet. Can you please provide any example or sample code for registering App for PUSH NOTIFICATION on uwp 10?
Client code needed and Push notification type is Server to client. Client should register for receiving Server PUSH and Handle the push coming from server.
Here is the link for localpush: http://blogs.msdn.com/b/tiles_and_toasts/archive/2015/10/05/sending-a-local-tile-notification-in-windows-10.aspx
For push notification from server to work, read here https://msdn.microsoft.com/en-us/windows/uwp/controls-and-patterns/tiles-and-notifications-windows-push-notification-services--wns--overview
I have implemented push notification. So, It may help someone.
Add a new method in App.xaml.cs:
private async Task InitNotificationsAsync()
{
// Get a channel URI from WNS.
var channel = await PushNotificationChannelManager
.CreatePushNotificationChannelForApplicationAsync();
channel.PushNotificationReceived += Channel_PushNotificationReceived;
}
Call this method inside OnLaunched method:
protected async override void OnLaunched(LaunchActivatedEventArgs e)
{
await InitNotificationsAsync();
...
}
Hope this will help.

Resources