天天看點

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的原生橋接檔案情況:

C++ Builder XE7 調用JAVA的JAR檔案

        在指定的檔案夾下,會生成一個新的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檔案添加到工程中!

C++ Builder XE7 調用JAVA的JAR檔案

        最後,編譯程式。如果該橋接檔案沒有錯誤,編譯結束後,你會在工程項目檔案夾中看到多出一個hpp檔案,這就是C++Builder的原生橋接檔案!(就這麼簡單,難道EMB的技術人員沒有把C++Builder的這個功能告訴寫幫助文檔的臨時工?)

       如果編譯産生錯誤,你可以對Delphi的橋接檔案進行修改,或者嘗試改用其它兩個工具來生成新的Delphi橋接檔案。

三、設定工程的部署選項

       打開你的Android工程,點菜單項Project——Deployment,打開部署子視窗,點Revert to Default按鈕,如圖所示:

C++ Builder XE7 調用JAVA的JAR檔案

        出現Revert to default對話框:

C++ Builder XE7 調用JAVA的JAR檔案

        選中第一項“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.     private Integer age;  
  6.     public String getName() {  
  7.         return name;  
  8.     }  
  9.     public void setName(String name) {  
  10.         this.name = name;  
  11.     }  
  12.     public Integer getAge() {  
  13.         return age;  
  14.     }  
  15.     public void setAge(Integer age) {  
  16.         this.age = age;  
  17.     }  
  18.     public static void main(String[] args) {  
  19.         // 執行個體化類  
  20.         Test test = new Test();  
  21.         // 設定預設名字  
  22.         test.setName("Delphi");  
  23.         // 設定預設年齡  
  24.         test.setAge(100);  
  25.     }  
  26. }  

        按上面所述,根據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.     testClass->setName(StringToJString(L"張三"));  
  10.     testClass->setAge(TJInteger::JavaClass->init(StringToJString(L"20")));  
  11. }  
  12. //---------------------------------------------------------------------------  
  13. void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)  
  14. {  
  15.     //釋放執行個體  
  16.     testClass = NULL;  
  17. }  
  18. //---------------------------------------------------------------------------  
  19. void __fastcall TForm1::Button1Click(TObject *Sender)  
  20. {  
  21.     UnicodeString strName = Edit1->Text.Trim();  
  22.     UnicodeString strAge = Edit2->Text.Trim();  
  23.     if(strName == "")  
  24.     {  
  25.         ShowMessage(L"姓名不能為空!");  
  26.         return;  
  27.     }  
  28.     if(strAge == "")  
  29.     {  
  30.         ShowMessage(L"年齡不能為空!");  
  31.         return;  
  32.     }  
  33.     testClass->setName(StringToJString(strName));  
  34.     testClass->setAge(TJInteger::JavaClass->init(StringToJString(strAge)));  
  35. }  
  36. //---------------------------------------------------------------------------  
  37. void __fastcall TForm1::Button2Click(TObject *Sender)  
  38. {  
  39.     Memo1->Lines->Clear();  
  40.     UnicodeString strName = JStringToString(testClass->getName());  
  41.     UnicodeString strAge = JStringToString(testClass->getAge()->toString());  
  42.     Memo1->Lines->Add(strName);  
  43.     Memo1->Lines->Add(strAge);  
  44. }  
  45. //---------------------------------------------------------------------------  
  46. void __fastcall TForm1::Button3Click(TObject *Sender)  
  47. {  
  48.     Memo1->Lines->Clear();  
  49. }  
  50. //---------------------------------------------------------------------------  

        在Android 4.1.1上測試成功。程式運作效果如圖所示:

C++ Builder XE7 調用JAVA的JAR檔案

        所有源碼及上面三個工具可在此下載下傳:

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

【特别感謝】

       1.  JarOrClass2Pas_FlyingWang工具的作者老貓

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

轉載:http://blog.csdn.net/realbay/article/details/42587705