C++ Builder XE7 调用JAVA的JAR文件

 C++ Builder从XE6开始支持Android开发,但是在目前看来,C++ Builder for Android的技术资料非常少,我们只能从一些博客和论坛的只言片语中获取相关的信息和资源。

 

       我们知道,Android的应用程序大部分是用JAVA开发的,许多硬件制造商和服务商提供的SDK开发包,也是以JAVA的JAR库文件形式提供的,如果C++ Builder能够调用JAVA的JAR文件,那么将会大幅拓宽C++ Builder在移动开发上的应用环境,缓解在商业应用上的窘境。

 

       一直以来,C++ Builder作为Delphi的附属产品,其所获得的技术支持和关注都要比Delphi少,即使在EMB公司(Embarcadero)旗下发展到了XE7版本,这种状况仍然没有改变。许多Delphi和C++ Builder都面临的新问题,我们在网上只找到Delphi的解决方案。

 

       因此,当我在互联网上搜索“XE7调用JAR文件”时,只找到一篇文章:

              《Delphi XE7的安卓程序如何调用JAVA的JAR,使用JAVA的类》

              链接地址:http://blog.csdn.net/sunylat/article/details/41414785

 

       以及一篇EMB的帮助文档:
       
             《Using a Custom Set of Java Libraries In Your RAD Studio Android Apps》

             http://docwiki.embarcadero.com/RADStudio/XE7/en/Using_a_Custom_Set_of_Java_Libraries_In_Your_RAD_Studio_Android_Apps


        当然,Delphi和C++ Builder在一定程度上是相通的,于是尝试动手在C++ Builder下调用JAR文件。经过两天测试,终于找到了在C++ Builder XE7下调用JAR文件的方法。(注:以下方法在XE7下测试成功,如果您用的是其它版本,请自行测试)

 

        具体步骤如下:

一、生成原生桥接文件(NativeBridge File)


        所谓“原生桥接文件”,即JAR文件的定义文件,说明了存在JAR库文件里的类、类型、函数等,相当于Windows系统下的dll文件和hpp文件,原生桥接文件只是进行说明定义,具体的实现功能代码仍然在JAR文件里。

 

        如何生成原生桥接文件?EMB给出的方法是用Java2OP.exe工具,这是一个命令行程序,使用方法详见:

       http://docwiki.embarcadero.com/RADStudio/XE7/en/Java2OP.exe,_the_Native_Bridge_File_Generator_for_Android

 

        除了EMB的方案,我们还有另外两个选择:

                1. 使用Java2Pas.exe工具

               这也是一个命令行程序,通过一个批处理命令调用,作者未知。

       2. 使用JarOrClass2Pas_FlyingWang工具

              这是一个窗口程序,界面友好,是一个QQ群的牛人“老猫”开发。

 

       因为JarOrClass2Pas_FlyingWang操作简单,推荐优先使用。下面是用JarOrClass2Pas_FlyingWang根据JAR文件生成Delphi的原生桥接文件情况:


        在指定的文件夹下,会生成一个新的pas文件,这就是Delphi的原生桥接文件。

 

二、把Delphi的原生桥接文件转化为C++Builder的原生桥接文件


       上面生成的是Delphi的原生桥接文件(pas格式),要想在C++ Builder中使用,还必须将它转化为C++ Builder的原生桥接文件(hpp格式)。

 

       如何把pas文件转化为C++ Builder的原生桥接文件?EMB给出的方案是手工把pas文件转化为hpp文件!有没有搞错!!!如果是简单的JAR文件还好,其原生桥接文件就几十行代码,仔细研究还是有可能改写为hpp文件的。但是稍微复杂些的JAR文件,其其原生桥接文件达到几百上千行,各种奇怪的类型变量层出不穷,不是同时精通Delphi和C++ Builder的开发者,根本无法做到。

 

       在这里,我使用一个简单的方法,让C++ Builder自动把pas文件转化为hpp文件。

 

       打开C++ Builder XE7,新建一个Multi-Device Application项目,Target Platforms设置为Android程序,在Libraries项之下添加你的JAR文件,然后,把上面生成的Delphi桥接文件添加到工程中。你没有看错,C++ Builder XE7可以直接把Delphi的pas文件添加到工程中!

        最后,编译程序。如果该桥接文件没有错误,编译结束后,你会在工程项目文件夹中看到多出一个hpp文件,这就是C++Builder的原生桥接文件!(就这么简单,难道EMB的技术人员没有把C++Builder的这个功能告诉写帮助文档的临时工?)

 

       如果编译产生错误,你可以对Delphi的桥接文件进行修改,或者尝试改用其它两个工具来生成新的Delphi桥接文件。

 

 

三、设置工程的部署选项


       打开你的Android工程,点菜单项Project——Deployment,打开部署子窗口,点Revert to Default按钮,如图所示:


        出现Revert to default对话框:


        选中第一项“Revert for all configurationsthe active platform”,点OK。

 

       注意:不论其默认选项如何,在这里都必须选择其中一个并点OK,否则你的Android程序在调用JAR文件时将会出现“Java Class xxx could not befound”的错误。

 

       在《Delphi XE7的安卓程序如何调用JAVA的JAR》一文中,作者要求选第二项,经本人在C++ Builder XE7中测试,选第二项在调用JAR文件时可能会出现“JavaClass xxx could not be found”的错误。所以这里建议选第一项,如果程序调用JAR文件出错,再改为第二项。

 

 

