Xamarin Android iOS FirebasePushNotificationPlugin not receive message but token receves - c#

i'm using xamarin iOS FirebasePushNotificationPlugin for cloud messages, but i'm receiving the token but i can not receive any notification. CrossFirebasePushNotification.Current.OnNotificationReceived even not firing.
here is how my appDelegate looks likes.
using System;
using System.Collections.Generic;
using System.Linq;
using Foundation;
using Plugin.FirebasePushNotification;
using UIKit;
namespace onlinefirebase.iOS
{
// The UIApplicationDelegate for the application. This class is responsible for launching the
// User Interface of the application, as well as listening (and optionally responding) to
// application events from iOS.
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
FirebasePushNotificationManager.Initialize(options, true);
FirebasePushNotificationManager.CurrentNotificationPresentationOption =
UserNotifications.UNNotificationPresentationOptions.Alert |
UserNotifications.UNNotificationPresentationOptions.Badge;
return base.FinishedLaunching(app, options);
}
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
FirebasePushNotificationManager.DidRegisterRemoteNotifications(deviceToken);
}
public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
{
FirebasePushNotificationManager.RemoteNotificationRegistrationFailed(error);
}
// To receive notifications in foregroung on iOS 9 and below.
// To receive notifications in background in any iOS version
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired 'till the user taps on the notification launching the application.
// If you disable method swizzling, you'll need to call this method.
// This lets FCM track message delivery and analytics, which is performed
// automatically with method swizzling enabled.
FirebasePushNotificationManager.DidReceiveMessage(userInfo);
// Do your magic to handle the notification data
System.Console.WriteLine(userInfo);
completionHandler(UIBackgroundFetchResult.NewData);
}
}
}
Here is how i receive the notification
using System;
using Plugin.FirebasePushNotification;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace onlinefirebase
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new MainPage();
CrossFirebasePushNotification.Current.OnTokenRefresh += (s, p) =>
{
System.Diagnostics.Debug.WriteLine($"TOKEN : {p.Token}");
};
CrossFirebasePushNotification.Current.OnNotificationReceived += (s, p) =>
{
System.Diagnostics.Debug.WriteLine("Received");
};
}
protected override void OnStart()
{
}
protected override void OnSleep()
{
}
protected override void OnResume()
{
}
}
}
I have verified
. Enabled Background Mode -> Remote Notifications
. Info.plist -> "FirebaseAppDelegateProxyEnabled" boolean -> No
I'm successfully getting the token, but i can not receive the notification.

Issue is based on Apple key, apple key should be upload to firebase cloud panel and it'll work

Related

Xamarin Forms Multi-App - MacOS project not showing Xamarin forms

Edit: Added link to project I created:
https://drive.google.com/file/d/1A4XGKdxeC22_wqtNEtenLxYbgCp3I_dA/view?usp=sharing
I have a very basic multi-platform application created I Visual Studio 2019 (Windows 10) with 4 projects:
Source Project
Android
iOS
UWP
I added the MacOS project following these instructions:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/platform/other/mac
The application compiles but loads a blank form and does not show any of the Xamarin forms as per the UWP, iOS and Android apps.
I next created an empty Multi-Platform application natively on a Mac - added the MacOS as per the above instructions and get the same outcome, a blank form loading.
The code I am using in the Mac project is the link above.
// AppDelelegate.cs
using AppKit;
using Foundation;
using Xamarin.Forms;
using Xamarin.Forms.Platform.MacOS;
using pbTrader;
namespace pbTrader.MacOS
{
[Register("AppDelegate")]
public class AppDelegate : FormsApplicationDelegate
{
NSWindow window;
public AppDelegate()
{
var style = NSWindowStyle.Closable | NSWindowStyle.Resizable | NSWindowStyle.Titled;
var rect = new CoreGraphics.CGRect(200, 1000, 1024, 768);
window = new NSWindow(rect, style, NSBackingStore.Buffered, false);
window.Title = "Xamarin.Forms on Mac!"; // choose your own Title here
window.TitleVisibility = NSWindowTitleVisibility.Hidden;
}
public override NSWindow MainWindow
{
get { return window; }
}
public override void DidFinishLaunching(NSNotification notification)
{
Forms.Init();
LoadApplication(new App());
base.DidFinishLaunching(notification);
}
public override void WillTerminate(NSNotification notification)
{
// Insert code here to tear down your application
}
}
}
// Main.cs
using AppKit;
namespace pbTrader.MacOS
{
static class MainClass
{
static void Main(string[] args)
{
NSApplication.Init();
NSApplication.SharedApplication.Delegate = new AppDelegate(); // add this line
NSApplication.Main(args);
}
}
}

