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
- public class Test {
- // 名字屬性
- private String name;
- // 年齡屬性
- private Integer age;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Integer getAge() {
- return age;
- }
- public void setAge(Integer age) {
- this.age = age;
- }
- public static void main(String[] args) {
- // 執行個體化類
- Test test = new Test();
- // 設定預設名字
- test.setName("Delphi");
- // 設定預設年齡
- test.setAge(100);
- }
- }
按上面所述,根據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
- #include <Androidapi.Helpers.hpp> //StringToJString函數
- #include <Androidapi.JNI.JavaTypes.hpp>
- //---------------------------------------------------------------------------
- void __fastcall TForm1::FormCreate(TObject *Sender)
- {
- //建立執行個體(這是C++ Builder建立Java類的方法)
- testClass = TJTest::JavaClass->init();
- //初始化
- testClass->setName(StringToJString(L"張三"));
- testClass->setAge(TJInteger::JavaClass->init(StringToJString(L"20")));
- }
- //---------------------------------------------------------------------------
- void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
- {
- //釋放執行個體
- testClass = NULL;
- }
- //---------------------------------------------------------------------------
- void __fastcall TForm1::Button1Click(TObject *Sender)
- {
- UnicodeString strName = Edit1->Text.Trim();
- UnicodeString strAge = Edit2->Text.Trim();
- if(strName == "")
- {
- ShowMessage(L"姓名不能為空!");
- return;
- }
- if(strAge == "")
- {
- ShowMessage(L"年齡不能為空!");
- return;
- }
- testClass->setName(StringToJString(strName));
- testClass->setAge(TJInteger::JavaClass->init(StringToJString(strAge)));
- }
- //---------------------------------------------------------------------------
- void __fastcall TForm1::Button2Click(TObject *Sender)
- {
- Memo1->Lines->Clear();
- UnicodeString strName = JStringToString(testClass->getName());
- UnicodeString strAge = JStringToString(testClass->getAge()->toString());
- Memo1->Lines->Add(strName);
- Memo1->Lines->Add(strAge);
- }
- //---------------------------------------------------------------------------
- void __fastcall TForm1::Button3Click(TObject *Sender)
- {
- Memo1->Lines->Clear();
- }
- //---------------------------------------------------------------------------
在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