Android上的Native以及JNI開發(1)

來源:互聯網
上載者:User

最近在Android上開發,主要是將以前Win32以及Windows Mobile上的一些程式庫移植到Andriod,並在Java層封裝二次開發介面。

雖然Google封裝的很徹底,但是Android畢竟是一個Linux系統,Linux相關的很多東西在Android的Native開發中是繞不開的。我一直很懶得碰Linux,多麼麻煩啊……當時vista出來沒多久,聽說ubuntu介面是如何如何華麗blabla的,遠不是以前的什麼紅帽紅旗Linux可比,於是第一次裝ubuntu,是8.04,其不支援我筆記本的HD2400顯卡……後來聽說它支援了,於是我裝了11.04,可惜此時換了一個新本,它又不支援我的nvidia/i5顯卡切換……

前幾年真正深入研究使用過的主要是ASP.NET平台和VC這兩個環境中的技術。現在託管界中說會.NET就和說會算1+1差不多,連歐美寫書的大師們都說.NET程式員整體水平是比Java低……他們怎麼就斷定學.NET的必定都是拖控制項流?……於是別人問我,我就說我寫C++的……當然最近確實一直寫C++

我發現Android上關於Native開發以及封裝的討論很少,因此邊做邊總結一些東西。Android NDK和SDK的安裝使用、Native開發方法、Android上的JNI等基本的東西已經有好多人寫過了好多東西,不再提了,在此主要討論完全會寫Hello Word之後,下一步遇到的各種問題和解決方案。

1. 從 VC 到 Android Native C++的一些改變

函數庫、語言相關的東西就不說了,看過C/C++各種開源庫原始碼的人都知道跨平台對代碼的要求,各種宏判斷,平台無關性的函數封裝,位元組對齊,大端小端的處理,我覺得SQLite的VFS是一段多麼美麗的跨平台代碼……就是寫的挺麻煩。

主要提一下編譯方面的異同

1.Windows下的DLL為了匯出函數,或者要寫def檔案,或者用醜陋的__declspec(dllexport)。Linux下並不需要類似的機制,預設情況下所有符號都是匯出的,而且也不需要.lib這類東西,你可以直接連結一個so,通過標頭檔定義使用裡面的類或函數。

2.Android的應用開發(即不理Android原始碼)中,Native編譯主要有兩種方式:1)使用NDK的ndk-build  2) 使用NDK安裝Android GCC工具鏈,自己寫makefile。

VC下估計用nmake編譯C++的人不多吧,VC總是智能的編譯工程裡的所有.cpp,傻瓜式的IDE。NDK提供的這兩種編譯方式相關的問題之後一點點的總結。

3.Android為了保證後續版本的相容性,在NDK中僅提供極少數的穩定C++ API,真的是夠少的,不過好歹Linux標準C函數和標準的C++庫已經基本完備了。除了C函數和STL你還有更多要求?自己編譯吧...

4.調試真是一大難,Windows下GDB串連調試只成功過一次,剩下的都莫名其妙的卡死了。暫時先用日誌吧,反正也還算方便,因為是移植在Win32和WM上已經正常跑的庫,所以需要調試的東西不是很多。

2. Android.mk 與 Application.mk

NDK下的那幾頁協助文檔是必看的,整個NDK就那麼幾頁文檔再不看,光想上網搜搜入門教程是不行滴。

寫Android.mk的時候還是遇到了幾個小陷阱的。

1. 路徑問題。各種mk下千萬不要寫/cygdrive/....這樣的路徑。Win下開發Android,NDK是要求使用cygwin的。但是最終啟動並執行編譯器gcc之類的還是.exe的Windows程式。mk裡還是要寫Windows路徑的,可以接受的形式諸如 /C:/NDK/xxxxx 或直接 C:/NDK/xxx,注意斜杠的方向

2.LOCAL_PATH := $(call my-dir)這句,陷阱。所以說一定要仔細看那幾頁文檔。$(call my-dir)返回得實際不是【當前mk檔案的路徑】,而是【最後開啟的mk檔案的路徑】,如下就會出錯的

