1. 需求
最近有項目需要實現(xiàn)windows機器和Android開發(fā)版進(jìn)行UART串口通信刊头,經(jīng)過3天查找嘗試豁延,特記錄一下最終方案,希望之后的同行少走彎路腔召,最后在git上回開源我最終的方案希望大家支持轧葛。
2. 環(huán)境
Android 3.0.1
Gradle 4.1
ARM開發(fā)版 : RK3399
PC機器:Win10
開發(fā)機器:MAC 10.13.3
3. 解決方法
-
Android Things
Android Things 谷歌于2018年5月發(fā)布1.0正式版搂抒,讓開發(fā)者可以使用Android開發(fā)工具開發(fā)嵌入式設(shè)備。需要比較高的Android API支持 ( >24 )尿扯。很多樹莓派3用這個做開發(fā)求晶,普遍應(yīng)用于物聯(lián)網(wǎng)領(lǐng)域。
因為是官方的原因衷笋,感覺應(yīng)該靠譜些誉帅,且集成方便,Git上參考了https://github.com/androidthings/sample-uartloopback這個項目右莱。但是,每個卵用档插。簡直白折騰慢蜓。首先需要API 27以上的設(shè)備,現(xiàn)在手上的開發(fā)版很少有Android 8.0以上版本的郭膛。(為此晨抡,還刷了固件,做了嘗試)最大的坑是:這個項目最后基本安裝不到國內(nèi)的Android 系統(tǒng)上,原因:需要Google Service耘柱。強依賴
<uses-library android:name="com.google.android.things"/>
如捅。考慮日后上線產(chǎn)品的維護(hù)调煎,果斷放棄镜遣。 -
android-serialport-api,是兩個Eclipse項目士袄,導(dǎo)入進(jìn)去之后悲关,設(shè)置好設(shè)備和波特律之后直接就可以使用,也看到別人分享的項目經(jīng)驗娄柳,這個可用寓辱。具體講解可以參考這篇文章https://blog.csdn.net/qiwenmingshiwo/article/details/49557889,兩個項目分別是編譯底層JNI項目android-sercd赤拒,另一個側(cè)重根據(jù)JNI的API實現(xiàn)Java端功能秫筏。如果只實現(xiàn)功能就看android-serialport-api
缺點:項目比較老,需要JNI編譯
經(jīng)過嘗試導(dǎo)入庫中已編譯好的so挎挖,運行可以跑通UART通信这敬。但遇到了一下幾個‘坑’ 導(dǎo)入JNI的時候注意事項就不說了,包名這些的都不能改肋乍。
Run 使用已有的so的項目時候會報錯
dlopen failed: "has text relocations"
遇到無法獲取port鹅颊,請重新配置Serial port類似的報錯
解決方法:
-
關(guān)于dlopen failed: "has text relocations" 的簡單解決辦法,降級targetSdkVersion 23一下墓造。Android 6.0 機制的問題堪伍。根本解決版本使用高版本的NDK重新編譯so來解決,后文中我重新編譯了一把觅闽。這里是gradle文件修改的關(guān)鍵地方帝雇。
compileSdkVersion 22 defaultConfig { applicationId "com.attrsc.braincs.androidserialport" minSdkVersion 21 targetSdkVersion 22 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" ndk { abiFilters "armeabi-v7a" } }
-
關(guān)于無法獲取port的報錯
一開始我懷疑是我的so沒有加載成功,后來斷點發(fā)現(xiàn)無法從sharePreference中獲取到設(shè)置的 Device和baudrates蛉拙。修改
SerialPortPreferences
Activity如下:public class SerialPortPreferences extends PreferenceActivity { private Application mApplication; private SerialPortFinder mSerialPortFinder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mApplication = (Application) getApplication(); mSerialPortFinder = mApplication.mSerialPortFinder; addPreferencesFromResource(R.xml.serial_port_preferences); final SharedPreferences sp = getSharedPreferences("android_serialport_api.sample_preferences", MODE_PRIVATE); // Devices final ListPreference devices = (ListPreference)findPreference("DEVICE"); String[] entries = mSerialPortFinder.getAllDevices(); String[] entryValues = mSerialPortFinder.getAllDevicesPath(); devices.setEntries(entries); devices.setEntryValues(entryValues); devices.setSummary(devices.getValue()); devices.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { public boolean onPreferenceChange(Preference preference, Object newValue) { preference.setSummary((String)newValue); sp.edit().putString("DEVICE",(String) newValue).apply();//此處添加 return true; } }); // Baud rates final ListPreference baudrates = (ListPreference)findPreference("BAUDRATE"); baudrates.setSummary(baudrates.getValue()); baudrates.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { public boolean onPreferenceChange(Preference preference, Object newValue) { preference.setSummary((String)newValue); sp.edit().putString("BAUDRATE",(String) newValue).apply();//此處添加 return true; } }); } } ?```
4. 終極解決方案
先上圖
由于android-serialport-api項目中的so使用較old的ndk編譯尸闸,所以在對于Android 6.0 以上版本兼容的時候會報錯dlopen failed: "has text relocations"
。且使用的mk進(jìn)行編譯孕锄,特升級為用cmake編譯吮廉。
升級
android-serialport-api
ndk 17.0.4xxx jni編譯
cmake 編譯鏈
EClipse項目-> Android Studio項目
項目結(jié)構(gòu):
.
├── AndroidSerialLibrary.iml
├── androidserial
│ ├── CMakeLists.txt
│ ├── androidserial.iml
│ ├── build
│ ├── build.gradle
│ ├── libs
│ ├── proguard-rules.pro
│ └── src
├── app
│ ├── app.iml
│ ├── build
│ ├── build.gradle
│ ├── libs
│ ├── proguard-rules.pro
│ └── src
├── build
│ └── android-profile
├── build.gradle
├── gradle
│ └── wrapper
├── gradle.properties
├── gradlew
├── gradlew.bat
├── local.properties
└── settings.gradle
app對應(yīng)原項目中的各個Activity, androidserial 是module 對應(yīng)編譯之前的so畸肆,還有API的封裝宦芦。可以直接引用androidserial轴脐,調(diào)用方法參考app目錄下的activity调卑。
注意
關(guān)于權(quán)限抡砂!
當(dāng)接入開發(fā)板后如果發(fā)現(xiàn) Error You do not have read/write permission to the serial port
需要root 權(quán)限,在開發(fā)者模式中開啟root 權(quán)限 adb和應(yīng)用
使用一下命令開啟Android對串口的讀寫權(quán)限
? adb shell
rk3399_firefly_mid:/ $ su
rk3399_firefly_mid:/ # chmod 777 /dev/ttyS4
rk3399_firefly_mid:/ # setenforce 0
rk3399_firefly_mid:/ #
setenforce 0
: 關(guān)閉防火墻恬涧,有人說關(guān)鍵是這注益,但是我的環(huán)境不用關(guān)閉,只要給權(quán)限就可以
注意
關(guān)于ttyS1 - 6 ttyS1 - 6 對應(yīng)的是 UART 串口1-6 一般都是一一對應(yīng)的溯捆。這個具體要看一下開發(fā)板的說明丑搔。
記錄的比較糙,還請見諒现使,如有問題請留言低匙,我看到后肯定回復(fù)。項目主要看結(jié)構(gòu)碳锈,剩下的都是復(fù)制黏貼的事顽冶。git地址:https://github.com/braincs/AndroidSerialLibrary