四、编写调用JAR文件的代码

 

       首先了解一下示例的test.jar文件的JAVA代码,使用Eclipse编译,它简单定义了一个名字变量和一个年龄变量,并定义了四个函数,用于设置和获取名字和年龄。

[java]  view plain copy
  1. public class Test {  
  2.     // 名字属性  
  3.     private String name;  
  4.   
  5.     // 年龄属性  
  6.     private Integer age;  
  7.   
  8.     public String getName() {  
  9.         return name;  
  10.     }  
  11.   
  12.     public void setName(String name) {  
  13.         this.name = name;  
  14.     }  
  15.   
  16.     public Integer getAge() {  
  17.         return age;  
  18.     }  
  19.   
  20.     public void setAge(Integer age) {  
  21.         this.age = age;  
  22.     }  
  23.   
  24.     public static void main(String[] args) {  
  25.         // 实例化类  
  26.         Test test = new Test();  
  27.   
  28.         // 设置默认名字  
  29.         test.setName("Delphi");  
  30.         // 设置默认年龄  
  31.         test.setAge(100);  
  32.     }  
  33. }  

        按上面所述,根据JAR文件用工具生成Delphi的原生桥接文件。

       创建一个Android工程,添加JAR文件和Delphi的桥接文件,编译第一次得到C++ Builder的桥接文件。

       修改工程的部署选项,选第一项“Revert for allconfigurations the active platform”,点OK。

       在Form1内放置两个Edit组件用于设置数据,放置一个Memo组件用于显示数据。再放置三个Button,分别是“设置”、“获取”和“清空”按钮。

       在Unit1.hpp中,把C++ Builder的桥接文件include进来:

              #include"Androidapi.JNI.Test.hpp"


       注意:工程中原Delphi的桥接文件仍然保留,不要移除。

 

       在private段,定义一个JAR文件的类指针变量:

       private:

              _di_JTest testClass;

 

       在Unit1.cpp中编写调用代码:

[cpp]  view plain copy
  1. #include <Androidapi.Helpers.hpp>   //StringToJString函数  
  2. #include <Androidapi.JNI.JavaTypes.hpp>  
  3. //---------------------------------------------------------------------------  
  4. void __fastcall TForm1::FormCreate(TObject *Sender)  
  5. {  
  6.     //创建实例(这是C++ Builder创建Java类的方法)  
  7.     testClass = TJTest::JavaClass->init();  
  8.   
  9.     //初始化  
  10.     testClass->setName(StringToJString(L"张三"));  
  11.     testClass->setAge(TJInteger::JavaClass->init(StringToJString(L"20")));  
  12. }  
  13. //---------------------------------------------------------------------------  
  14. void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)  
  15. {  
  16.     //释放实例  
  17.     testClass = NULL;  
  18. }  
  19. //---------------------------------------------------------------------------  
  20. void __fastcall TForm1::Button1Click(TObject *Sender)  
  21. {  
  22.     UnicodeString strName = Edit1->Text.Trim();  
  23.     UnicodeString strAge = Edit2->Text.Trim();  
  24.   
  25.     if(strName == "")  
  26.     {  
  27.         ShowMessage(L"姓名不能为空!");  
  28.         return;  
  29.     }  
  30.     if(strAge == "")  
  31.     {  
  32.         ShowMessage(L"年龄不能为空!");  
  33.         return;  
  34.     }  
  35.   
  36.     testClass->setName(StringToJString(strName));  
  37.     testClass->setAge(TJInteger::JavaClass->init(StringToJString(strAge)));  
  38. }  
  39. //---------------------------------------------------------------------------  
  40. void __fastcall TForm1::Button2Click(TObject *Sender)  
  41. {  
  42.     Memo1->Lines->Clear();  
  43.   
  44.     UnicodeString strName = JStringToString(testClass->getName());  
  45.     UnicodeString strAge = JStringToString(testClass->getAge()->toString());  
  46.   
  47.     Memo1->Lines->Add(strName);  
  48.     Memo1->Lines->Add(strAge);  
  49. }  
  50. //---------------------------------------------------------------------------  
  51. void __fastcall TForm1::Button3Click(TObject *Sender)  
  52. {  
  53.     Memo1->Lines->Clear();  
  54. }  
  55. //---------------------------------------------------------------------------  

        在Android 4.1.1上测试成功。程序运行效果如图所示:


        所有源码及上面三个工具可在此下载:

                http://download.csdn.net/detail/realbay/8348639



【特别感谢】

       1.  JarOrClass2Pas_FlyingWang工具的作者老猫

       2. 《Delphi XE7的安卓程序如何调用JAVA的JAR》的作者sunylat


转载:http://blog.csdn.net/realbay/article/details/42587705


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值