xamarin / GooglePlayServicesComponents

Other
316 stars 147 forks source link

[Xamarin.Firebase.Messaging] Cannot receive push notifications when app is closed #273

Open Alexander-Alekseev opened 4 years ago

Alexander-Alekseev commented 4 years ago

Xamarin.Android Version (eg: 6.0):

Xamarin.Forms v4.3.0.908675 (not the latest one, but the "previous" one) Xamarin.Android.* libs are v28.0.0.3

Operating System & Version (eg: Mac OSX 10.11):

Edition: Windows 10 Pro Version: 1809 OS Build: 17763.805

Google Play Services Version (eg: 8.4.0):

Xamarin.GooglePlayServices.Base v71.1610.0 Xamarin.Firebase.Messaging v71.1740.0

Describe your Issue:

Title says the problem. Application receives push notification in both foreground and background, but does not receive them if I force close it. I followed both Xamarin and Firebase/Google tutorials to 'integrate' Firebase messaging services. I do have google-services.json in my project (in the Android project, not in the common one). OnMessageReceived is not called when app is closed (I checked logs). I payload only data messages, not notification messages. I'm sure that server side works correctly, because my Java Android application with the same settings (and the same google-services.json) is able to receive push notifications when it's closed. What else can be checked? Please let me know.

Steps to Reproduce (with link to sample solution if possible):

Implementation of FirebaseMessagingService: https://gist.github.com/Alexander-Alekseev/cb555f0ee5bb56c33229e3fbb1848682. Android manifest: https://gist.github.com/Alexander-Alekseev/d4a0a603afd6ff7b7038b7f854f1e4d7.

Include any relevant Exception Stack traces, build logs, adb logs:

CanT94 commented 4 years ago

I have the same problem. Since 1 week the Android Push Notifications stopped working, when I close the app. The store version of my app doesnt have this problem, so it has to be something that came from an update. I am testing it right now and it works if I have the app open and press on home button then it still works, but as soon as I close the app it stops receiving notifications.

Alexander-Alekseev commented 4 years ago

@CanT94, hey, could you please share which versions of Xamarin.Forms, Xamarin.GooglePlayServices.Base, Xamarin.Firebase.Messaging etc. did you use in your build which was uploaded to store and receives push notifications?

Alexander-Alekseev commented 4 years ago

Hi @moljac, no news here? Do you need any additional info?

@CanT94, hello again, could you please help us to find out which packages versions did you use in your store version?

moljac commented 4 years ago

@Alexander-Alekseev Sorry, but no new info right now. I need to sit down and dig into docs. Seems it might be different behavior for closed and force closed apps, but not 100% sure

moljac commented 4 years ago

Yes package version diff/comparisnon would help.

Loki606 commented 4 years ago

v71 of all relevant Firebase packages and none of the tutorials are working.

Alexander-Alekseev commented 4 years ago

Hey @moljac, still no news here? Last time you mentioned 'docs' which you need to dig into. Could you please share which docs did you mean? Maybe I can find something helpful that can increase the speed of solving the problem...

MattVon commented 4 years ago

I made a post on StackOverflow with little success right now, I created a sample project to work on isolating this issue but my sample project works spot on (Foreground, Background and app killed)... Although I've ensured nuget packages, code, manifests, etc. are identical from my sample project to my main project - yet my main project experiences this same issue regardless.

FrankSzendzielarz commented 4 years ago

Likewise same issue. Had 4.3 Forms, just updated to latest today and still same problem.

Alexander-Alekseev commented 4 years ago

@MattVon, @FrankSzendzielarz, hi, I got a new email from MS/Xamarin support team yesterday. Here it is:

This is indeed a confirmed bug within the framework and it seems that a few users are experiencing a similar issue as well.

The product team that works on the GooglePlayComponents for Xamarin are aware of this issue and are working towards a resolution. We’ve brought the Github issue that you’ve posted to their attention and we can follow the status of the report via the following link: https://github.com/xamarin/GooglePlayServicesComponents/issues/273

This is likely due to the new libraries (AndroidX) that are being released as the product has been focusing on making these available as quickly as they can. The issue might be resolved once these libraries have become a stable release and available via NuGet.

I am going to archive this case temporarily while we wait for this bug to be fixed, I will certainly reach out to you should there be any updates that resolves this issue.