LOCAL_PATH := $(call my-dir)

include $(PROJECT_PATH)/prebuilt.mk

.........

這樣用的時候,LOCAL_PATH可能在prebuilt.mk中被改寫

include $(PROJECT_PATH)/prebuilt.mk

LOCAL_PATH := $(call my-dir)

.........

這樣用的時候,LOCAL_PATH實際獲得的是prebuilt.mk的路徑

mk實際是makefile的一部分,可以參考NDK裡面內建的一些庫的Android.mk,其實寫法很靈活的

3. 注意使用ndk-build時,ndk-build直接找 jni/Android.mk,所有在此mk中包含的mk也會被加入,但是編譯並不是發生在$(BUILD_SHARED_LIBRARY)這句執行時,這句只是記一下一會兒要編譯這個庫。一直到所有mk執行完,ndk-build才開始編譯各個庫,所以想在mk中加入拷貝編譯好的庫到指定位置等指令的想法只是在做夢,好吧我就做過這個夢,不過最終還是另寫編譯指令碼完成

3. 中文編碼問題

NDK上的中文編碼問題絕對是一個大老虎,至少比紙老虎強一點,皮紙老虎吧……

實際上不用強調”中文“編碼,這就是單純的不同字元集轉換問題。

首先,Android2.2以前不支援wchar_t,好吧現在的確支援wchar_t了,不過這又如何,GCC下wchar_t是坑爹的4位元組,不是2位元組!怪不得你看各種開源庫各種不使用wchar_t,人家都直接用void*或者unsigned short。JNI中的jchar也是unsigned short,所以wchar_t純粹就是坑爹用的。

雖然可以用編譯指令-fshort-wchar強制wchar_t使用2位元組,不過這樣與其他庫連結的時候就會收到無數的警告……除非你保證你遇到的所有庫(包括C/C++標準庫)都是用這個指令編譯的。我試過一個犀利無比的WCHAR16定義,用於自動選擇最合適的類型,保證WCHAR16總是2位元組字元:

template<int>struct tag_auto_WCHAR_CHOOSER;template<>struct tag_auto_WCHAR_CHOOSER<4> {typedef unsigned short WCHAR16;};template<>struct tag_auto_WCHAR_CHOOSER<2> {typedef unsigned short WCHAR16;};typedef tag_auto_WCHAR_CHOOSER<sizeof(wchar_t)>::WCHAR16 WCHAR16;

不過GCC下如此不能保證做到 WCHAR16與unsigned short用於同參數簽名的重載函數,而我就是要重載,那麼wchar_t對我就無用了,拋棄吧

好吧有點跑題了。。。

首先是原始碼檔案的編碼問題:NDK下C++的char*預設編碼是UTF-8,但是你如果這樣寫: const char* szChina = "中國", 那麼就天知道什麼編碼了。預設情況下,如果你的該代碼檔案本身使用GBK,則szChina裡就是GBK編碼,如果代碼檔案是UTF-8, szChina就也是UTF-8。你非要問如果代碼檔案是UTF-16?我沒試,不過如果你的代碼能編譯過,想來szChina就會是UTF-8,原因嗎,說到這裡了你們懂得。如果你不懂,你可以先找
MBCS/UNICODE教程,再找GBK/UTF-8/UTF16的編碼規則及其與Unicode的關係教程,再找 UCS-2/UTF-16LE/UTF-16BE區別分析,最後看GCC對於不同編碼源檔案的處理,然後就一定已經懂了

編碼轉換:NDK下沒提供任何直接的編碼轉換方法,不過你可以編譯一個十分著名的庫,iconv,當然要寫Android.mk,不過你可以下載大好人hgl868已經改好了的……編譯後稍微有點大,900多K……不過去掉除了UTF-8,UTF-16LE,GBK之外的其他編碼庫後,iconv能精簡到200K……至於使用,剛才大好人家的傳送門點擊開啟連結

至於傳回Java轉換的方法,還是省省吧……使用Android內部的那個轉換庫?你保證你用這個能繼續正常在Android 4.0上運行?

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.