user2244705
user2244705

Reputation: 381

Delphi Android Firebase Cloud Messaging : Application crashes on notification receive

I use Delphi Rio 10.3.2. I followed this tutorial : http://docwiki.embarcadero.com/RADStudio/Rio/en/Firebase_Android_Support

So in main form, I added OnServiceConnectionChange, OnReceiveNotificationEvent.

The OnServiceConnectionChange just gives me the device token using logcat.

procedure TfAccueil.OnServiceConnectionChange(Sender: TObject;PushChanges: TPushService.TChanges);
     var
       PushService: TPushService;
       token : string;
       url : string;
     begin
       PushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.GCM);
       if TPushService.TChange.DeviceToken in PushChanges then begin
          token := PushService.DeviceTokenValue[TPushService.TDeviceTokenNames.DeviceToken];
          if FDeviceToken <> token then begin
            FDeviceToken := token;

            fData.Log('#FCM','FireBase Device Token: ' + FDeviceToken);

          end;
       end;
       if (TPushService.TChange.Status in PushChanges) and (PushService.Status = TPushService.TStatus.StartupError) then begin
           fData.Log('#FCM','Error: ' + PushService.StartupError);
       end;
     end;

Once I get the device token, I test notification using Postman (where XXX is the device token):

 {
 "registration_ids" : ["XXX"],
 "data" : {
     "key_1" : "Value for key_1",
     "key_2" : "Value for key_2"
 }
}   

In the OnReceiveNotificationEvent, I get what I sent.

procedure TfAccueil.OnReceiveNotificationEvent(Sender: TObject; const ServiceNotification: TPushServiceNotification);
begin
        fData.Log('#FCM','-----------------------------------------');
        fData.Log('#FCM','DataKey = ' + ServiceNotification.DataKey);
        fData.Log('#FCM','Json = ' + ServiceNotification.Json.ToString);
        fData.Log('#FCM','DataObject = ' + ServiceNotification.DataObject.ToString);
        fData.Log('#FCM','---------------------------------------');
end;

The data received are displayed in logcat, I see values for "key_1" and "key_2".

PostMan displayed right response :

{
    "multicast_id": 1194574639982246633,
    "success": 1,
    "failure": 0,
    "canonical_ids": 0,
    "results": [
        {
            "message_id": "0:1591625227805806%7de42328f9fd7ecd"
        }
    ]
}

However, the application crashes, it stops to respond and I get this in logcat :