Since the support team refers to this task, let's continue the discussion here.

FrankSzendzielarz commented 4 years ago

OK, I finally got this working. Still seem to be some minor issues in my project, probably to do with token refresh, but the core issue of notifications not being received when app is closed now seems to be resolved for me. There were a number of confusing factors.

  1. Main issue turned out to be accessing shared library App property setters from the constructor of the derived FirebaseMessagingService. I had to work around this.
  2. Issue 1) was largely down to my lack of understanding of Android architecture coming at this as a Xamarin .NET developer. I learnt that an Android 'app' consists of at least 3 components (following is my understanding, caveat emptor): the App UI, Services and Receivers. The app has some different states, such as foreground, stopped, and force stopped. When an app is just stopped by swiping it out of the recents list, only the App UI components is terminated; the services/receivers continue as long as memory is available. When an 'intent' (seems to be android parlance for 'message' or 'event') is received when the app is in the 'swipe stopped' state the receiver/service wakes up and handles it, in my case the Firebase message service/receiver, but the app does not exist. 'Force stopped' kills the app and its services, so it can't work.
  3. Running from Visual Studio debugger and then stopping causes a Force Stop. You need to run the app direct on the device a second time after debugging.
  4. Most of the online docs for configuring Xamarin are out of date. The Receiver elements in the android manifest are unnessary for example.
  5. Getting the logs means running the app on device without debugger, then using Visual Studio Device Log to view the messages.
  6. The error message is cryptic "Could not activate JNI Handle 0x7fdbfee170 (key_handle 0x7d963d4) of Java type 'crc64925d64ef8a16450b/FirebaseService' as managed type 'CMSApp.Droid.FirebaseService'."

Suspect that xam/firebase updates modified the lifecycle resulting in the above main issue. Perhaps the updates coincided with code changes that led to this issue.

Alexander-Alekseev commented 4 years ago

@FrankSzendzielarz,

  1. Running from Visual Studio debugger and then stopping causes a Force Stop. You need to run the app direct on the device a second time after debugging.

That's a good catch, thanks!

However, I didn’t understand how you made your application work... I still don't have push notifications when I close my app (when I start and close it, without VS).

FrankSzendzielarz commented 4 years ago

@Alexander-Alekseev Well it's not 100% sorted yet, I still have an issue that the notifications stop 'arriving' after some unknown amount of time, so there's still the chance that this is some kind of red herring, but I am pretty confident I have identified and solved the main issue. I recommend you do this:

  1. In Visual Studio go to View -> Other Windows -> Device Log.
  2. In the top left where it says 'choose device' choose your device connected by usb.
  3. Start logging if it aint already.
  4. Go to the notification hub or firebase or wherever it is you are sending the push messages from, then get ready to send.
  5. Quickly clear the log in the device log.
  6. Quickly send the notification.
  7. Make a note of the millisecond time.
  8. After the device log settles down after a few seconds, stop the logger. Copy the logs into notepad++ or something. (Ctrl-A, Ctrl-C)
  9. Search for the earliest PACKAGE NAME entry in the log
  10. Search for all Warning or Error(usually Warning) entries later than that.

This will give you a clue as to what is going on. In my case I got the JNI error accessing the App from the MyFirebaseService ctor.

FrankSzendzielarz commented 4 years ago

By the way this is the manifest I use:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="Demo" package="CMSApp.CMSApp" android:installLocation="auto" android:versionCode="2">
    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
  <application android:label="Mocha" android:icon="@drawable/xamarin_logo">

  </application>

  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
  <uses-permission android:name="android.permission.WAKE_LOCK" />
  <permission android:name="CMSApp.CMSApp.permission.C2D_MESSAGE" android:protectionLevel="signature" />
  <uses-permission android:name="CMSApp.CMSApp.permission.C2D_MESSAGE" />
  <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
Alexander-Alekseev commented 4 years ago
  • In Visual Studio go to View -> Other Windows -> Device Log.
  • In the top left where it says 'choose device' choose your device connected by usb.
  • Start logging if it aint already.
  • Go to the notification hub or firebase or wherever it is you are sending the push messages from, then get ready to send.
  • Quickly clear the log in the device log.
  • Quickly send the notification.
  • Make a note of the millisecond time.
  • After the device log settles down after a few seconds, stop the logger. Copy the logs into notepad++ or something. (Ctrl-A, Ctrl-C)
  • Search for the earliest PACKAGE NAME entry in the log
  • Search for all Warning or Error(usually Warning) entries later than that.

