經過Java Native Interface (JNI)入門 -- 觀念篇及Java Native Interface (JNI) 實戰篇後,延續著前兩篇的觀念第三篇繼續討論在Android上實作,本篇主要學習目的是在Android上實現針對UART的傳輸題目就沿用Hello系列稱為HelloUart。
執行環境:
A.開發平台
DMA-6410L or DMA-6410XP
Kernel 2.6.29
Android 2.1 (Eclair)
B.開發環境
個人電腦
Ubuntu 10.10
Eclipse 3.5.2
Android NDK, r5b
C.測試環境
個人電腦 (Win7)-DMAComDebuger.exe
DMA-6410
GPS接收器
建立一個HelloUart專案,程式部分架構如下圖所示:
其中MainActivity.java是主要,Uart2C.java的部分是將Java對C的部分獨立出來寫成一個java,我覺得將這部分獨立這樣寫程式的方式很好,主要是參考一些Demo程式而來。
另外jni目錄夾要自己建立,裡面的必須要自行建立Android.mk及hello-uart.c兩個檔案;
還有libs是由NDK所自動產生詳見先前所撰寫的"第一支Android NDK程式--HelloJni"。
程式說明:
1. main.xml 使用 RelativeLayout (相對佈局)方式,用到有:
ScrollView : @+id/uart_scrollview
TextView : @+id/uart_view
EditText : @+id/uart_edit
Spinner : @+id/uart_select 、 @+id/uart_mode
Button : @+id/uart_button0 (OPEN) 、 @+id/uart_button1 (CLEAR) 、 @+id/uart_button2 (CLOSE) 、 @+id/uart_button3 (EXIT) 、 @+id/uart_button4 (SEND)
這部份算基本功礙於篇幅這部分就忽略說明,我所建立的執行畫面如下:
2.MainActivity.java
主要使用 timer.schedule(task, 1000, 100)這行作為訊息接收;
透過 Spinner 來選擇串列埠及Baud rate;
Button0 處理uart的開啟
Button1 清除接收畫面
Button2 處理uart的關閉
Button3 處理程式關閉
Button4 處理送出訊息
3.Uart2C.java
主要是呼叫hello-uart.c,並宣告native方法。
4.Android.mk
在jni目錄下建立了一隻hello-uart.c,因此編輯一個android.mk如下:
5.hello-uart.c
這裡須注意的是一定要按照Android規範,例如:
JNIEXPORT jint JNICALL Java_idv_android_hellouart_Uart2C_openUart(JNIEnv *env,jobject mc, jint i)
在Java_..._openUart部分一定要照下列規範否則編譯後Android程式會找不到相對應的native函數名,例如:
Java_Android Package Name_類名稱_native函數名,並注意底線及大小寫
Android Package Name : idv_android_hellouart
類名稱 : Uart2C
native函數名 : openUart
以下是程式內容,
程式開頭:
開啟UART
關閉UART
設定UART
送出訊息
接收訊息
編譯程式:
上述程式完成後存檔,由於這次我的開發環境在Ubuntu下,所以在編譯C的部分我使用的方法如下:
編輯 .profile 增加如下內容:
#Android NDK
SDK_ROOT= android-sdk-linux_x86 所在目錄,須注意要有可讀寫權限
NDK_ROOT= android-ndk-r5b 所在目錄,須注意要有可讀寫權限
PATH=$SDK_ROOT/tools:$NDK_ROOT:$PATH
NDK_Sample=$NDK_ROOT/samples
export PATH NDK_ROOT NDK_Sample
編輯完成後存檔後重新登入。
到程式所在目錄下執行ndk-build:
在Eclipse下執行Run把apk及so安裝至Android開發平台即完成。
執行結果:
下圖是執行後的畫面:
環境:
開發平台 <--> PL-2303 <--> GPS接收器
開發平台 <--> UART1 <--> GPS接收器
開發平台 <--> UART1 <--> Null modem 線(交叉線) <--> PC RS-232 ComPort <--> DMAComDebuger
以上是HelloUart程式內容及講解,這隻程式應該還有不少可以修正的Bug,我在執行時有時候開啟時會遇到VM abort導致跳出程式,絕大多看到的訊息時接受到亂碼所導致,這部分改良程式或測試環境後也許可以更好些。
所以各位如果遇到類似上述問題:
1.不要懷疑記得使用logcat來找問題;使用logcat至少可以解90%以上的問題。
2.建議使用 開發平台 <--> UART1 <--> Null modem 線(交叉線) <--> PC RS-232 ComPort <--> 超級終端機 or DMAComDebuger(DMA-6410XP所附光碟中) 的環境來測試傳送與接收,與PC連結 Baud rate 建議設9600或115200。
3.如果要測試 開發平台 <--> PL-2303 要先確認 kernel是否載入PL-2303相關驅動,否則建議使用第2項方式進行測試。
4.HelloUart是參考DMA-6410XP所附光碟中原始碼,詳見光碟內容。
參考資料:
1.DMA-6410XP所附光碟
2.在Android下建立RS232通訊應用程式心得分享
http://cheng-min-i-taiwan.blogspot.com/2010/04/androidrs232.html
==============延伸閱讀=====================
[ Android RS232 ] 在Android系統下實作RS232應用程式
==============相關閱讀=====================
Android Bluetooth 應用之 HelloBTUart(RS-232)-->-->-->-->-->-->-->-->-->-->-->-->-->
Android USB 應用之 HelloUsbUart(RS-232)
感謝蚊子提供這麼棒的文章
回覆刪除您好
回覆刪除最近參考您的文章學習JNI在Android中的應用
作為我之後再Android開發板上的RS232應用的學習
程式大致上沒甚麼問題
唯獨res\layout\main.xml我沒辦法像您的範例一樣將每個物件
分配的那麼漂亮
可否跟您索取程式碼供我學習
另外想請問您在這個範例中
於AndroidManifest.xml檔案中有需要修改的地方嗎?
我的信箱是fatalcord@gmail.com
由衷感謝
另外我依照您的程式範本寫了一個專案
回覆刪除但在模擬器執行時按下OPEN程式就會強制關閉
請問這是正常的現象嗎?
初學JNI,有許多不懂的地方
如果有造成您的不便,深感抱歉
我的經驗,強制關閉的話大多會出現的問題:
回覆刪除1.可能找不到so檔案
2.所呼叫的native參數在so檔案內對應不到,詳見文章中5.hello-uart.c說明,我的經驗通常是大小寫錯誤了。
3.Activity輸出(顯示)錯誤,例如傳回值為int但顯示為String之類。
4.使用C++(副檔名為cpp),主要要多寫一個ON_Load程式,這部分過幾天我分享文章出來說明。
其他部分,建議用logcat+Log來追中~因為我就遇過我的RS-232干擾後收到非ASCII的亂碼導致程式中斷。
作者已經移除這則留言。
回覆刪除您好,想請教一下
回覆刪除若將開發平台轉移至智慧型手機上
應該如何實現呢??
因為智慧型手機似乎不能看到目前將設備辨識為何個comport
所以想向您請教一下
您好:
回覆刪除關於在智慧型手機做類似的功能,手機原廠大多不會提供相關硬體對應的資訊,況且手機廠商所提供的核心驅動部分我們也無法進行客製或修改,所以類似的功能要在手機上實作通常機會不大;不過在手機上同樣可以使用JNI,如果要一定要在手機上使用RS-232功能的話,建議使用IOIO會簡單些,不妨試試看。
作者已經移除這則留言。
回覆刪除作者已經移除這則留言。
回覆刪除板主您好:有幾個問題想請教一下;我所使用的開發平台為華亨的6410,我按照文章中所教的步驟,已經把APK安裝到平台上了,但是設定好COM PORT與鮑率之後,都無法開啟串列埠,請問這是什麼情況呢?
回覆刪除這可能會是系統中沒有COM Port您可以查詢看看/dev目錄下是否有您指定的tty...例如ttyS0,ttyS1 or ttyUSB等
回覆刪除請問如果我資料夾是放在eclipse的workspace 要怎麼設定 .profile ?
回覆刪除才能產生.so檔呢
我的作法很簡單
刪除$ cd /cygdrive/c/..../Workspace/HelloUart
$ ndk-build
Cygwin : Generating dependency file converter script
Compile thumb : hello-uart <= hello-uart.c
SharedLibrary : libhello-uart.so
Install : libhello-uart.so => libs/armeabi/libhello-uart.so
您試試看....
蚊子您好:請教一下關於JNI傳送字元陣列顯示於EditText上的問題,
回覆刪除目前寫一個簡單的JNI傳送於EditText上作顯示,JNI的程式如下:
Method-1:
char buf[3]={3,22,11};
return (*env)->NewStringUTF(env, buf);
Method-2:
jbyteArray LTH;
char lth[32];
int i,j;
LTH = (*env)->NewByteArray(env, 32);
for(i=0;i<32;i++){
lth[i] = '12';
}
for(j=0;j<32;j++){
(*env)->SetByteArrayRegion(env, LTH, j, 1, lth[j]);
}
return LTH;
以上兩種方法在EditText上作顯示時,都會以亂碼的方式呈現,
請教蚊子大大是否有其他更好的方式作為顯示呢!!
因為你程式裡面用的是char試看看return不要傳回用String,用NewCharArray看看(或其他)。可以Google搜尋一下"The Java Native Interface Programmer's Guide and Specification"這個PDF裡面可以找到。
刪除嗯 上網看一下它們是使用ByteArray的方式,我在看試試看,謝謝蚊子大大歐!!
刪除板主您好:
回覆刪除有個問題想請教一下
在 open uart port時, 是否 /dev/ttyS1 的權限要為 666才能開啟
否則是否 open後會回傳 -1
如果是一般手機沒 root權限是否 open就不能用了 ?
謝謝