一直想寫一份技術文檔,但因為自感能力有限而無從下筆,近期做了個關於Android平台下實現與C語言的通訊來操作藍牙模塊的項目,中間碰到了很多問題,也在網上查了很多資料,在完畢主要功能后。也有一些人在網上問我一些問題。這里寫下這篇文檔算是一個階段性的總結。
假設反響好。興許將會發上Android Stub與新版Android HAL的學習文檔。
因為藍牙模塊是串口通訊機制。使用C語言來訪問,而Android的應用層採用Java。無法直接操作硬件。故使用JNI的技術實現主要功能。Android的JNI應該屬於Android HAL的一部分,因為Android的HAL機制眼下還沒全然摸索透,所以這里的程序架構算是老版本號的HAL機制。程序架構例如以下圖。
一、 什么是JNI?
JNI是Java Native Interface的縮寫,中文為JAVA本地調用。從Java1.1開始,Java Native Interface(JNI)標准成為java平台的一部分,它同意Java代碼和其它語言寫的代碼進行交互。
JNI一開始是為了本地已編譯語言。尤其是C和C++而設計的,可是它並最好還是礙你使用其它語言,僅僅要調用約定受支持就能夠了。(以上內容摘自百度百科)
二、 怎樣使用JNI?
1、在使用JNI之前,你要確保你的電腦中安裝下面軟件環境:
Android SDK :版本號與你硬件測試環境版本號同樣,在Google的Android官網下載
Android NDK :用於編譯C文件為.so的共享庫。假設你是在Linux下進行開發而又具有Android的全然SDK,則不須要
Cygwin :用於編譯C文件
Android 開發環境 :android開發環境的配置網上一大堆,這里不再贅述
2、程序中因為僅僅用到Java調C,而不須要C調Java,所以在應用層調C的函數非常easy,僅僅須要在一個方法前增加nativekeyword(native的方法不能有方法體),然后將編譯的共享庫導入就可以。
例如以下:
public class BluetoothJNI {
static{
System.loadLibrary("jni");
}
public native static int bluetoothOn(String strAT);
public native static void bluetoothOff(String strAT);
public native static String readSerial();
public native static void write(String strAT);
}
3、Eclipse在保存project后,會自己主動把Java文件編譯為class文件。我們使用javah命令把class文件編譯成C頭文件。例如以下:
運行此命令后將會在project的bin文件夾下生成一個.h的C頭文件。
頭文件里會生成相應Java native方法的函數聲明。
新建一個與頭文件同名的C文件並實現全部函數。
4、因為Android的底層是基於Linux內核。所以一些Windows下的系統函數不可用。Linux下的串口通訊文章網上有非常多,此處代碼繁多,就不貼出來了。。我們在C文件里引入jni.h與剛生成的頭文件以確保JNI能調用。注意:整個程序的核心部分便是在此處,C語言與藍牙模塊的串口通訊處,我在此處碰到的問題也是最多的。
三、編譯C文件
1、在Android-ndk-r5b\samples\下新建文件夾Bluetooth\jni,將C文件與頭文件復制過來,新建Makefile。
例如以下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_LDLIBS := -lm -llog
LOCAL_MODULE := jni
LOCAL_SRC_FILES := com_android_semisky_bluetooth_util_BluetoothJNI.c
include $(BUILD_SHARED_LIBRARY)
2、打開Cygwin bash shell,進入Bluetooth文件夾。運行ndk-build進行編譯。
3、將libs/armeabi下生成的libjni.so文件拷入到Androidproject的libs/armeabi文件夾下。安裝apk到開發板。運行程序。
四、可能出現的問題
1、串口讀寫權限的問題
網上的方法是在Java中獲取su賬號來改權限或者在init.rc中加入命令來改動權限最后編譯成img燒錄進開發板。而這兩種方法我都沒成功,最后沒辦法在dos下運行shell命令來改動
2、C文件的串口讀寫問題
我不知道是我的程序有問題還是藍牙模塊的問題,在藍牙模塊返回數據稍大的時候。會出現數據有時返回有時不返回的情況。
3、亂碼問題
藍牙返回的數據時而出現亂碼,未解決。
4、串口號的問題
假設你open的時候返回的fd小於1,確保你的開發板串口號是否正確。協議是否正確,權限是否改動。
5、最大大大的問題
讀取串口代碼段的算法問題,優化問題,不然數據會返回不正常。