如何从这个JAVA文件中提取一个Delphi类以便在Android中使用?

3

我的Delphi XE7项目需要与FTDI FT311 Android Accessory Chip通信。他们提供了一个Android演示程序,其中包括他们的JAVA驱动程序FT311I2CInterface.java(稍后在本文中显示)。假设我需要将此文件转换为OP,我遵循了使用Java2OP.exe命令行工具的说明,进行必要的路径添加以指向JDK(似乎由XE7安装)SET PATH=%PATH%;C:\Program Files\Java\jdk1.7.0_25\bin

所有文件都在同一个文件夹中,我使用以下命令运行了该工具:

java2op.exe  -unit FT311I2CInterface.java

没有收到错误并获得了一个输出文件FT311I2CInterface.java.pas。然而,这个输出文件里面有一个空的类,如下所示:

{*******************************************************}
{                                                       }
{           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.

请问有人能建议我做错了什么吗?

原始的JAVA文件如下:

//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){}
                }
            }
        }



    }

JDK 1.7.0_25已经相当陈旧(JRE在2013年11月15日到期),目前的版本是1.7.0_71/72。 - mjn
3个回答

2

我是一个Android的初学者,同时也在尝试与FT311进行接口交互。 我将分享我的Java2OP经验,但我还无法在Delphi XE7中获得usbAccessory。

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;

我在使用java2op时遇到了很多问题,但是这里是我遵循的步骤(抱歉我不记得链接了):

  1. 使用eclipse ADT创建一个包含所需类的.jar文件(我使用FTDI提供的FT31演示项目中的FT311GPIOInterface.java)。这并不容易,因为您必须将演示应用程序拆分成“Android项目库”(生成.jar的项目)和“Android项目”(演示应用程序的UI)。当您构建和运行演示应用程序时,.jar会被构建(而不是构建android项目库时)。 如果您想要使用UI应用程序测试您的.jar,则必须将.jar复制到UI应用程序的Libs目录中,然后部署到Android设备上。 我对eclipse还很陌生,可能有更好的方法,但是…… 我看到了另一种生成.jar文件的方法 请参见brian long网站

  2. Java2op:它在干净的XP Windows上工作:我使用虚拟机,未安装delphi XE,使用java jdk1.7.0_25,安装了java2op,没有安装Android SDK。

我的jar是ft311lib.jar

java2op -jar ft311lib.jar -unit com.poco.ft311lib

这会生成com.poco.ft311lib.pas

希望这可以帮助到您


谢谢Domido,我们都在努力实现类似的事情,这很好。你展示了如何将FT311作为附件获取,但是得到了AV。我比这更进一步,但无法创建输入和输出Java缓冲区,所以我像你一样尝试使用提供的类(对我来说是FT311I2CInterface.java)。自从我在这里发布后,我已经成功地使用了Java2Pas,这是一款50英镑的付费工具,它现在给了我一个Delphi接口单元。你是否成功调用了由java2op生成的单元?你想合作吗?我有一些示例文件可以与你交换。 - Brian Frost

1

Java2OP.exe是一个命令行工具,可用于从Java库(JAR或class文件)生成Delphi本地桥接文件。

我建议检查您是否正确使用了该工具:

java2op.exe  -unit FT311I2CInterface.java

根据文档,-unit指定的是输出单元的文件名,而不是输入文件。文档还指出:
“您必须至少指定一个输入选项,以指示您要在输出 Delphi 本地桥接文件中包含哪些内容。”
请尝试以下操作:
java2op.exe  -source .

我已经尝试过了,但是我得到了一个doclava.log错误:“命令: javadoc -J-Xmx1024m -encoding“UTF-8”-sourcepath“C:\Art_soft\Java2OP\src”-subpackages-classpath“C:\Art_soft\Java2OP\android-19.jar”-bootclasspath“C:\Art_soft\Java2OP\android-19.jar”-docletpath“C:\Art_soft\Java2OP\doclava.jar”-doclet com.google.doclava.Doclava-nodocs-public-apixml“C:\Art_soft\Java2OP\temp.xml”输出: javadoc:错误-非法包名称:“C:\Art_soft\Java2OP\android-19.jar” 1个错误” - Brian Frost

1
根据关于此命令行工具的链接文档,我将按照以下步骤进行:
  • 创建一个src/文件夹,并将FT311I2CInterface.java放入其中。
  • 使用以下参数运行java2op.exe

    java2op.exe -source src/ -unit Android.JNI.FT311I2C

预期输出:

Android.JNI.FT311I2C.pas
< p > -unit 参数指定输出。

-source 参数指定输入(在您的情况下,您需要一个Java源文件)


谢谢,但这没用(我得到了一个错误日志),所以在文档链接的末尾,它展示了一个简单的例子:“java2op.exe -classes android.animation.* -unit hope”。当我尝试这个时,我得到了同样的空输出文件,有结构但没有类和错误。 - Brian Frost
这个可以从Android API中提取信息,并创建一个名为“Android.Hardware.USB.pas”的文件 - “Java2OP.exe -classes android.hardware android.hardware.usb.* -unit Android.Hardware.USB”。到目前为止,只有这个Android提取方式对我有效。 - Brian Frost
或许尝试将Java文件放在这里:src/com/I2CDemo/FT311I2CInterface.java,以便目录层次结构反映Java包。(并使用相同的命令行:java2op.exe -source src/ -unit Android.JNI.FT311I2C) - ben75

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接