06-08 16:01:55.461: I/info(19398): -----------------------------------------
06-08 16:01:55.461: W/System.err(19398): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
06-08 16:01:55.461: I/info(19398): DataKey = fcm
06-08 16:01:55.461: I/info(19398): Json = {"google.delivered_priority":"normal","google.sent_time":"1591624915033","google.ttl":"2419200","google.original_priority":"normal","from":"697029724431","key_1":"Value for key_1","key_2":"Value for key_2","google.message_id":"0:1591624915047510%7de42328f9fd7ecd","google.c.sender.id":"697029724431"}
06-08 16:01:55.461: I/info(19398): DataObject = {"google.delivered_priority":"normal","google.sent_time":"1591624915033","google.ttl":"2419200","google.original_priority":"normal","from":"697029724431","key_1":"Value for key_1","key_2":"Value for key_2","google.message_id":"0:1591624915047510%7de42328f9fd7ecd","google.c.sender.id":"697029724431"}
06-08 16:01:55.461: I/info(19398): ---------------------------------------
06-08 16:01:55.462: W/System.err(19398):    at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6898)
06-08 16:01:55.462: W/System.err(19398):    at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1048)
06-08 16:01:55.462: W/System.err(19398):    at android.view.View.requestLayout(View.java:19785)
06-08 16:01:55.462: W/System.err(19398):    at android.view.View.requestLayout(View.java:19785)
06-08 16:01:55.462: W/System.err(19398):    at android.view.View.requestLayout(View.java:19785)
06-08 16:01:55.462: W/System.err(19398):    at android.view.View.requestLayout(View.java:19785)
06-08 16:01:55.462: W/System.err(19398):    at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:360)
06-08 16:01:55.462: W/System.err(19398):    at android.view.View.setFlags(View.java:11482)
06-08 16:01:55.462: W/System.err(19398):    at android.view.View.setVisibility(View.java:8069)
06-08 16:01:55.462: W/System.err(19398):    at com.embarcadero.rtl.ProxyInterface.dispatchToNative(Native Method)
06-08 16:01:55.462: W/System.err(19398):    at com.embarcadero.rtl.ProxyInterface.invoke(ProxyInterface.java:21)
06-08 16:01:55.462: W/System.err(19398):    at java.lang.reflect.Proxy.invoke(Proxy.java:813)
06-08 16:01:55.462: W/System.err(19398):    at $Proxy8.onNotificationReceived(Unknown Source)
06-08 16:01:55.462: W/System.err(19398):    at com.embarcadero.firebase.messaging.ProxyFirebaseMessagingService.onMessageReceived(ProxyFirebaseMessagingService.java:35)
06-08 16:01:55.462: W/System.err(19398):    at com.google.firebase.messaging.FirebaseMessagingService.zzd(Unknown Source)
06-08 16:01:55.462: W/System.err(19398):    at com.google.firebase.iid.zzc.run(Unknown Source)
06-08 16:01:55.462: W/System.err(19398):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
06-08 16:01:55.463: W/System.err(19398):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
06-08 16:01:55.463: W/System.err(19398):    at com.google.android.gms.common.util.concurrent.zza.run(Unknown Source)
06-08 16:01:55.463: W/System.err(19398):    at java.lang.Thread.run(Thread.java:761)
06-08 16:01:55.478: W/System.err(19398): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
06-08 16:01:55.478: W/System.err(19398):    at android.os.Handler.<init>(Handler.java:200)
06-08 16:01:55.478: W/System.err(19398):    at android.os.Handler.<init>(Handler.java:114)
06-08 16:01:55.478: W/System.err(19398):    at android.view.SurfaceView$1.<init>(SurfaceView.java:131)
06-08 16:01:55.478: W/System.err(19398):    at android.view.SurfaceView.<init>(SurfaceView.java:131)
06-08 16:01:55.478: W/System.err(19398):    at android.view.SurfaceView.<init>(SurfaceView.java:207)
06-08 16:01:55.478: W/System.err(19398):    at android.view.SurfaceView.<init>(SurfaceView.java:203)
06-08 16:01:55.478: W/System.err(19398):    at android.view.SurfaceView.<init>(SurfaceView.java:199)
06-08 16:01:55.478: W/System.err(19398):    at com.embarcadero.firemonkey.form.FormView.<init>(FormView.java:16)
06-08 16:01:55.478: W/System.err(19398):    at com.embarcadero.rtl.ProxyInterface.dispatchToNative(Native Method)
06-08 16:01:55.478: W/System.err(19398):    at com.embarcadero.rtl.ProxyInterface.invoke(ProxyInterface.java:21)
06-08 16:01:55.479: W/System.err(19398):    at java.lang.reflect.Proxy.invoke(Proxy.java:813)
06-08 16:01:55.479: W/System.err(19398):    at $Proxy8.onNotificationReceived(Unknown Source)
06-08 16:01:55.479: W/System.err(19398):    at com.embarcadero.firebase.messaging.ProxyFirebaseMessagingService.onMessageReceived(ProxyFirebaseMessagingService.java:35)
06-08 16:01:55.479: W/System.err(19398):    at com.google.firebase.messaging.FirebaseMessagingService.zzd(Unknown Source)
06-08 16:01:55.479: W/System.err(19398):    at com.google.firebase.iid.zzc.run(Unknown Source)
06-08 16:01:55.479: W/System.err(19398):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
06-08 16:01:55.479: W/System.err(19398):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
06-08 16:01:55.479: W/System.err(19398):    at com.google.android.gms.common.util.concurrent.zza.run(Unknown Source)
06-08 16:01:55.479: W/System.err(19398):    at java.lang.Thread.run(Thread.java:761)

The key is here : W/System.err(19398): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views

But I can't figure out what is wrong... what I missed ? I don't even make any UI update.

Note I also tried to remove all code in OnReceiveNotificationEvent, that is all lines with "fData.Log(...)" but I get same result, same logcat (without my data log of course).

Upvotes: 2

Views: 1533

Answers (1)

user2244705
user2244705

Reputation: 381

After some research, the issue was caused by another procedure listening to notifications from another application and making some UI update, which explains why application complains about a thread trying to "touch" the view.


procedure TfData.HandleActivityMessage(const Sender: TObject; const M: TMessage);
begin
    if M is TMessageReceivedNotification then begin
        HandleIntentAction(TMessageReceivedNotification(M).Value);
    end;
end;

function TfData.HandleIntentAction(const Data: JIntent): Boolean; var bc : string; begin Result := False; if Data <> nil then begin if Data.hasExtra(StringToJString(bcDatawedgeData)) then begin //---> I ADDED THIS TEST bc := JStringToString(Data.getStringExtra(StringToJString(bcDatawedgeData))); result := true; bcScan(bc); end; end; end;

The Push Notification also triggers this code. So I added the test (Data.hasExtra(StringToJString(bcDatawedgeData))) to be sure to not execute code in case of push notification.

This solves the problem.

Upvotes: 1

Related Questions