Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)


This question is answered. Helpful answers available: 0. Correct answers available: 1.


Permlink Replies: 30 - Last Post: May 11, 2016 11:55 AM Last Post By: Markus Humm
Oliver Hager

Posts: 37
Registered: 8/13/10
Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 5, 2016 11:15 AM
Hi

I am trying to use a Honeywell SDK in Delphi Seattle to control a scanner on an Android device.

Honeywell provided me with a SDK jar called DataCollection.jar. I used the Java2OP utility to create my JNI bridge but am having trouble with it. To be honest I am a novice on this and am not sure where to look or how to implement this. I have searched for similar examples too.

I know I have to create an object of type TJAidmanager to access the barcode reader functions , it is defined as :

JAidcManagerClass = interface(JObjectClass)
['{EE70EF80-4CA8-4FE0-B912-6453CA0336CD}']
{class} function _GetBARCODE_DEVICE_CONNECTED: Integer; cdecl;
{class} function _GetBARCODE_DEVICE_DISCONNECTED: Integer; cdecl;
{class} procedure addBarcodeDeviceListener(P1:      JAidcManager_BarcodeDeviceListener); cdecl;
{class} procedure close; cdecl;
{class} procedure create(P1: JContext; P2: JAidcManager_CreatedCallback);    cdecl;
{class} function createBarcodeReader: JBarcodeReader; cdecl; overload;
{class} function createBarcodeReader(P1: JString): JBarcodeReader; cdecl;     overload;
{class} function listBarcodeDevices: JList; cdecl;
{class} function listConnectedBarcodeDevices: JList; cdecl;
{class} procedure removeBarcodeDeviceListener(P1:    JAidcManager_BarcodeDeviceListener); cdecl;
{class} property BARCODE_DEVICE_CONNECTED: Integer read     _GetBARCODE_DEVICE_CONNECTED;
{class} property BARCODE_DEVICE_DISCONNECTED: Integer read   _GetBARCODE_DEVICE_DISCONNECTED;
end;
 
[JavaSignature('com/honeywell/aidc/AidcManager')]
JAidcManager = interface(JObject)
['{98A668C5-9204-4F0C-98B0-A8E1F1124738}']
end;
TJAidcManager = class(TJavaGenericImport<JAidcManagerClass, JAidcManager>)    end;


The java sample code looks like this :

import com.honeywell.aidc.*;
public class MainActivity extends Activity {
private AidcManager manager;
private BarcodeReader reader;
 
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
 
// create the AidcManager providing a Context and an
// CreatedCallback implementation.
AidcManager.create(this, new AidcManager.CreatedCallback() {
 
@Override
public void onCreated(AidcManager aidcManager) {
manager = aidcManager;
reader = manager.createBarcodeReader();
}
}
}
 
@Override
public void onDestroy() {
super.onDestroy();
// make sure that AidcManager isn't null
if (reader != null) {
// close BarcodeReader to clean up resources.
// once closed, the object can no longer be used.
reader.close();
}
if (manager != null) {
// close AidcManager to disconnect from the scanner service.
// once closed, the object can no longer be used.
manager.close();
}
}
}


Now when I try and use this in delphi , I have tried this but get a segmentation fault :

var cb : JAidcManager_CreatedCallback;
begin
      TJAidcManager.JavaClass.create(SharedActivity,TJAidcManager_CreatedCallback.Wrap((cb as ILocalObject).getobjectID));


The JAidcManager_CreatedCallback is defined as :

 JAidcManager_CreatedCallbackClass = interface(IJavaClass)
    ['{E27EF6BB-C642-42B6-98CA-6C270A1AD5D1}']
    {class} procedure onCreated(P1: JAidcManager); cdecl;//Deprecated
  end;
 
  [JavaSignature('com/honeywell/aidc/AidcManager$CreatedCallback')]
  JAidcManager_CreatedCallback = interface(IJavaInstance)
    ['{E2713D70-1CE6-43AA-9181-7054BD787F1B}']
  end;
  TJAidcManager_CreatedCallback =   class(TJavaGenericImport<JAidcManager_CreatedCallbackClass,   JAidcManager_CreatedCallback>) end;


I assume I have to implement an onCreated Event for a variable of type TJAidcManager but I am not sure how to link these all together.

I then tried this :

var   cb : JObject;
begin
  cb := TjObject.Create;
  TJAidcManager.JavaClass.create(SharedActivityContext,TJAidcManager_CreatedCallback.Wrap((cb as ILocalObject).getobjectID));


I also added this to the JNIBridge Unit in the implementation section :

procedure onCreated(P1: JAidcManager); cdecl;//Deprecated
begin
   Form2.manager := P1;
end;


When running this, I get a
java.lang.SecurityException: Not allowed to start service Intent

error. I tried adding "Bind Remoteviews" to permissions but that didn't help.

If anyone could advise me or point me in the correct direction on how to create the AidcManager in Delphi, that would be appreciated.

Edited by: Oliver Hager on Apr 7, 2016 4:25 AM
Cristian Peța

