Pedro Franco
Pedro Franco

Reputation: 2006

Android not receiving PushNotification when App is "closed"

I'm using GCM Service for push notification, it's working fine when App is open or in backgourd, but when app is closed it's Crashing:

enter image description here

Exception:

FATAL EXCEPTION: main Process: br.com.siagri.SiagriAutorize, PID: 15786 android.runtime.JavaProxyThrowable: System.NotSupportedException: Could not activate JNI Handle 0xbeed8498 (key_handle 0xa7376b4) of Java type 'md5d8b390bb35897e87a51d1b4384dffa30/GcmService' as managed type 'SiagriAuth.Droid.Services.GcmService'. ---> System.InvalidOperationException: You MUST call Xamarin.Forms.Init(); prior to using it.

I have followed this tutorial and taked a look at this sample but i dont saw any about/diferent for notification works when the app is closed.

This is my method to recive and process the notification:

 private void CreateNotification(string title, string desc, string approvalCode)
        {
            try
            {
                //Create notification
                var notificationManager = GetSystemService(NotificationService) as NotificationManager;

                //Create an intent to show ui
                var uiIntent = new Intent(this, typeof(MainActivity));

                //Use Notification Builder
                var builder = new NotificationCompat.Builder(this);

                //Create the notification
                //we use the pending intent, passing our ui intent over which will get called
                //when the notification is tapped.
                var notification = builder.SetContentIntent(PendingIntent.GetActivity(this, 0, uiIntent, 0))
                        .SetSmallIcon(Resource.Drawable.icon)
                        .SetTicker(title)
                        .SetContentTitle(title)
                        .SetContentText(desc)
                        .SetPriority((int)NotificationPriority.High)
                        .SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate)
                        //Set the notification sound
                        .SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Notification))
                        //Auto cancel will remove the notification once the user touches it
                        .SetAutoCancel(true).Build();
                //Show the notification

                int uniqueIdentifier = 0;
                for (int i = 0; i < approvalCode.Length; i++)
                {
                    uniqueIdentifier += (int)approvalCode[i];
                }
                notificationManager?.Notify(uniqueIdentifier, notification);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e);
                App.LocalAlert("Erro", "Erro ao criar notificação.");
            }
        }

        protected override void OnMessage(Context context, Intent intent)
        {
            try
            {
                if (intent != null && intent.Extras != null)
                {
                    var messageText = intent.Extras.GetString("message");
                    var approvalCode = intent.Extras.GetString("ApprovalCode");
                    if (!string.IsNullOrEmpty(messageText) && !string.IsNullOrEmpty(approvalCode))
                        CreateNotification($"Solicitação - {approvalCode}", messageText, approvalCode);
                }
            }
            catch (Exception e)
            {
                Debug.WriteLine(e);
                App.LocalAlert("Erro", "Erro ao criar notificação.");
            }
        }

I'm using these assembly:

[assembly: Permission(Name = "myProject.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "myProject.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")]
[assembly: UsesPermission(Name = "android.permission.INTERNET")]
[assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")]
[assembly: UsesPermission(Name = "android.permission.GET_ACCOUNTS")]

And these IntentFilter:

 [BroadcastReceiver(Permission = Constants.PERMISSION_GCM_INTENTS)]
    [IntentFilter(new[] { Constants.INTENT_FROM_GCM_MESSAGE }, Categories = new[] { "br.com.siagri.SiagriAutorize" })]
    [IntentFilter(new[] { Constants.INTENT_FROM_GCM_REGISTRATION_CALLBACK }, Categories = new[] { "br.com.siagri.SiagriAutorize" })]
    [IntentFilter(new[] { Constants.INTENT_FROM_GCM_LIBRARY_RETRY }, Categories = new[] { "br.com.siagri.SiagriAutorize" })]

Any idea of how to make this works for closed apps?

Obs.: I'm already running the app in release mode.

Upvotes: 4

Views: 231

Answers (1)

Pedro Franco
Pedro Franco

Reputation: 2006

My error was in the construct of GcmService, i was instantiating my repository there, so i was trying to access the database, i just remove from constructor and put on my registered method, that was where i used it.

 public GcmService() : base(PushHandlerBroadcastReceiver.SenderIds)
    {
        Log.Info(PushHandlerBroadcastReceiver.Tag, "PushHandlerService() constructor");
        _permissaoRepository = new PermissaoRepository(App.SiagriAuthContext);
        _loginRepository = new LoginRepository(App.SiagriAuthContext);
    }

I changed to:

public GcmService() : base(PushHandlerBroadcastReceiver.SenderIds)
    {
        Log.Info(PushHandlerBroadcastReceiver.Tag, "PushHandlerService() constructor");
    }

So i can't access my database when the app is closed, this is quite reasonable. I have make a quick search of try to use database when app is closed but i dont found, but here and here have something about use local database.

Upvotes: 2

Related Questions