“My solution was to write some Java code then insert this code into classes.dex
Then I use this Java code from Delphi trough Java generic import and JNI.
You can read Brian Long blog about classes.dex
My starting point from Honeywell SDK examples was DecodeSampleActivity. There is ScanDemoMainActivity.java that I modified and merged into classes.dex
I extended com.embarcadero.firemonkey.FMXNativeActivity but I think now it should be enough to extend Activity. When you extend Activity you do not need to decompile classes.dex
The main Delphi part is here:”
//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;
//This is called from the Java activity's onBarCodeComplete() method
procedure onBarCodeFailNative(PEnv: PJNIEnv; This: JNIObject); cdecl;
begin
Log.d('+onBarCodeFailNative');
Log.d('Thread (Main: %.8x, Current: %.8x, Java:%.8d (%2:.8x), POSIX:%.8x)',
[MainThreadID, TThread.CurrentThread.ThreadID, TJThread.JavaClass.currentThread.getId, GetCurrentThreadID]);
Log.d('Calling Synchronize');
TThread.Synchronize(nil, onBarCodeFailThreadSwitcher);
Log.d('Synchronize is over');
Log.d('-onBarCodeFailNative');
end;
procedure TFormMain.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;
“And Java code:”
package com.winarhi.nativeactivitysubclass;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import java.io.IOException;
import com.honeywell.decodemanager.DecodeManager;
import com.honeywell.decodemanager.barcode.DecodeResult;
public class NativeActivitySubclass extends com.embarcadero.firemonkey.FMXNativeActivity{
//private final int ID_SCANSETTING = 0x12;
//private final int ID_CLEAR_SCREEN = 0x13;
private DecodeManager mDecodeManager = null;
public String strDecodeResult = "";
private final int WA_SCANTIMEOUT = 5000;
long WA_mScanAccount = 0;
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();
}
}
}
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:
{
}
break;
default:
super.handleMessage(msg);
break;
}
}
};
private void WA_cancelScan() throws Exception {
mDecodeManager.cancelDecode();
}
}
One more thing (Java generic import):
uses
Androidapi.JNIBridge,
Androidapi.JNI.App;
type
JNativeActivitySubclassClass = interface(JNativeActivityClass)
['{829C77FB-08F1-4D19-9782-3C58EECAAAAA}']
{Methods}
//function init: JFMXNativeActivity; cdecl;
end;
[JavaSignature('com/winarhi/nativeactivitysubclass/NativeActivitySubclass')]
JNativeActivitySubclass = interface(JNativeActivity)
['{2FA559EC-D1D7-46AA-9C52-FEFC6B3AAAAA}']
{Methods}
procedure WA_DoScan;
procedure WA_CreateDecodeManager;
procedure WA_DestroyDecodeManager;
end;
TJNativeActivitySubclass = class(TJavaGenericImport<JNativeActivitySubclassClass, JNativeActivitySubclass>) end;
Best Regards,
Cristian Peta
For implementing existing third party SDKs like MoPub, TapJoy, Millennial Media, Google Play Services, Flurry, Chartboost, Upsight, or even new Bluetooth functionality for Android in Delphi XE5, Delphi XE6, and AppMethod this may be the fastest way.
Head over and download the samples from Brian Long on customizing your Firemonkey classes.dex file.