Posts: 157
Registered: 8/7/06
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)
Helpful
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 6, 2016 4:09 AM   in response to: Oliver Hager in response to: Oliver Hager
Oliver Hager wrote:
Honeywell provided me with a SDK jar called DataCollection.jar. I used the Java2OP utility to create my JNI bridge but am having trouble with it. To be honest I am a novice on this and am not sure where to look or how to implement this. I have searched for similar examples too.
This sounds like 75e (70e was an other beast)
AidcManager.create(this, new AidcManager.CreatedCallback() {
Because this "this" I sub-classed com.embarcadero.firemonkey.FMXNativeActivity because I have not managed to do it in other way.
But now I can't debug from the IDE because IDE will try to start FMXNativeActivity and not my sub-classed one.

And I used Java code example provided by Honeywell and modified it slightly so I can link it from my Delphi code.
There is somewhere in this forum my example for 70e.
My code now works for both 70e and 75e so it's harder to read. You need to look for comments "for 75e"
This is the Java code. It can be cleaner but it was not time for this.
package com.winarhi.nativeactivitysubclass;
 
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.os.Bundle;
import android.content.Intent;
import android.widget.Toast;
 
import java.io.IOException;
 
import com.honeywell.decodemanager.DecodeManager;
import com.honeywell.decodemanager.barcode.DecodeResult;
 
import com.honeywell.decodemanager.SymbologyConfigs;
import com.honeywell.decodemanager.barcode.CommonDefine;
import com.honeywell.decodemanager.symbologyconfig.SymbologyConfigCodeDataMatrix;
 
//for 75e
import com.honeywell.aidc.*;
 
public class NativeActivitySubclass extends com.embarcadero.firemonkey.FMXNativeActivity implements BarcodeReader.BarcodeListener,
    BarcodeReader.TriggerListener {
 
    //private final int ID_SCANSETTING = 0x12;
    //private final int ID_CLEAR_SCREEN = 0x13;
 
    static final String TAG = "NativeActivitySubclass";
    private DecodeManager mDecodeManager = null;
    public String strDecodeResult = "";
    private final int WA_SCANTIMEOUT = 5000;
    long WA_mScanAccount = 0;
    private NativeActivitySubclass selfActivity;
 
    //for 75e
    private com.honeywell.aidc.BarcodeReader H75e_barcodeReader = null;
    private AidcManager H75e_manager = null;
 
    //introduced for XE7
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //Custom initialization
        Log.d(TAG, "onCreate");
 
        selfActivity = this;
    }
 
    private void WA_CreateDecodeManager() {
        if (mDecodeManager == null)
            mDecodeManager = new DecodeManager(this, ScanResultHandler);
    }
 
    private void WA_DestroyDecodeManager() {
        if (mDecodeManager != null) {
            try {
                mDecodeManager.release();
                mDecodeManager = null;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
 
    //for 75e
    private void WA_75e_DoScan() throws Exception {
        if (H75e_manager != null) {
            strDecodeResult = "";
        }
    }
 
    //for 75e
    private void WA_75e_Create_aidcManager() {
        // create the AidcManager providing a Context and a
        // CreatedCallback implementation.
        if (H75e_manager == null)
          AidcManager.create(this, new AidcManager.CreatedCallback() {
              @Override
              public void onCreated(AidcManager aidcManager) {
                  H75e_manager = aidcManager;
                  H75e_barcodeReader = H75e_manager.createBarcodeReader();
 
                  // register bar code event listener
                  H75e_barcodeReader.addBarcodeListener(selfActivity);
 
                  // set the trigger mode to client control
                  try {
                        H75e_barcodeReader.setProperty(BarcodeReader.PROPERTY_TRIGGER_CONTROL_MODE,
                                BarcodeReader.TRIGGER_CONTROL_MODE_AUTO_CONTROL);
                  } catch (UnsupportedPropertyException e) {
                        Toast.makeText(selfActivity, "Failed to apply properties", Toast.LENGTH_SHORT).show();
                  }
                  // register trigger state change listener
                  H75e_barcodeReader.addTriggerListener(selfActivity);
 
                  try {
                      H75e_barcodeReader.claim();
                  } catch (ScannerUnavailableException e) {
                      e.printStackTrace();
                      Toast.makeText(selfActivity, "Scanner unavailable", Toast.LENGTH_SHORT).show();
                  }
              }
          });
    }
 
    //for 75e
    private void WA_75e_Destroy_aidcManager() {
        if (H75e_barcodeReader != null) {
            // unregister barcode event listener
            H75e_barcodeReader.removeBarcodeListener(this);
 
            // unregister trigger state change listener
            H75e_barcodeReader.removeTriggerListener(this);
 
            // close BarcodeReader to clean up resources.
            H75e_barcodeReader.close();
            H75e_barcodeReader = null;
        }
 
        if (H75e_manager != null) {
            // close AidcManager to disconnect from the scanner service.
            // once closed, the object can no longer be used.
            H75e_manager.close();
            H75e_manager = null;
        }
    }
 
    //for 75e BarcodeReader.BarcodeListener.onBarcodeEvent
    @Override
    public void onBarcodeEvent(final BarcodeReadEvent event) {
        onBarCodeCompleteNative(event.getBarcodeData());
    }
 
    //for 75e BarcodeReader.BarcodeListener.onFailureEvent
    @Override
    public void onFailureEvent(BarcodeFailureEvent arg0) {
        // TODO Auto-generated method stub
        Toast.makeText(this, "BarcodeListener.onFailureEvent", Toast.LENGTH_SHORT).show();
 
    }
 
    //for 75e BarcodeReader.BarcodeListener.onResume
    @Override
    public void onResume() {
        super.onResume();
        if (H75e_barcodeReader != null) {
            try {
                H75e_barcodeReader.claim();
            } catch (ScannerUnavailableException e) {
                e.printStackTrace();
                Toast.makeText(this, "Scanner unavailable", Toast.LENGTH_SHORT).show();
            }
        }
    }
 
    //for 75e BarcodeReader.BarcodeListener.onPause
    @Override
    public void onPause() {
        super.onPause();
        if (H75e_barcodeReader != null) {
            // release the scanner claim so we don't get any scanner
            // notifications while paused.
            H75e_barcodeReader.release();
        }
    }
 
    //for 75e BarcodeReader.TriggerListener.onTriggerEvent
    @Override
    public void onTriggerEvent(TriggerStateChangeEvent event) {
        Toast.makeText(this, "TriggerListener.onTriggerEvent", Toast.LENGTH_SHORT).show();
 
    }
 
    private void WA_DoScan() throws Exception {
        if (mDecodeManager != null) {
            try {
                strDecodeResult = "";
                mDecodeManager.doDecode(WA_SCANTIMEOUT);
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
 
    public native void onBarCodeCompleteNative(String BarCode);
    public native void onBarCodeFailNative();
 
    private Handler ScanResultHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case DecodeManager.MESSAGE_DECODER_COMPLETE:
                    WA_mScanAccount++;
                    DecodeResult decodeResult = (DecodeResult) msg.obj;
 
                    //byte codeid = decodeResult.codeId;
                    //byte aimid = decodeResult.aimId;
                    //int iLength = decodeResult.length;
 
                    strDecodeResult = decodeResult.barcodeData;
                    onBarCodeCompleteNative(strDecodeResult);
                    break;
 
                case DecodeManager.MESSAGE_DECODER_FAIL: {
                    strDecodeResult = "";
                    onBarCodeFailNative();
                }
                break;
                case DecodeManager.MESSAGE_DECODER_READY:
                {
                    try {
                        //mDecodeManager.disableSymbology(CommonDefine.SymbologyID.SYM_ALL);
                        SymbologyConfigCodeDataMatrix DataMatrix = new SymbologyConfigCodeDataMatrix();
                        DataMatrix.enableSymbology(true);
                        SymbologyConfigs symconfig = new SymbologyConfigs();
 
                        symconfig.addSymbologyConfig(DataMatrix);
                        mDecodeManager.setSymbologyConfigs(symconfig);
 
                        mDecodeManager.enableSymbology(CommonDefine.SymbologyID.SYM_DATAMATRIX);
                    } catch (RemoteException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                break;
                default:
                    super.handleMessage(msg);
                    break;
            }
        }
    };
    private void WA_cancelScan() throws Exception {
        mDecodeManager.cancelDecode();
    }
}
Oliver Hager

Posts: 37
Registered: 8/13/10
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 6, 2016 5:48 AM   in response to: Cristian Peța in response to: Cristian Peța
Thank you Christian. Yes, this is a 75e. I am about to throw it against the wall. I expected the wedge mode on the scanner to just populate a TEdit that I could react off, but I had issues where the scanner would work fine until I used the backspace or return key on the virtual keyboard. Thereafter the scanner wouldn't populate the TEdit. Hence the reason why I have gone the SDK route.

Thank you for your code, very much appreciated. I will look through it. I don't quite know how to hook this code up to my Delphi project , but a quick google shows some examples from Brian Long, so will give those a read and try from there.

Thanks again.
Cristian Peța

Posts: 157
Registered: 8/7/06
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)
Helpful
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 6, 2016 6:00 AM   in response to: Oliver Hager in response to: Oliver Hager
This way you call Java functions (here I call WA_75e_Create_aidcManager)
      TJNativeActivitySubclass.Wrap(PANativeActivity(System.DelphiActivity)^.clazz).WA_75e_Create_aidcManager;


And here you define the Delphi interface with Java functions.
uses
//  Androidapi.JNI.JavaTypes
  Androidapi.JNIBridge,
  Androidapi.JNI.App;
 
type
  JNativeActivitySubclass = interface;
 
  JNativeActivitySubclassClass = interface(JActivityClass)
  ['{829C77FB-08F1-4D19-9782-3C58EECAAAAA}']
    {Methods}
    //function init: JFMXNativeActivity; cdecl;
  end;
 
  [JavaSignature('com/winarhi/nativeactivitysubclass/NativeActivitySubclass')]
  JNativeActivitySubclass = interface(JActivity)
  ['{2FA559EC-D1D7-46AA-9C52-FEFC6B3AAAAA}']
    {Methods}
    procedure WA_DoScan;
    procedure WA_CreateDecodeManager;
    procedure WA_DestroyDecodeManager;
 
    procedure WA_75e_DoScan;
    procedure WA_75e_Create_aidcManager;
    procedure WA_75e_Destroy_aidcManager;
  end;
  TJNativeActivitySubclass = class(TJavaGenericImport<JNativeActivitySubclassClass, JNativeActivitySubclass>) end;


You need to modify also manifest file to start your sub-classed activity instead standard FMX.

This is a Delphi procedure that is called from Java:
//This is called from the Java activity's onBarCodeComplete() method
procedure onBarCodeCompleteNative(PEnv: PJNIEnv; This: JNIObject; BarCode: JNIString); cdecl;
begin
  Log.d('+onBarCodeCompleteNative');
  Log.d('Thread (Main: %.8x, Current: %.8x, Java:%.8d (%2:.8x), POSIX:%.8x)',
    [MainThreadID, TThread.CurrentThread.ThreadID, TJThread.JavaClass.currentThread.getId, GetCurrentThreadID]);
  ARNBarCode := JNIStringToString(PEnv, BarCode);
  Log.d('Calling Synchronize');
  TThread.Synchronize(nil, onBarCodeCompleteThreadSwitcher);
  Log.d('Synchronize is over');
  Log.d('-onBarCodeCompleteNative');
end;


And here is code to register your Delphi procedures to be called from Java:
procedure TMainForm.RegisterDelphiNativeMethods;
var
  PEnv: PJNIEnv;
  ActivityClass: JNIClass;
  NativeMethods: array[0..1] of JNINativeMethod;
begin
  Log.d('Starting the registration JNI stuff');
 
  PEnv := TJNIResolver.GetJNIEnv;
 
  Log.d('Registering interop methods');
 
  NativeMethods[0].Name := 'onBarCodeCompleteNative';
  NativeMethods[0].Signature := '(Ljava/lang/String;)V';
  NativeMethods[0].FnPtr := @onBarCodeCompleteNative;
 
  NativeMethods[1].Name := 'onBarCodeFailNative';
  NativeMethods[1].Signature := '()V';
  NativeMethods[1].FnPtr := @onBarCodeFailNative;
 
  ActivityClass := PEnv^.GetObjectClass(PEnv, PANativeActivity(System.DelphiActivity).clazz);
 
  PEnv^.RegisterNatives(PEnv, ActivityClass, @NativeMethods[0], 2);
 
  PEnv^.DeleteLocalRef(PEnv, ActivityClass);
end;
Oliver Hager

Posts: 37
Registered: 8/13/10
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 6, 2016 6:41 AM   in response to: Cristian Peța in response to: Cristian Peța
Thank you again Christian. Hopefully last question, do I need to compile the nativeactivitysubclass using javac.exe into a jar file and include in my classes.dex ?
Cristian Peța

Posts: 157
Registered: 8/7/06
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 6, 2016 7:07 AM   in response to: Oliver Hager in response to: Oliver Hager
Oliver Hager wrote:
Thank you again Christian. Hopefully last question, do I need to compile the nativeactivitysubclass using javac.exe into a jar file and include in my classes.dex ?
You need only to compile your Java code to a .jar file. It will merged by the IDE into classes.dex if you add this .jar file to the Android Libraries of the project. Also you need to add to the Libraries the DataCollection.jar

I use this bath file to compile my Java code (it is adapted after Brian's example).
You can see that I use also honeywell.jar but it is for 70e. I don't think you need it for 75e.
@echo on
 
setlocal
 
set ANDROID="C:\Users\Public\Documents\Embarcadero\Studio\15.0\PlatformSDKs\adt-bundle-windows-x86-20131030\sdk"
set ANDROID_PLATFORM=%ANDROID%\platforms\android-19
set DX_LIB=%ANDROID%\build-tools\android-4.4\lib
set EMBO_LIB="C:\Program Files (x86)\Embarcadero\Studio\15.0\lib\android\debug"
 
set PROJ_DIR=%CD%
set VERBOSE=0
 
echo.
echo Compiling the Java source files
echo.
mkdir output\classes 2> nul
if x%VERBOSE% == x1 SET VERBOSE_FLAG=-verbose
javac %VERBOSE_FLAG% -source 1.6 -target 1.6 -Xlint:deprecation -cp %ANDROID_PLATFORM%\android.jar;%EMBO_LIB%\fmx.jar;libs\honeywell.jar;libs\DataCollection.jar -d output\classes com\winarhi\nativeactivitysubclass\NativeActivitySubclass.java
 
echo.
echo Creating jar containing the new classes
echo.
mkdir output\jar 2> nul
if x%VERBOSE% == x1 SET VERBOSE_FLAG=v
jar c%VERBOSE_FLAG%f output\jar\NativeActivitySubclass.jar -C output\classes com
 
:Exit
 
endlocal
Cristian Peța

Posts: 157
Registered: 8/7/06
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 6, 2016 6:10 AM   in response to: Oliver Hager in response to: Oliver Hager
Oliver Hager wrote:
Thank you for your code, very much appreciated. I will look through it. I don't quite know how to hook this code up to my Delphi project , but a quick google shows some examples from Brian Long, so will give those a read and try from there.
Brian Long was also my source of inspiration.

There is also an QC report created by Brian asking to start default activity defined in manifest file and not the standard FMX activity. This will allow to use debugging after sub-classing FMX activity.
Maybe it would be useful to create an QP with same request.
Markus Humm

Posts: 5,113
Registered: 11/9/03
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 6, 2016 10:09 AM   in response to: Cristian Peța in response to: Cristian Peța
Am 06.04.2016 um 15:10 schrieb Cristian Peta:
Oliver Hager wrote:
Thank you for your code, very much appreciated. I will look through it. I don't quite know how to hook this code up to my Delphi project , but a quick google shows some examples from Brian Long, so will give those a read and try from there.
Brian Long was also my source of inspiration.

There is also an QC report created by Brian asking to start default activity defined in manifest file and not the standard FMX activity. This will allow to use debugging after sub-classing FMX activity.
Maybe it would be useful to create an QP with same request.

Hello,

could you please post the QC number of this one?

Greetings

Markus
Cristian Peța

Posts: 157
Registered: 8/7/06
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 6, 2016 11:05 PM   in response to: Markus Humm in response to: Markus Humm
Markus Humm wrote:
Am 06.04.2016 um 15:10 schrieb Cristian Peta:
Oliver Hager wrote:
Thank you for your code, very much appreciated. I will look through it. I don't quite know how to hook this code up to my Delphi project , but a quick google shows some examples from Brian Long, so will give those a read and try from there.
Brian Long was also my source of inspiration.

There is also an QC report created by Brian asking to start default activity defined in manifest file and not the standard FMX activity. This will allow to use debugging after sub-classing FMX activity.
Maybe it would be useful to create an QP with same request.

Hello,

could you please post the QC number of this one?

Greetings

Markus
Unfortunately it is deeply buried but you should see it because you have a comment there...
QC 118450
http://qc.embarcadero.com/wc/qcmain.aspx?d=118450

For others I post it here:

Description
... is not expecting anyone to change the standard activity.
However my app has had a need to do this. I've subclassed the FMX activity and updated my manifest template to reflect this.
In my manifest template I've replaced:
com.embarcadero.firemonkey.FMXNativeActivity
with:
com.embarcadero.firemonkey.NativeActivitySubclass
But the IDE is not expecting this.
Consequently, when I run the app with F9 or Ctrl+Shift+F9 it will compile, link, deploy, uninstall and install it all correctly (the package name has not been altered outside its expectations).
However the next step the IDE embarks upon is to launch the app. From a command-line this is done rather like:
adb -s %DEVICE_NAME% shell am start -a android.intent.action.MAIN -n %PKG_NAME%/%MAIN_ACTIVITY%
Because I changed the default main activity, when it tries to emit this (or some similar) command it tries to launch the wrong activity. It then sits there endlessly running adb command lines that run a ps command in the device shell looking for the process running, which it won't be thanks to not having started thanks to not having that sought activity advertised in the manifest.
It would be awesome if the IDE read the main activity name (and maybe also, for the sheer completeness of it, the package name) from the manifest template, or indeed from the actual manifest that it generated during the build process.
That way, when the manifest template is updated, as it is intended to be, apps will still launch from the IDE
The main activity element is the <activity> element that contains an <intent-filter> element with an <action> element inside whose android:name attribute has a value of android.intent.action.MAIN. The required activity name is then the value of that activity element's android:name attribute.
The package is the value of the package attribute in the singular <manifest> element.

Steps to Reproduce:
Difficult to give steps
You;d need to write a Java subclass of the main com.embarcadero.firemonkey.FMXNativeActivity and get that into the classes.dex that is deployed with a sample app
You'd then need to update the Android manifest template as described in the Description
Then when you try to launch the app with Ctrl+Shift+F9, the IDE will sit dumbly at the launching stage.
If you launch a process monitor you can see the IDE is repeatedly running commands of this ilk:
adb -s <device_name> shell ps
It never finds the sougfht process as it failed to launch long before

Oliver Hager

Posts: 37
Registered: 8/13/10
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 6, 2016 11:50 PM   in response to: Cristian Peța in response to: Cristian Peța
Cristian Peta wrote:
Oliver Hager wrote:
Thank you for your code, very much appreciated. I will look through it. I don't quite know how to hook this code up to my Delphi project , but a quick google shows some examples from Brian Long, so will give those a read and try from there.
Brian Long was also my source of inspiration.

There is also an QC report created by Brian asking to start default activity defined in manifest file and not the standard FMX activity. This will allow to use debugging after sub-classing FMX activity.
Maybe it would be useful to create an QP with same request.

Thanks Christian. I see what you mean, Delphi just shows launching activity and doesn't do anything further. I followed your steps and compiled the jar for the subclassed native activity etc, but when I started the app on the device, I immediately got "Application has stopped working". I check the device log and see "thread exiting with uncaught exception".I thought maybe the code for the 70e was causing the exception ,so I have removed it from the java file and recompiled. Seems to open the project now so let me see if I can get the scanner working.

Edited by: Oliver Hager on Apr 7, 2016 12:26 AM
Oliver Hager

Posts: 37
Registered: 8/13/10
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 7, 2016 2:50 AM   in response to: Oliver Hager in response to: Oliver Hager
Oliver Hager wrote:
Cristian Peta wrote:
Oliver Hager wrote:
Thank you for your code, very much appreciated. I will look through it. I don't quite know how to hook this code up to my Delphi project , but a quick google shows some examples from Brian Long, so will give those a read and try from there.
Brian Long was also my source of inspiration.

There is also an QC report created by Brian asking to start default activity defined in manifest file and not the standard FMX activity. This will allow to use debugging after sub-classing FMX activity.
Maybe it would be useful to create an QP with same request.

Thanks Christian. I see what you mean, Delphi just shows launching activity and doesn't do anything further. I followed your steps and compiled the jar for the subclassed native activity etc, but when I started the app on the device, I immediately got "Application has stopped working". I check the device log and see "thread exiting with uncaught exception".I thought maybe the code for the 70e was causing the exception ,so I have removed it from the java file and recompiled. Seems to open the project now so let me see if I can get the scanner working.

Edited by: Oliver Hager on Apr 7, 2016 12:26 AM

Hi Christian

So I have compiled everything and the app runs but it doesn't react to a barcode being scanned.

This is my MainForm Unit :

unit frmMain;
 
interface
 
uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, Androidapi.JNIBridge,
  Androidapi.JNI.App,Androidapi.Jni,Androidapi.JNI.JavaTypes,
  FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo, FMX.StdCtrls;
 
type
  JNativeActivitySubclass = interface;
 
  JNativeActivitySubclassClass = interface(JActivityClass)
  ['{829C77FB-08F1-4D19-9782-3C58EECAAAAA}']
    {Methods}
    //function init: JFMXNativeActivity; cdecl;
  end;
 
  [JavaSignature('com/winarhi/nativeactivitysubclass/NativeActivitySubclass')]
  JNativeActivitySubclass = interface(JActivity)
  ['{2FA559EC-D1D7-46AA-9C52-FEFC6B3AAAAA}']
    {Methods}
    procedure WA_75e_DoScan;
    procedure WA_75e_Create_aidcManager;
    procedure WA_75e_Destroy_aidcManager;
  end;
  TJNativeActivitySubclass = class(TJavaGenericImport<JNativeActivitySubclassClass, JNativeActivitySubclass>) end;
 
  TMainForm = class(TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    ARNBarCode : string;
    procedure RegisterDelphiNativeMethods;
    procedure onBarCodeCompleteThreadSwitcher;
    procedure onBarCodeFailThreadSwitcher;
 
    { Public declarations }
  end;
 
var
  MainForm: TMainForm;
 
implementation
 
uses
  FMX.Helpers.Android,
  Androidapi.NativeActivity;
 
 
{$R *.fmx}
 
//This is called from the Java activity's onBarCodeComplete() method
procedure TMainForm.FormCreate(Sender: TObject);
begin
RegisterDelphiNativeMethods;
end;
 
procedure TMainForm.onBarCodeCompleteThreadSwitcher;
begin
  memo1.Lines.Add(ARNBarCode);
end;
 
procedure TMainForm.onBarCodeFailThreadSwitcher;
begin
   memo1.Lines.Add('Barcode Scan Failed ' + ARNBarCode);
end;
 
procedure onBarCodeCompleteNative(PEnv: PJNIEnv; This: JNIObject; BarCode: JNIString); cdecl;
begin
  Log.d('+onBarCodeCompleteNative');
  Log.d('Thread (Main: %.8x, Current: %.8x, Java:%.8d (%2:.8x), POSIX:%.8x)',
    [MainThreadID, TThread.CurrentThread.ThreadID, TJThread.JavaClass.currentThread.getId]);
  MainForm.ARNBarCode := JNIStringToString(PEnv, BarCode);
  Log.d('Calling Synchronize');
  TThread.Synchronize(nil, Mainform.onBarCodeCompleteThreadSwitcher);
  Log.d('Synchronize is over');
  Log.d('-onBarCodeCompleteNative');
end;
 
 
 
procedure onBarCodeFailNative(PEnv: PJNIEnv; This: JNIObject; BarCode: JNIString); cdecl;
begin
  Log.d('+onBarCodeCompleteNative');
  Log.d('Thread (Main: %.8x, Current: %.8x, Java:%.8d (%2:.8x), POSIX:%.8x)',
    [MainThreadID, TThread.CurrentThread.ThreadID, TJThread.JavaClass.currentThread.getId]);
  MainForm.ARNBarCode := JNIStringToString(PEnv, BarCode);
  Log.d('Calling Synchronize');
  TThread.Synchronize(nil, Mainform.onBarCodeFailThreadSwitcher);
  Log.d('Synchronize is over');
  Log.d('-onBarCodeCompleteNative');
end;
 
procedure TMainForm.RegisterDelphiNativeMethods;
var
  PEnv: PJNIEnv;
  ActivityClass: JNIClass;
  NativeMethods: array[0..1] of JNINativeMethod;
begin
  Log.d('Starting the registration JNI stuff');
 
  PEnv := TJNIResolver.GetJNIEnv;
 
  Log.d('Registering interop methods');
 
  NativeMethods[0].Name := 'onBarCodeCompleteNative';
  NativeMethods[0].Signature := '(Ljava/lang/String;)V';
  NativeMethods[0].FnPtr := @onBarCodeCompleteNative;
 
  NativeMethods[1].Name := 'onBarCodeFailNative';
  NativeMethods[1].Signature := '()V';
  NativeMethods[1].FnPtr := @onBarCodeFailNative;
 
  ActivityClass := PEnv^.GetObjectClass(
    PEnv, PANativeActivity(System.DelphiActivity).clazz);
 
  PEnv^.RegisterNatives(PEnv, ActivityClass, @NativeMethods[0], 2);
 
  PEnv^.DeleteLocalRef(PEnv, ActivityClass);
 
  Log.d('Interop Methods Registered');
end;
 
end.
 


And this is the Java file source :


package com.winarhi.nativeactivitysubclass;
 
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.os.Bundle;
import android.content.Intent;
import android.widget.Toast;
 
import java.io.IOException;
 
//for 75e
import com.honeywell.aidc.*;
 
public class NativeActivitySubclass extends com.embarcadero.firemonkey.FMXNativeActivity implements BarcodeReader.BarcodeListener,
    BarcodeReader.TriggerListener {
 
    Log.d(TAG, "NativeActivitySubclass onCreate");
	
    //private final int ID_SCANSETTING = 0x12;
    //private final int ID_CLEAR_SCREEN = 0x13;
 
    static final String TAG = "NativeActivitySubclass";
    public String strDecodeResult = "";
    private final int WA_SCANTIMEOUT = 5000;
    long WA_mScanAccount = 0;
    private NativeActivitySubclass selfActivity;
 
    //for 75e
    private com.honeywell.aidc.BarcodeReader H75e_barcodeReader = null;
    private AidcManager H75e_manager = null;
 
    //introduced for XE7
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //Custom initialization
        Log.d(TAG, "onCreate");
 
        selfActivity = this;
    }
 
    //for 75e
    private void WA_75e_DoScan() throws Exception {
        if (H75e_manager != null) {
            strDecodeResult = "";
        }
    }
 
    //for 75e
    private void WA_75e_Create_aidcManager() {
        // create the AidcManager providing a Context and a
        // CreatedCallback implementation.
        Log.d(TAG, "CReate aidc manager");
        if (H75e_manager == null)
          AidcManager.create(this, new AidcManager.CreatedCallback() {
              @Override
              public void onCreated(AidcManager aidcManager) {
                  H75e_manager = aidcManager;
                  H75e_barcodeReader = H75e_manager.createBarcodeReader();
 
                  // register bar code event listener
                  H75e_barcodeReader.addBarcodeListener(selfActivity);
 
                  // set the trigger mode to client control
                  try {
                        H75e_barcodeReader.setProperty(BarcodeReader.PROPERTY_TRIGGER_CONTROL_MODE,
                                BarcodeReader.TRIGGER_CONTROL_MODE_AUTO_CONTROL);
                  } catch (UnsupportedPropertyException e) {
                        Toast.makeText(selfActivity, "Failed to apply properties", Toast.LENGTH_SHORT).show();
                  }
                  // register trigger state change listener
                  H75e_barcodeReader.addTriggerListener(selfActivity);
 
                  try {
                      H75e_barcodeReader.claim();
                  } catch (ScannerUnavailableException e) {
                      e.printStackTrace();
                      Toast.makeText(selfActivity, "Scanner unavailable", Toast.LENGTH_SHORT).show();
                  }
              }
          });
    }
 
    //for 75e
    private void WA_75e_Destroy_aidcManager() {
        if (H75e_barcodeReader != null) {
            // unregister barcode event listener
            H75e_barcodeReader.removeBarcodeListener(this);
 
            // unregister trigger state change listener
            H75e_barcodeReader.removeTriggerListener(this);
 
            // close BarcodeReader to clean up resources.
            H75e_barcodeReader.close();
            H75e_barcodeReader = null;
        }
 
        if (H75e_manager != null) {
            // close AidcManager to disconnect from the scanner service.
            // once closed, the object can no longer be used.
            H75e_manager.close();
            H75e_manager = null;
        }
    }
 
    //for 75e BarcodeReader.BarcodeListener.onBarcodeEvent
    @Override
    public void onBarcodeEvent(final BarcodeReadEvent event) {
        onBarCodeCompleteNative(event.getBarcodeData());
    }
 
    //for 75e BarcodeReader.BarcodeListener.onFailureEvent
    @Override
    public void onFailureEvent(BarcodeFailureEvent arg0) {
        // TODO Auto-generated method stub
        Toast.makeText(this, "BarcodeListener.onFailureEvent", Toast.LENGTH_SHORT).show();
 
    }
 
    //for 75e BarcodeReader.BarcodeListener.onResume
    @Override
    public void onResume() {
        super.onResume();
        if (H75e_barcodeReader != null) {
            try {
                H75e_barcodeReader.claim();
            } catch (ScannerUnavailableException e) {
                e.printStackTrace();
                Toast.makeText(this, "Scanner unavailable", Toast.LENGTH_SHORT).show();
            }
        }
    }
 
    //for 75e BarcodeReader.BarcodeListener.onPause
    @Override
    public void onPause() {
        super.onPause();
        if (H75e_barcodeReader != null) {
            // release the scanner claim so we don't get any scanner
            // notifications while paused.
            H75e_barcodeReader.release();
        }
    }
 
    //for 75e BarcodeReader.TriggerListener.onTriggerEvent
    @Override
    public void onTriggerEvent(TriggerStateChangeEvent event) {
        Toast.makeText(this, "TriggerListener.onTriggerEvent", Toast.LENGTH_SHORT).show();
 
    }
 
     
    public native void onBarCodeCompleteNative(String BarCode);
    public native void onBarCodeFailNative();
 
    
}
 


And my appmanifest has been updated to :

 <activity android:name="com.winarhi.nativeactivitysubclass.NativeActivitySubclass"


I can see on my device log , the comments from the mainform when registering the interop methods but there is no data in the log from the NativeActivitySubclass so it does not seem to be listening to the onBarcodeEvent. WOuld you have any ideas on this ? Sorry I am asking so many questions on this, you have helped me so much already.

Edited by: Oliver Hager on Apr 7, 2016 4:22 AM
Cristian Peța

Posts: 157
Registered: 8/7/06
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 7, 2016 3:28 AM   in response to: Oliver Hager in response to: Oliver Hager
Oliver Hager wrote:
So I have compiled everything and the app runs but it doesn't react to a barcode being scanned.
It looks you have not triggered the scanner from Delphi.
For this I call:
    TJNativeActivitySubclass.Wrap(PANativeActivity(System.DelphiActivity)^.clazz).WA_DoScan;


Detecting special keys like "Scan" is an other thing, for now you can just use a button on the form.
Cristian Peța

Posts: 157
Registered: 8/7/06
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 7, 2016 3:40 AM   in response to: Cristian Peța in response to: Cristian Peța
Cristian Peta wrote:
Oliver Hager wrote:
So I have compiled everything and the app runs but it doesn't react to a barcode being scanned.
It looks you have not triggered the scanner from Delphi.
For this I call:
    TJNativeActivitySubclass.Wrap(PANativeActivity(System.DelphiActivity)^.clazz).WA_DoScan;
Sorry.
This was for 70e. For 75e it's somehow automatic but I don't remember now how all is working.
Maybe you need to disable the scan wedge?
Oliver Hager

Posts: 37
Registered: 8/13/10
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 7, 2016 3:52 AM   in response to: Cristian Peța in response to: Cristian Peța
Cristian Peta wrote:
Oliver Hager wrote:
So I have compiled everything and the app runs but it doesn't react to a barcode being scanned.
It looks you have not triggered the scanner from Delphi.
For this I call:
    TJNativeActivitySubclass.Wrap(PANativeActivity(System.DelphiActivity)^.clazz).WA_DoScan;


Detecting special keys like "Scan" is an other thing, for now you can just use a button on the form.

Thanks I noticed that and tried this version that didnt work , JO being a JObject:

JO := TJObject.Create;
TJNativeActivitySubclass.Wrap((JO as ILocalObject).getobjectID).WA_75e_Create_aidcManager;}

So I tried your method and didnt work. I then thought I need to create the AidcManager first , so I did this :

procedure TMainForm.Button1Click(Sender: TObject);
begin
TJNativeActivitySubclass.Wrap(PANativeActivity(System.DelphiActivity)^.clazz).WA_75e_Create_aidcManager;
TJNativeActivitySubclass.Wrap(PANativeActivity(System.DelphiActivity)^.clazz).WA_75e_DoScan;
end;

But now I get the error "java.lang.SecurityException : Not allowed to bond to service Intent {act=com.honeywell.decode.DecodeService cmp=com.intermec,datacollectionservice/.datacollecitonservice }

This is the same error I originally received on my other implementation attempt. Is this a security setting I need to enable in my manifest ?
Cristian Peța

Posts: 157
Registered: 8/7/06
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 7, 2016 4:02 AM   in response to: Oliver Hager in response to: Oliver Hager
Oliver Hager wrote:
TJNativeActivitySubclass.Wrap(PANativeActivity(System.DelphiActivity)^.clazz).WA_75e_DoScan;
I do not use this call in my code.
As I said... I must cleanup my code :-)
Cristian Peța

Posts: 157
Registered: 8/7/06
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 7, 2016 3:49 AM   in response to: Oliver Hager in response to: Oliver Hager
Oliver Hager wrote:
So I have compiled everything and the app runs but it doesn't react to a barcode being scanned.
You can put this in app OnCreate to create the manager.
I do not see this in your code.
      TJNativeActivitySubclass.Wrap(PANativeActivity(System.DelphiActivity)^.clazz).WA_75e_Create_aidcManager;
Oliver Hager

Posts: 37
Registered: 8/13/10
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 7, 2016 3:56 AM   in response to: Cristian Peța in response to: Cristian Peța
Cristian Peta wrote:
Oliver Hager wrote:
So I have compiled everything and the app runs but it doesn't react to a barcode being scanned.
You can put this in app OnCreate to create the manager.
I do not see this in your code.
      TJNativeActivitySubclass.Wrap(PANativeActivity(System.DelphiActivity)^.clazz).WA_75e_Create_aidcManager;

Thanks I thought so but that throws out a java error :

java.lang.SecurityException : Not allowed to bond to service Intent {act=com.honeywell.decode.DecodeService cmp=com.intermec,datacollectionservice/.datacollecitonservice }
Cristian Peța

Posts: 157
Registered: 8/7/06
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 7, 2016 4:06 AM   in response to: Oliver Hager in response to: Oliver Hager
Oliver Hager wrote:
Thanks I thought so but that throws out a java error :

java.lang.SecurityException : Not allowed to bond to service Intent {act=com.honeywell.decode.DecodeService cmp=com.intermec,datacollectionservice/.datacollecitonservice }
Have you added DataCollection.jar to your project Android "Libraries"?
And also your compiled library (I suppose: NativeActivitySubclass.jar)
Oliver Hager

Posts: 37
Registered: 8/13/10
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 7, 2016 4:11 AM   in response to: Cristian Peța in response to: Cristian Peța
Cristian Peta wrote:
Oliver Hager wrote:
Thanks I thought so but that throws out a java error :

java.lang.SecurityException : Not allowed to bond to service Intent {act=com.honeywell.decode.DecodeService cmp=com.intermec,datacollectionservice/.datacollecitonservice }
Have you added DataCollection.jar to your project Android "Libraries"?
And also your compiled library (I suppose: NativeActivitySubclass.jar)

Yes I did. This is from my Scantest.dproj :

<JavaReference Include="Java\libs\DataCollection.jar">
            <Disabled/>
        </JavaReference>
        <JavaReference Include="Java\libs\NativeActivitySubclass.jar">
            <Disabled/>
        </JavaReference>


And I can see the DataCollection-dex.jar and NativeActivitySubclass-dexed.jar in the debug folder.

This is the device log :

W/System.err(30852): java.lang.SecurityException: Not allowed to bind to service Intent { act=com.honeywell.decode.DecodeService cmp=com.intermec.datacollectionservice/.DataCollectionService }
W/System.err(30852): 	at android.app.ContextImpl.bindServiceCommon(ContextImpl.java:1614)
W/System.err(30852): 	at android.app.ContextImpl.bindService(ContextImpl.java:1578)
W/System.err(30852): 	at android.content.ContextWrapper.bindService(ContextWrapper.java:517)
W/System.err(30852): 	at com.honeywell.aidc.AidcManager.create(AidcManager.java:243)
W/System.err(30852): 	at com.winarhi.nativeactivitysubclass.NativeActivitySubclass.WA_75e_Create_aidcManager(NativeActivitySubclass.java:55)
W/System.err(30852): 	at dalvik.system.NativeStart.run(Native Method)


Edited by: Oliver Hager on Apr 7, 2016 4:14 AM
Oliver Hager

Posts: 37
Registered: 8/13/10
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 7, 2016 6:02 AM   in response to: Oliver Hager in response to: Oliver Hager
Oliver Hager wrote:
Cristian Peta wrote:
Oliver Hager wrote:
Thanks I thought so but that throws out a java error :

java.lang.SecurityException : Not allowed to bond to service Intent {act=com.honeywell.decode.DecodeService cmp=com.intermec,datacollectionservice/.datacollecitonservice }
Have you added DataCollection.jar to your project Android "Libraries"?
And also your compiled library (I suppose: NativeActivitySubclass.jar)

Yes I did. This is from my Scantest.dproj :

<JavaReference Include="Java\libs\DataCollection.jar">
            <Disabled/>
        </JavaReference>
        <JavaReference Include="Java\libs\NativeActivitySubclass.jar">
            <Disabled/>
        </JavaReference>


And I can see the DataCollection-dex.jar and NativeActivitySubclass-dexed.jar in the debug folder.

This is the device log :

W/System.err(30852): java.lang.SecurityException: Not allowed to bind to service Intent { act=com.honeywell.decode.DecodeService cmp=com.intermec.datacollectionservice/.DataCollectionService }
W/System.err(30852): 	at android.app.ContextImpl.bindServiceCommon(ContextImpl.java:1614)
W/System.err(30852): 	at android.app.ContextImpl.bindService(ContextImpl.java:1578)
W/System.err(30852): 	at android.content.ContextWrapper.bindService(ContextWrapper.java:517)
W/System.err(30852): 	at com.honeywell.aidc.AidcManager.create(AidcManager.java:243)
W/System.err(30852): 	at com.winarhi.nativeactivitysubclass.NativeActivitySubclass.WA_75e_Create_aidcManager(NativeActivitySubclass.java:55)
W/System.err(30852): 	at dalvik.system.NativeStart.run(Native Method)


Edited by: Oliver Hager on Apr 7, 2016 4:14 AM

Hi Christian

Just to let you know, I seem to have made some progress. First I modified the WA_75e_Create_aidcManager event in the java file by adding

Intent intent=new Intent("com.honeywell.decode.DecodeService");  
        this.startService(intent);


so it look slike htis now

//for 75e
    private void WA_75e_Create_aidcManager() {
        // create the AidcManager providing a Context and a
        // CreatedCallback implementation.
        Log.d(TAG, "Create aidc manager 1.1.1");
        
        Intent intent=new Intent("com.honeywell.decode.DecodeService");  
        this.startService(intent);
        if (H75e_manager == null) {
        	Log.d(TAG, "H75e is null");
        }
        
        if (H75e_manager == null)
          AidcManager.create(this, new AidcManager.CreatedCallback() {           
              @Override
              public void onCreated(AidcManager aidcManager) {
              	  Log.d(TAG, "onCreate aidc manager");
                  H75e_manager = aidcManager;
                  H75e_barcodeReader = H75e_manager.createBarcodeReader();
 
                  // register bar code event listener
                  H75e_barcodeReader.addBarcodeListener(selfActivity);
 
                  // set the trigger mode to client control
                  try {
                        H75e_barcodeReader.setProperty(BarcodeReader.PROPERTY_TRIGGER_CONTROL_MODE,
                                BarcodeReader.TRIGGER_CONTROL_MODE_AUTO_CONTROL);
                        
                        //reader.setProperty(BarcodeReader.PROPERTY_TRIGGER_CONTROL_MODE,
                        //  BarcodeReader.TRIGGER_CONTROL_MODE_CLIENT_CONTROL);                        
                  } catch (UnsupportedPropertyException e) {
                        Toast.makeText(selfActivity, "Failed to apply properties", Toast.LENGTH_SHORT).show();
                  }
                  // register trigger state change listener
                  H75e_barcodeReader.addTriggerListener(selfActivity);
 
                  try {
                      H75e_barcodeReader.claim();
                  } catch (ScannerUnavailableException e) {
                      e.printStackTrace();
                      Toast.makeText(selfActivity, "Scanner unavailable", Toast.LENGTH_SHORT).show();
                  }
              }
          });
    }


then I had to add

 
<uses-permission android:name="com.honeywell.decode.permission.DECODE" /> 


This now works perfectly. You sir are a legend and I thank you so so much for your help. If we ever meet , I owe you a lot of beer (if you drink beer) !

Thank you again.

If anybody else ever needs the source to the test project , it can be found here [http://www.infomastersglobal.co.za/downloads/Source/Scanner.zip] . I compiled this in Delphi Seattle. Please give credit to Christian , it is all his code.

Edited by: Oliver Hager on Apr 7, 2016 6:10 AM
Cristian Peța

Posts: 157
Registered: 8/7/06
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 7, 2016 6:25 AM   in response to: Oliver Hager in response to: Oliver Hager
Oliver Hager wrote:
 
<uses-permission android:name="com.honeywell.decode.permission.DECODE" /> 
Now I see this permission request also in my manifest.
But I have not starter that service and it works...

If you want also to detect Scan, Left and Right buttons you need this:
{$REGION 'Hack HandleAndroidInputEvent'}
var
  OldHandleAndroidInputEvent: function(App: PAndroid_app; Event: PAInputEvent): Int32; cdecl;
  OldKeyTime: TDateTime = 0;
  swScanKeyDown: Boolean = False;
 
function MyHandleAndroidKeyEvent(AEvent: PAInputEvent): Int32;
var
  KeyCode, vkKeyCode, ScanCode: Word;
  KeyKind: TKeyKind;
  NowTime: TDateTime;
begin
  Result := 0;
 
  KeyCode := AKeyEvent_getKeyCode(AEvent);
  vkKeyCode := PlatformKeyToVirtualKey(KeyCode, KeyKind);
  if (vkKeyCode = 0) and (KeyKind = TKeyKind.Unknown) then begin
    case AKeyEvent_getAction(AEvent) of
      AKEY_EVENT_ACTION_DOWN:
        begin
          ScanCode := AKeyEvent_getScanCode(AEvent);
          //$57 left button
          //$58 right button
          //$94 Scan button
          if (ScanCode in [$57, $58, $94]) and not swScanKeyDown then begin
            swScanKeyDown := True;
            NowTime := Now;
            if (NowTime - OldKeyTime) > 1/24/3600 then begin
              MainForm.StartScan;
              OldKeyTime := NowTime;
            end;
          end;
        end;
      AKEY_EVENT_ACTION_UP:
        begin
          ScanCode := AKeyEvent_getScanCode(AEvent);
          if ScanCode in [$57, $58, $94] then begin
            swScanKeyDown := False;
          end;
        end;
    end;
  end;
end;
 
function MyHandleAndroidInputEvent(var App: PAndroid_app; AEvent: PAInputEvent): Int32; cdecl;
var
  EventType: Int64;
begin
  Result := OldHandleAndroidInputEvent(App, AEvent);
 
  EventType := AInputEvent_getType(AEvent);
  if EventType = AINPUT_EVENT_TYPE_KEY then // Keyboard input
    MyHandleAndroidKeyEvent(AEvent);
end;
{$ENDREGION}


And in app main form OnCreate event:
  OldHandleAndroidInputEvent := GetAndroidApp^.onInputEvent;
  GetAndroidApp^.onInputEvent := @MyHandleAndroidInputEvent;
Oliver Hager

Posts: 37
Registered: 8/13/10
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 7, 2016 6:28 AM   in response to: Cristian Peța in response to: Cristian Peța
Cristian Peta wrote:
Oliver Hager wrote:
 
<uses-permission android:name="com.honeywell.decode.permission.DECODE" /> 
Now I see this permission request also in my manifest.
But I have not starter that service and it works...

If you want also to detect Scan, Left and Right buttons you need this:
{$REGION 'Hack HandleAndroidInputEvent'}
var
  OldHandleAndroidInputEvent: function(App: PAndroid_app; Event: PAInputEvent): Int32; cdecl;
  OldKeyTime: TDateTime = 0;
  swScanKeyDown: Boolean = False;
 
function MyHandleAndroidKeyEvent(AEvent: PAInputEvent): Int32;
var
  KeyCode, vkKeyCode, ScanCode: Word;
  KeyKind: TKeyKind;
  NowTime: TDateTime;
begin
  Result := 0;
 
  KeyCode := AKeyEvent_getKeyCode(AEvent);
  vkKeyCode := PlatformKeyToVirtualKey(KeyCode, KeyKind);
  if (vkKeyCode = 0) and (KeyKind = TKeyKind.Unknown) then begin
    case AKeyEvent_getAction(AEvent) of
      AKEY_EVENT_ACTION_DOWN:
        begin
          ScanCode := AKeyEvent_getScanCode(AEvent);
          //$57 left button
          //$58 right button
          //$94 Scan button
          if (ScanCode in [$57, $58, $94]) and not swScanKeyDown then begin
            swScanKeyDown := True;
            NowTime := Now;
            if (NowTime - OldKeyTime) > 1/24/3600 then begin
              MainForm.StartScan;
              OldKeyTime := NowTime;
            end;
          end;
        end;
      AKEY_EVENT_ACTION_UP:
        begin
          ScanCode := AKeyEvent_getScanCode(AEvent);
          if ScanCode in [$57, $58, $94] then begin
            swScanKeyDown := False;
          end;
        end;
    end;
  end;
end;
 
function MyHandleAndroidInputEvent(var App: PAndroid_app; AEvent: PAInputEvent): Int32; cdecl;
var
  EventType: Int64;
begin
  Result := OldHandleAndroidInputEvent(App, AEvent);
 
  EventType := AInputEvent_getType(AEvent);
  if EventType = AINPUT_EVENT_TYPE_KEY then // Keyboard input
    MyHandleAndroidKeyEvent(AEvent);
end;
{$ENDREGION}


And in app main form OnCreate event:
  OldHandleAndroidInputEvent := GetAndroidApp^.onInputEvent;
  GetAndroidApp^.onInputEvent := @MyHandleAndroidInputEvent;

It seems I dont need to do anything special to make those buttons work, It is working without that code. I can use the left,right or center scan buttons and the app is detecting it and populating my memo box.

Cristian Peța

Posts: 157
Registered: 8/7/06
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 7, 2016 6:30 AM   in response to: Cristian Peța in response to: Cristian Peța
Now I realize that for 75e you don't need to start the decoder.
Hacking GetAndroidApp^.onInputEvent is needed only for 70e.
Oliver Hager

Posts: 37
Registered: 8/13/10
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 7, 2016 6:14 AM   in response to: Oliver Hager in response to: Oliver Hager
Thank you Cristian Peta
Sebi Dan

Posts: 2
Registered: 6/11/16
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 11, 2016 12:48 AM   in response to: Oliver Hager in response to: Oliver Hager
Hello ! I'm new in this and I tried to run this code in Android Studio but I've got problems with imports :" Cannot resolve symbole "decodemanager" ". It also can resolve "com.embarcadero...". Can you help me ? I want with this project to get the barcode and write it to a file.txt, but I can't run it.
Oliver Hager

Posts: 37
Registered: 8/13/10
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 11, 2016 12:56 AM   in response to: Sebi Dan in response to: Sebi Dan
Hi

This code won't run in Android Studio. It is a Delphi Firemonkey project and it will only compile in Delphi
Cristian Peța

Posts: 157
Registered: 8/7/06
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 11, 2016 2:12 AM   in response to: Sebi Dan in response to: Sebi Dan
Sebi Dan wrote:
Hello ! I'm new in this and I tried to run this code in Android Studio but I've got problems with imports :" Cannot resolve symbole "decodemanager" ". It also can resolve "com.embarcadero...". Can you help me ? I want with this project to get the barcode and write it to a file.txt, but I can't run it.
Why you just don't use Honeywell examples?
They are for Android Studio. Actually most Java code you see here is from Honeywell examples but modified to work with Delphi.

If you can't understand why this code here don't compile in Android Studio and you are new to Delphi then you have much to learn before you can do something in Delphi with JNI. I can wish you only best luck. And many coffees.
Cristian Peța

Posts: 157
Registered: 8/7/06
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 11, 2016 2:19 AM   in response to: Sebi Dan in response to: Sebi Dan
Sebi Dan wrote:
I've got problems with imports :" Cannot resolve symbole "decodemanager" ".
This is from Honeywell library.
It also can resolve "com.embarcadero...".
This is from Delphi (classes.dex). You don't need this in Android Studio.
Sebi Dan

Posts: 2
Registered: 6/11/16
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 11, 2016 1:14 AM   in response to: Oliver Hager in response to: Oliver Hager
First time opening Delphi. How can I import the project ? It says : The project can not be loaded because the required personality Delphi.Personality is not available...
Oliver Hager

Posts: 37
Registered: 8/13/10
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 11, 2016 1:15 AM   in response to: Sebi Dan in response to: Sebi Dan
You dont import the project you just do a File->Project->Open. I have never seen an error relating to personality. Perhaps google that error
Markus Humm

Posts: 5,113
Registered: 11/9/03
Re: Consuming a 3rd Party Android API (Honeywell Datacapture.jar)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 11, 2016 11:55 AM   in response to: Oliver Hager in response to: Oliver Hager
Am 11.05.2016 um 10:15 schrieb Oliver Hager:
You dont import the project you just do a File->Project->Open. I have never seen an error relating to personality. Perhaps google that error

Maybe he tried to open a non Delphi project wioth Delphi.
if he's new to Delphi he might want to start with some of the supplied
samples first and not do such a complex thing as first project!

Greetings

Markus
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02