Thank you very much! It's really, REALLY helpful. I immediately found the problem (in my code) and fixed it, and now I have push-notifications even if my app closed.


If somebody interested, I had the following error:

01-16 13:09:57.292 Asus ZB633KL Error 12355 mono-rt [ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidOperationException: You MUST call Xamarin.Forms.Init(); prior to using it. at Xamarin.Forms.Device.get_PlatformServices () [0x00007] in <46a6a42f4aa4494a9a4f56ec3eee8423>:0 at Xamarin.Forms.Device.GetAssemblies () [0x00000] in <46a6a42f4aa4494a9a4f56ec3eee8423>:0 at Xamarin.Forms.DependencyService.Initialize () [0x00021] in <46a6a42f4aa4494a9a4f56ec3eee8423>:0 at Xamarin.Forms.DependencyService.Get[T] (Xamarin.Forms.DependencyFetchTarget fetchTarget) [0x00000] in <46a6a42f4aa4494a9a4f56ec3eee8423>:0 at XamarinAirkey.Droid.MyFirebaseMessagingService.OnMessageReceived (Firebase.Messaging.RemoteMessage remoteMessage) [0x00031] in :0 at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.b__7_1 (System.Object state) [0x00000] in <6de48997d0c0445dbea8d4d83492d8c6>:0 at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context (System.Object state) [0x00007] in <6de48997d0c0445dbea8d4d83492d8c6>:0 at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00071] in <6de48997d0c0445dbea8d4d83492d8c6>:0 at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00000] in <6de48997d0c0445dbea8d4d83492d8c6>:0 at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem () [0x00021] in <6de48997d0c0445dbea8d4d83492d8c6>:0 at System.Threading.ThreadPoolWorkQueue.Dispatch () [0x00074] in <6de48997d0c0445dbea8d4d83492d8c6>:0 at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback () [0x00000] in <6de48997d0c0445dbea8d4d83492d8c6>:0

For some reason (probably I just copied some parts of my code from another class) I used DependencyService in my MyFirebaseMessagingService. It has no sense as I can use Android implementation of my abstraction directly. Also DependencyService can't be called before Xamarin.Forms.Init().

FrankSzendzielarz commented 4 years ago

You are more than welcome, friend. My issue was also related to using a Dependency service to register an abstract context, but I see now the approach can't be implemented that way when Services cannot rely the shared app code exists.

FrankSzendzielarz commented 4 years ago

I would say, on reflection, that this 'bug' is more like a set of confusing circumstances that would have been completely avoided if:

  1. VS allowed to attach to process or had a feature for attaching to services/receivers.
  2. allowed the 'stop debugger' event to optionally avoid force stop
  3. and/or kept the debugger alive when the user swipe stops the app
ch4m0n1x101 commented 3 years ago

For some reason (probably I just copied some parts of my code from another class) I used DependencyService in my MyFirebaseMessagingService. It has no sense as I can use Android implementation of my abstraction directly. Also DependencyService can't be called before Xamarin.Forms.Init().

@Alexander-Alekseev Big thanks for this...just had the same issue. Your post helped me identify.

Guervyl commented 2 years ago

My problem fixed based on this post. Check it out to fix your problems related to push notifications. Even if you are using dependency service you should check if Xamarin.Forms.Forms.IsInitialized before initializing the dependency.

emmaprofemx commented 1 week ago

By the way this is the manifest I use:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="Demo" package="CMSApp.CMSApp" android:installLocation="auto" android:versionCode="2">
  <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
  <application android:label="Mocha" android:icon="@drawable/xamarin_logo">

  </application>

  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
  <uses-permission android:name="android.permission.WAKE_LOCK" />
  <permission android:name="CMSApp.CMSApp.permission.C2D_MESSAGE" android:protectionLevel="signature" />
  <uses-permission android:name="CMSApp.CMSApp.permission.C2D_MESSAGE" />
  <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>

Using you code after last tag aplication , my app now to receive the notification yet its background! :)