How can I extract the Delphi class from this JAVA file for use with Android?
My Delphi XE7 project needs to interoperate with FTDI FT311 for Android accessories . They help provide an Android demo that includes the JAVA driver FT311I2CInterface.java
(shown below in this post). Assuming I need to convert this file to OP, I followed the instructions for using the Java2OP.exe command line tool , making the necessary path addition to point to the JDK (which seems to be installed by XE7)SET PATH=%PATH%;C:\Program Files\Java\jdk1.7.0_25\bin
With everything in the same folder, I ran the tool with
java2op.exe -unit FT311I2CInterface.java
got no errors and got an output file FT311I2CInterface.java.pas
. However, this output file has an empty class in it like this:
{*******************************************************}
{ }
{ CodeGear Delphi Runtime Library }
{ Copyright(c) 2014 Embarcadero Technologies, Inc. }
{ }
{*******************************************************}
unit FT311I2CInterface.java;
interface
uses
Androidapi.JNIBridge;
type
// ===== Forward declarations =====
// ===== Interface declarations =====
implementation
procedure RegisterTypes;
begin
end;
initialization
RegisterTypes;
end.
Can anyone suggest what I am doing wrong?
The original JAVA file, as stated, looks like this:
//User must modify the below package with their package name
package com.I2CDemo;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.widget.Toast;
/******************************FT311 GPIO interface class******************************************/
public class FT311I2CInterface extends Activity
{
private static final String ACTION_USB_PERMISSION = "com.I2CDemo.USB_PERMISSION";
public UsbManager usbmanager;
public UsbAccessory usbaccessory;
public PendingIntent mPermissionIntent;
public ParcelFileDescriptor filedescriptor;
public FileInputStream inputstream;
public FileOutputStream outputstream;
public boolean mPermissionRequestPending = false;
public boolean READ_ENABLE = true;
public boolean accessory_attached = false;
public handler_thread handlerThread;
private byte [] usbdata;
private byte [] writeusbdata;
private int readcount;
private byte status;
private byte maxnumbytes = 60;
public boolean datareceived = false;
public Context global_context;
public static String ManufacturerString = "mManufacturer=FTDI";
public static String ModelString = "mModel=FTDII2CDemo";
public static String VersionString = "mVersion=1.0";
/*constructor*/
public FT311I2CInterface(Context context){
super();
global_context = context;
/*shall we start a thread here or what*/
usbdata = new byte[64];
writeusbdata = new byte[64];
/***********************USB handling******************************************/
usbmanager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
// Log.d("LED", "usbmanager" +usbmanager);
mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
context.registerReceiver(mUsbReceiver, filter);
inputstream = null;
outputstream = null;
}
/*reset method*/
public void Reset()
{
/*create the packet*/
writeusbdata[0] = 0x34;
writeusbdata[1] = 0x00;
writeusbdata[2] = 0x00;
writeusbdata[3] = 0x00;
writeusbdata[4] = 0x00;
/*send the packet over the USB*/
SendPacket(5);
}
/*SetFrequency*/
public void SetFrequency(byte freq)
{
/*check for maximum and minimum freq*/
if(freq > 92)
freq = 92;
if (freq < 23)
freq = 23;
/*create the packet*/
writeusbdata[0] = 0x31;
switch(freq)
{
case 23:
writeusbdata[1] = 10;
break;
case 44:
writeusbdata[1] = 21;
break;
case 60:
writeusbdata[1] = 30;
break;
default:
writeusbdata[1] = 56;
break;
}
writeusbdata[2] = 0x00;
writeusbdata[3] = 0x00;
writeusbdata[4] = 0x00;
/*send the packet over the USB*/
SendPacket(5);
}
/*write data*/
public byte WriteData(byte i2cDeviceAddress,byte transferOptions,
byte numBytes, byte[] buffer,
byte [] actualNumBytes)
{
status = 0x01; /*error by default*/
/*
* if num bytes are more than maximum limit
*/
if(numBytes < 1){
actualNumBytes[0] = (byte)0x00;
/*return the status with the error in the command*/
return status;
}
/*check for maximum limit*/
if(numBytes > maxnumbytes){
numBytes = maxnumbytes;
}
/*prepare the packet to be sent*/
for(int count = 0;count<numBytes;count++)
{
writeusbdata[4+count] = (byte)buffer[count];
}
/*prepare the usbpacket*/
writeusbdata[0] = 0x32;
writeusbdata[1] = i2cDeviceAddress;
writeusbdata[2] = transferOptions;
writeusbdata[3] = numBytes;
SendPacket((int)(numBytes+4));
datareceived = false;
/*wait while the data is received*/
/*FIXME, may be create a thread to wait on , but any
* way has to wait in while loop
*/
while(true){
if(datareceived == true){
break;
}
}
/*by default it error*/
status = 0x01;
/*check for the received data*/
if(usbdata[0] == 0x32)
{
/*check for return error status*/
status = usbdata[1];
/*updated the written bytes*/
actualNumBytes[0] = usbdata[3];
}
datareceived = false;
return status;
}
/*read data*/
public byte ReadData(byte i2cDeviceAddress,byte transferOptions,
byte numBytes, byte[] readBuffer,
byte [] actualNumBytes)
{
status = 0x01; /*error by default*/
/*should be at least one byte to read*/
if(numBytes < 1){
return status;
}
/*check for max limit*/
if(numBytes > maxnumbytes){
numBytes = maxnumbytes;
}
/*prepare the packet to send this command*/
writeusbdata[0] = 0x33; /*read data command*/
writeusbdata[1] = i2cDeviceAddress; /*device address*/
writeusbdata[2] = transferOptions; /*transfer options*/
writeusbdata[3] = numBytes; /*number of bytes*/
/*send the data on USB bus*/
SendPacket(4);
datareceived = false;
/*wait for data to arrive*/
while(true)
{
if(datareceived == true){
break;
}
}
/*check the received data*/
if(usbdata[0] == 0x33)
{
/*check the return status*/
status = usbdata[1];
/*check the received data length*/
numBytes = usbdata[3];
if(numBytes > maxnumbytes){
numBytes = maxnumbytes;
}
for(int count = 0; count<numBytes;count++)
{
readBuffer[count] = usbdata[4+count];
}
/*update the actual number of bytes*/
actualNumBytes[0] = numBytes;
datareceived = false;
}
return status;
}
/*method to send on USB*/
private void SendPacket(int numBytes)
{
try {
if(outputstream != null){
outputstream.write(writeusbdata, 0,numBytes);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*resume accessory*/
public void ResumeAccessory()
{
// Intent intent = getIntent();
if (inputstream != null && outputstream != null) {
return;
}
UsbAccessory[] accessories = usbmanager.getAccessoryList();
if(accessories != null)
{
Toast.makeText(global_context, "Accessory Attached", Toast.LENGTH_SHORT).show();
}
else
{
accessory_attached = false;
return;
}
UsbAccessory accessory = (accessories == null ? null : accessories[0]);
if (accessory != null) {
if( -1 == accessory.toString().indexOf(ManufacturerString))
{
Toast.makeText(global_context, "Manufacturer is not matched!", Toast.LENGTH_SHORT).show();
return;
}
if( -1 == accessory.toString().indexOf(ModelString))
{
Toast.makeText(global_context, "Model is not matched!", Toast.LENGTH_SHORT).show();
return;
}
if( -1 == accessory.toString().indexOf(VersionString))
{
Toast.makeText(global_context, "Version is not matched!", Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(global_context, "Manufacturer, Model & Version are matched!", Toast.LENGTH_SHORT).show();
accessory_attached = true;
if (usbmanager.hasPermission(accessory)) {
OpenAccessory(accessory);
}
else
{
synchronized (mUsbReceiver) {
if (!mPermissionRequestPending) {
Toast.makeText(global_context, "Request USB Permission", Toast.LENGTH_SHORT).show();
usbmanager.requestPermission(accessory,
mPermissionIntent);
mPermissionRequestPending = true;
}
}
}
} else {}
}
/*destroy accessory*/
public void DestroyAccessory(){
global_context.unregisterReceiver(mUsbReceiver);
if(accessory_attached == true)
{
READ_ENABLE = false;
byte i2cDeviceAddress = 1;
byte transferOptions = bOption.START_BIT;
byte numBytes = 2;
byte [] actualNumBytes = new byte[1];
byte [] readBuffer = new byte[60];
//byte deviceAddress = 1;
readBuffer[0] = 1;
ReadData(i2cDeviceAddress,transferOptions,
numBytes, readBuffer,
actualNumBytes);
try{Thread.sleep(10);}
catch(Exception e){}
}
CloseAccessory();
}
/*********************helper routines*************************************************/
public void OpenAccessory(UsbAccessory accessory)
{
filedescriptor = usbmanager.openAccessory(accessory);
if(filedescriptor != null){
usbaccessory = accessory;
FileDescriptor fd = filedescriptor.getFileDescriptor();
inputstream = new FileInputStream(fd);
outputstream = new FileOutputStream(fd);
/*check if any of them are null*/
if(inputstream == null || outputstream==null){
return;
}
}
handlerThread = new handler_thread(inputstream);
handlerThread.start();
}
private void CloseAccessory()
{
try{
if(filedescriptor != null)
filedescriptor.close();
}catch (IOException e){}
try {
if(inputstream != null)
inputstream.close();
} catch(IOException e){}
try {
if(outputstream != null)
outputstream.close();
}catch(IOException e){}
/*FIXME, add the notfication also to close the application*/
filedescriptor = null;
inputstream = null;
outputstream = null;
System.exit(0);
}
/***********USB broadcast receiver*******************************************/
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action))
{
synchronized (this)
{
UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false))
{
Toast.makeText(global_context, "Allow USB Permission", Toast.LENGTH_SHORT).show();
OpenAccessory(accessory);
}
else
{
Toast.makeText(global_context, "Deny USB Permission", Toast.LENGTH_SHORT).show();
Log.d("LED", "permission denied for accessory "+ accessory);
}
mPermissionRequestPending = false;
}
}
else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action))
{
CloseAccessory();
}else
{
Log.d("LED", "....");
}
}
};
/*usb input data handler*/
private class handler_thread extends Thread {
FileInputStream instream;
handler_thread(FileInputStream stream ){
instream = stream;
}
public void run()
{
while(READ_ENABLE == true)
{
try
{
/*dont overwrite the previous buffer*/
if((instream != null) && (datareceived==false))
{
readcount = instream.read(usbdata,0,64);
if(readcount > 0)
{
datareceived = true;
/*send only when you find something*/
}
}
}catch (IOException e){}
}
}
}
}
source to share
I am starting with Android and I am also trying to link FT311. I will share my experience with Java2OP, but I still cannot get usbAccessory in Delphi XE7
UsbManager := TJUsbManager.Wrap(SharedActivityContext.getSystemService(TJContext.JavaClass.USB_SERVICE));
AccessoryList := UsbManager.getAccessoryList();
if ( AccessoryList <> nil ) then begin
if ( AccessoryList.Length > 0 ) then begin
Accessory := AccessoryList.Items[0]; <<<<<<< raise an illegal instruction , access violation..
end;
end;
I had a lot of trouble using java2op, but here are the steps I am following. After searching on Google (sorry, I don't remember the url).
-
create a .jar file with eclipse ADT containing the class you need (I'm using FT311GPIOInterface.java from the FT31 demo project supplied by FTDI). It's not that easy because you need to split the demo app into an "android project library" (the one that will create the .jar) and an "android project" in the demo app UI..jar is created when you build and run the demo app ( not when building the Android project library). If you want to test your .jar with a UI app, you need to copy the .jar to your UI app in the Libs directory and then deploy it to your android device I'm new to eclipse, maybe there is a better way to do this, but ... I saw another way to create a file.jar See brian long website for another way
-
Java2op: It works on clean windows XP: I am using a virtual machine, no Delphi XE installed, with java jdk1.7.0_25, java2op, no Android SDK.
my jar is ft311lib.jar java2op -jar ft311lib.jar -unit com.poco.ft311lib
this product is com.poco.ft311lib.pas
Hope for this help
source to share
Java2OP.exe ... is a command line tool that you can use to generate your own Delphi bridge files from Java libraries (JAR files or class files).
I suggest checking if you are using the tool correctly:
java2op.exe -unit FT311I2CInterface.java
According to the documentation, -unit points File name of the output unit
, not the input file. He also says
You must specify at least one input parameter that specifies what content you want to include in the Delphi interface output file.
Try this instead:
java2op.exe -source .
source to share
In the related documentation about this command line tool, I would do the following:
- create a folder
src/
and place in itFT311I2CInterface.java
. -
run
java2op.exe
with these arguments:java2op.exe -source src/ -unit Android.JNI.FT311I2C
Expected Result:
Android.JNI.FT311I2C.pas
The argument -unit
specifies the output file.
The -source
arg argument specifies the input (in your case, you need the java source file)
source to share