Jump to content
krucifix

Android payment terminal

Recommended Posts

 

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

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 by mjustin

Share this post


Link to post

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
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
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
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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×