Reputation: 381
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
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