krucifix 0 Posted February 13, 2023 I'm developing POS app which will be used on A920 payment terminal. Vendor supplied jar file and I used java2op and generated bridge file. Documentation have android example public static final String AIDL_ACTION = "rs.asoft.asoftposandroid.util.service.AIDL"; public static final String AIDL_PACKAGE = "rs.asoft.asoftposandroid"; private IAsoftPOS common; private ServiceConnection serviceConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { common = IAsoftPOS.Stub.asInterface(service); Log.d("ServiceConnection", "Successful connection"); } @Override public void onServiceDisconnected(ComponentName name) { Log.d("ServiceConnection", "The connection has been lost"); } }; //The implicit Intent must be converted to the explicit: private Intent convertImplicitIntentToExplicitIntent(Intent implicitIntent) { PackageManager pm = getPackageManager(); List<ResolveInfo> resolveInfoList = pm.queryIntentServices(implicitIntent, 0); if (resolveInfoList == null || resolveInfoList.size() != 1) return null; ResolveInfo serviceInfo = resolveInfoList.get(0); ComponentName componen = new ComponentName(serviceInfo.serviceInfo.packageName, serviceInfo.serviceInfo.name); Intent exlicitIntent = new Intent(implicitIntent); exlicitIntent.setComponent(componen); return exlicitIntent; } //Connecting: Intent intent = new Intent(IAsoftPOS.class.getName()); intent.setAction(AIDL_ACTION); intent.setPackage(AIDL_PACKAGE); bindService(convertImplicitIntentToExplicitIntent(intent), serviceConn, BIND_AUTO_CREATE); //Calling method messageExchange: byte[] response = common.messageExchange(tlvCommand); As total noob with this, I managed to convert to delphi function ConvertImplicitIntentToExplicitIntent(implicitIntent: JIntent): JIntent; var PM: JPackageManager; ResolveInfoList: JList; ServiceInfo: JResolveInfo; Componen: JComponentName; ExplicitIntent: JIntent; begin PM := TAndroidHelper.Context.getPackageManager; ResolveInfoList := PM.queryIntentServices(implicitIntent, 0); if (ResolveInfoList = nil) or (ResolveInfoList.size <> 1) then Exit(nil); ServiceInfo := TJavaObjectArray<JResolveInfo>.Wrap((ResolveInfoList as ILocalObject).GetObjectID).Items[0]; Componen := TJComponentName.JavaClass.init(ServiceInfo.ServiceInfo.packageName, ServiceInfo.ServiceInfo.name); ExplicitIntent := TJIntent.JavaClass.init(implicitIntent); ExplicitIntent.setComponent(Componen); Result := ExplicitIntent; end; And I'm stuck with ServiceConnection as I need to assign OnServiceConnected. var Common: JIAsoftPOS; ServiceConnection: JServiceConnection; procedure TfmPostTest.Button1Click(Sender: TObject); Var Intent: JIntent; Response: TJavaArray<Byte>; sendCommand: string; i: Integer; begin Intent := TJIntent.Create; Intent.setAction(StringToJString(AIDL_ACTION)); Intent.setPackage(StringToJString(AIDL_PACKAGE)); TAndroidHelper.Context.bindService(ConvertImplicitIntentToExplicitIntent(Intent), ServiceConnection, TJContext.JavaClass.BIND_AUTO_CREATE); Response := Common.messageExchange(StringToJA(IspisiracunTest)); if Response <> nil then for i := 0 to Response.length - 1 do sendCommand := sendCommand + IntToHex(Response[i]); showMessage(sendCommand); end; Si If anyone can look at it, greatly appreciated. I'm prepared to pay for the services as I'm on very tight schedule. Boris A920.zip Share this post Link to post
mjustin 23 Posted February 13, 2023 (edited) android.content.ServiceConnection is an interface (see https://developer.android.com/reference/android/content/ServiceConnection) Your code must (aquire or) create an instance of a class which implements this interface. If you create it in your code, you must at least implement the two non-default methods, as shown in your Java example.. type TMyServiceConnection = class (TInterfacedObject, JServiceConnection) public procedure onServiceConnected(JComponentName name, JIBinder service); procedure onServiceDisconnected(JComponentName name); ... Edited February 13, 2023 by mjustin Share this post Link to post
krucifix 0 Posted February 13, 2023 Tx mjustin. Created classes and that part is working now. Now getting EJNIFatal with message 'Fatal error invoking interface' at TAndroidHelper.Context.bindService(ConvertImplicitIntentToExplicitIntent(Intent), ServiceConnection, TJContext.JavaClass.BIND_AUTO_CREATE); Investigating... Share this post Link to post
Dave Nottage 557 Posted February 13, 2023 1 hour ago, krucifix said: Now getting EJNIFatal with message 'Fatal error invoking interface' at Might help to show your code for whatever implements JServiceConnection. Share this post Link to post
krucifix 0 Posted February 13, 2023 type TMyServiceConnection = class(TInterfacedObject, JServiceConnection) public procedure onServiceConnected(componentName: JComponentName; Binder: JIBinder)cdecl; procedure onServiceDisconnected(componentName: JComponentName)cdecl; procedure onBindingDied(componentName: JComponentName)cdecl; end; type TfmPostTest = class(TForm) Header: TToolBar; Footer: TToolBar; HeaderLabel: TLabel; Button1: TButton; procedure Button1Click(Sender: TObject); private function IspisiracunTest: string; { Private declarations } public { Public declarations } end; const AIDL_ACTION = 'rs.asoft.asoftposandroid.util.service.AIDL'; AIDL_PACKAGE = 'rs.asoft.asoftposandroid'; DynamicReportprint = '114'; var Common: JIAsoftPOS; ServiceConnection: TMyServiceConnection; var fmPostTest: TfmPostTest; implementation uses ASoftPosPrinter; procedure TMyServiceConnection.onServiceConnected(componentName: JComponentName; Binder: JIBinder); begin Common := TJIAsoftPOS.Wrap((ServiceConnection as ILocalObject).GetObjectID); end; procedure TMyServiceConnection.onServiceDisconnected(componentName: JComponentName); begin end; procedure TMyServiceConnection.onBindingDied(componentName: JComponentName); begin end; {$R *.fmx} function StringToJA(Data: String; charset: String = ''): TJavaArray<Byte>; var Encoding: TEncoding; Arr: TBytes; len: Integer; begin if charset <> '' then Encoding := TEncoding.GetEncoding(charset) else Encoding := TEncoding.Default; Arr := Encoding.GetBytes(Data); len := length(Arr); Result := TJavaArray<Byte>.Create(len); if len > 0 then Move(Arr[0], Result.Data^, len); end; procedure TfmPostTest.Button1Click(Sender: TObject); Var Intent: JIntent; Response: TJavaArray<Byte>; sendCommand: string; i: Integer; ExplicitIntent: JIntent; begin Intent := TJIntent.Create; ServiceConnection := TMyServiceConnection.Create(); try Intent.setAction(StringToJString(AIDL_ACTION)); Intent.setPackage(StringToJString(AIDL_PACKAGE)); ExplicitIntent := TAndroidHelper.Context.getPackageManager.getLaunchIntentForPackage(StringToJString(AIDL_PACKAGE)); if ExplicitIntent <> nil then begin ExplicitIntent.setAction(StringToJString(AIDL_ACTION)); // ExplicitIntent.setPackage(StringToJString(AIDL_PACKAGE)); ?? hm ExplicitIntent.setData(Intent.getData); TAndroidHelper.Context.bindService(ExplicitIntent, ServiceConnection, TJContext.JavaClass.BIND_AUTO_CREATE); TAndroidHelper.Context.startActivity(ExplicitIntent); Response := Common.messageExchange(StringToJA(IspisiracunTest)); if Response <> nil then for i := 0 to Response.length - 1 do sendCommand := sendCommand + IntToHex(Response[i]); ShowMessage(sendCommand); end; finally ServiceConnection.Free; end; end; Tx for looking Share this post Link to post
Dave Nottage 557 Posted February 13, 2023 27 minutes ago, krucifix said: Common := TJIAsoftPOS.Wrap((ServiceConnection as ILocalObject).GetObjectID); This code is not going to work. I suggest looking at the code for TLocalServiceConnection.TJavaServiceConnection.onServiceConnected in the System.Android.Service unit in the Delphi source code. Warning: it's not for the faint of heart 🙂 Share this post Link to post
krucifix 0 Posted February 13, 2023 Knew it will be simple...... Task for tomorrow... Share this post Link to post