Android 8 receive of stop receiving media buttons events

I have a service that listens to media buttons, but I only want to listen to those when my service is running since I have a button on the UI to start/stop the service.
How can I achieve the following two actions:
On MyService start-up, start receiving media button events to com.myApp/MyService.
On MyService end, stop receiving media button events in com.myApp/MyService.
The related logs are the following:
D MediaSessionService: Sending KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_HEADSETHOOK, scanCode=226, metaState=0, flags=0x8, repeatCount=0, eventTime=13258317, downTime=13258317, deviceId=4, source=0x101 } to com.myApp/MyService (userId=0)
Note:
I found out that I can start receiving media events after my app started to play audio. This is however not ideal, since I don't want to play audio in my app. (I am only using media events in order to trigger voice recognition)
After I played audio, my service is apparently the default media receiver. This means that when a media button is pressed, my service get instantiated, does nothing, and get destroyed. This is not an idea behavior for the end user since my app ends up 'stealing' these events that could potentially be handled by something else.
Overriding OnStartCommand() in my service does not help
Calling SetMediaButtonReceiver on the MediaSession does not help either
Using a BroadcastReceiver with the intent "android.intent.action.MEDIA_BUTTON" registered in the AudioManager does not work either
Relevant code (in C#, I am on Xamarin.Forms, but that should not have any impact on the way to achieve this)
public class MediaSessionCompatCallback : MediaSessionCompat.Callback
{
public Func<Intent, bool> MediaButtonEvent { get; set; }
public override bool OnMediaButtonEvent(Intent mediaButtonEvent) => MediaButtonEvent?.Invoke(mediaButtonEvent) ?? false;
}
[Service(Exported = true, Enabled = true)]
[IntentFilter(new[] { ServiceInterface })]
public class MediaBrowserService : MediaBrowserServiceCompat, AudioManager.IOnAudioFocusChangeListener
{
private MediaSessionCompat mediaSession;
private MediaSessionCompatCallback mediaSessionCallback;
private void CreateMediaSessionCallback()
{
mediaSessionCallback = new MediaSessionCompatCallback()
{
MediaButtonEvent = OnMediaButtonEvent
};
}
private void SetupMediaSession()
{
CreateMediaSessionCallback();
var stateBuilder = new PlaybackStateCompat.Builder().SetActions(PlaybackStateCompat.ActionPlay | PlaybackStateCompat.ActionPlayPause);
mediaSession = new MediaSessionCompat(this, nameof(MediaBrowserService));
mediaSession.SetFlags(MediaSessionCompat.FlagHandlesMediaButtons | MediaSessionCompat.FlagHandlesTransportControls);
mediaSession.SetPlaybackState(stateBuilder.Build());
mediaSession.SetCallback(mediaSessionCallback);
mediaSession.Active = true;
SessionToken = mediaSession.SessionToken;
}
private void BuildNotification() { [...] }
public override void OnCreate()
{
base.OnCreate();
SetupMediaSession();
StartForeground(135, BuildNotification());
ContextCompat.StartForegroundService(ApplicationContext, new Intent(ApplicationContext, Java.Lang.Class.FromType(typeof(MediaBrowserService))));
}
public override void OnDestroy()
{
base.OnDestroy();
if (mediaSession != null)
{
mediaSession.Active = false;
mediaSession.SetCallback(null);
mediaSession.Release();
mediaSession.Dispose();
mediaSession = null;
}
if (mediaSessionCallback != null)
{
mediaSessionCallback.Dispose();
mediaSessionCallback = null;
}
StopForeground(true);
StopSelf();
}
}

Visual Studio App Center: The 'await' operator can only be used within an async method

I need help with App Center push notifications. I want to find out if the user has enabled or disabled push notifications on his iOS/Android device. This task should be done when the application launches. I followed this App Center tutorial but I get an error message when I check if push notifications are enabled or disabled.
App Center tutorial
Error CS4033: The 'await' operator can only be used within an async
method. Consider marking this method with the 'async' modifier and
changing its return type to 'Task'.
What is wrong? How can I find out if the user has enabled or disabled push notifications?
using Foundation;
using UIKit;
using Microsoft.AppCenter;
using Microsoft.AppCenter.Analytics;
using Microsoft.AppCenter.Crashes;
using Microsoft.AppCenter.Push;
namespace iosprojectnew.iOS
{
[Register("AppDelegate")]
class Program : UIApplicationDelegate
{
private static Game1 game;
internal static void RunGame()
{
game = new Game1();
game.Run();
}
static void Main(string[] args)
{
UIApplication.Main(args, null, "AppDelegate");
}
public override void FinishedLaunching(UIApplication app)
{
if (!AppCenter.Configured)
{
bool isEnabled = await Push.IsEnabledAsync();
Push.PushNotificationReceived += (sender, e) =>
{
// Add the notification message and title to the message
var summary = $"Push notification received:" +
$"\n\tNotification title: {e.Title}" +
$"\n\tMessage: {e.Message}";
// If there is custom data associated with the notification,
// print the entries
if (e.CustomData != null)
{
summary += "\n\tCustom data:\n";
foreach (var key in e.CustomData.Keys)
{
summary += $"\t\t{key} : {e.CustomData[key]}\n";
}
}
// Send the notification summary to debug output
System.Diagnostics.Debug.WriteLine(summary);
};
}
AppCenter.Start("...", typeof(Analytics), typeof(Crashes), typeof(Push));
RunGame();
}
}
}
A method that uses await must be marked as async. Try to add the async keyword before void FinishedLaunching:
public override async void FinishedLaunching(UIApplication app) { ... }
The await keyword can be used only into a async method, but this method is an override, so you cant' transform to a task.
Anyway you can write the line code where you use async like this:
bool isEnabled = await Push.IsEnabledAsync().Result;

Android Xamarin detect started from task manager

I am currently developing an android xamarin app (android 6 and above) and I have got a problem.
Our customer wants to secure the app by a pinpad. Whenever the app is started the user has to enter a four digit pin.
We have created an activity for the pinpad. This works pretty fine, but the problem is the following:
The pinpad just opens if the app was completely killed (e.g. by the task manager ) -> cold started.
How can I achive that the pinpad opens if the app was in the background and reopend by the task manager for example (user pressed home button and then wants to start app again) -> warm started.
I've tried to do this by OnResume(), OnStart(),. But unfortunately they trigger every time an another activity (e.g. open detail view of list item) is opened.
use IActivityLifecycleCallbacks to listen the status.
Application registration ActivityLifecycleCallbacks, such, when each activity in the app lifecycle occurs, the Application can be listening to. The number of public void onActivityStarted(activity activity) and public void onActivityStopped(activity activity) of an activity can be used to determine whether the app is in the foreground. Because when the app is in the foreground, an activity must have started onActivityStarted but not onActivityStopped, so the statistics of the number of activities opened in the app must be 1. When the app switches to the background, activityStartCount will be 0.
so write a Helper classes :
public class AppFrontBackHelper
{
public static OnAppStatusListener mOnAppStatusListener;
private LifecycleCallBack lifecycleCallBack;
public AppFrontBackHelper()
{
}
/**
* Register status listener, only used in Application
* #param application
* #param listener
*/
public void register(Application application, OnAppStatusListener listener)
{
mOnAppStatusListener = listener;
lifecycleCallBack = new LifecycleCallBack();
application.RegisterActivityLifecycleCallbacks(lifecycleCallBack);
}
public void unRegister(Application application) => application.UnregisterActivityLifecycleCallbacks(lifecycleCallBack);
public interface OnAppStatusListener
{
void onFront();
void onBack();
}
public class LifecycleCallBack : Java.Lang.Object, Application.IActivityLifecycleCallbacks
{
public int activityStartCount { get; private set; }
public void OnActivityCreated(Activity activity, Bundle savedInstanceState)
{
}
public void OnActivityDestroyed(Activity activity)
{
}
public void OnActivityPaused(Activity activity)
{
}
public void OnActivityResumed(Activity activity)
{
}
public void OnActivitySaveInstanceState(Activity activity, Bundle outState)
{
}
public void OnActivityStarted(Activity activity)
{
activityStartCount++;
//A value from 1 to 0 indicates cutting from the background to the foreground
if (activityStartCount == 1)
{
if (mOnAppStatusListener != null)
{
mOnAppStatusListener.onFront();
}
}
}
public void OnActivityStopped(Activity activity)
{
activityStartCount--;
//A value from 1 to 0 indicates cutting from the foreground to the background
if (activityStartCount == 0)
{
//从前台切到后台
if (mOnAppStatusListener != null)
{
mOnAppStatusListener.onBack();
}
}
}
}
}
then custom an Application and regist the listener :
[Application]
public class MyApplication : Application,AppFrontBackHelper.OnAppStatusListener
{
protected MyApplication(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}
public override void OnCreate()
{
base.OnCreate();
AppFrontBackHelper appFrontBackHelper = new AppFrontBackHelper();
appFrontBackHelper.register(this, this);
}
public void onBack()
{
Toast.MakeText(this, "from front to back", ToastLength.Short).Show();
}
public void onFront()
{
Toast.MakeText(this, "from back to front", ToastLength.Short).Show();
}
}
you could do something in the onFront() callback.

DismissViewController sometimes causes the program to freeze or crash

I have the following MonoTouch program:
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System;
namespace Experiment
{
// This is just for the example, I use a singleton in my app to do this.
public class AppSettings
{
public static bool IsLoggedIn = false;
}
[Register ("AppDelegate")]
public class AppDelegate : UIApplicationDelegate
{
UIWindow window;
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
UIViewController baseViewController = new RootViewController();
window = new UIWindow(UIScreen.MainScreen.Bounds);
window.AddSubview(baseViewController.View);
window.MakeKeyAndVisible();
return true;
}
static void Main(string[] args)
{
UIApplication.Main(args, null, "AppDelegate");
}
}
public class RootViewController : UITableViewController
{
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
if (!AppSettings.IsLoggedIn) {
this.PresentViewController(new LoginPopupController(), false, () => {});
}
}
}
public class LoginPopupController : UIViewController
{
public override void LoadView()
{
View = new UIView(UIScreen.MainScreen.ApplicationFrame);
View.BackgroundColor = UIColor.White;
UIButton button = new UIButton();
button.SetTitle("press me", UIControlState.Normal);
button.Frame = new RectangleF(50, 50, 80, 80);
button.TouchUpInside += delegate {
LoginSucceeded();
};
button.BackgroundColor = UIColor.Purple;
View.AddSubview(button);
}
public void LoginSucceeded()
{
AppSettings.IsLoggedIn = true;
Console.WriteLine("This line causes multiple problems at random");
DismissViewController(true, () => {});
}
}
}
It has two controllers the RootViewController and the LoginPopupController. The FinishedLoading method adds the RootViewController to the window. The RootViewController in the ViewDidAppear method checks if the app is logged in. If not, it will present the LoginPopupController.
The LoginPopupController has a button, which when pressed will set IsLoggedIn to true, and dismiss itself.
Basically, I want a login window to appear if the user isn't logged in, and then dismiss itself after it has entered login details into a singleton settings object.
However, the app is very unreliable at the moment. Pressing the "press me" button can cause the following to happen at random:
Work as expected
Freeze the app
Crash the app
Do nothing on first press, crash the app on the second press
The Console.WriteLine line has a big effect on this - if you remove it the code succeeds more often (but not always).
Can anyone figure out what is causing this problem? It seems like a race condition (as the results change between runs), however I can't figure out what could be causing that.
I'm running the code on the simulator using iOS 5.1. I have MonoTouch version 5.2.10 installed with Mono 2.10.8.
I have done two changes in your code and it never crashed, at least for my number of tries.
First, move the UIButton declaration to the class:
UIButton button;
public override LoadView()
{
//...
}
Second, initialize the button with the UIButton.FromType(UIButtonType) static method:
button = UIButton.FromType(UIButtonType.Custom);
The UIButton() constructor had problems in previous versions of MonoTouch. In some versions it was not even available. I could not find anything specific for its current state, however creating buttons with the static method is the normal way to go, according to Apple docs.

Categories