Android串口驱动实现

参考文章:Android串口通信:抱歉,学会它真的可以为所欲为 - 掘金

官网文章:https://code.google.com/archive/p/android-serialport-api/

官网代码demo:https://github.com/cepr/android-serialport-api

个人开发者的demo:https://github.com/AIlll/AndroidSerialPort

个人开发者GitHub中的demo:https://github.com/licheedev/Android-SerialPort-API

hello-jni 项目:

gitlib : https://ce4.midea.com:8078/huangjy138/Android_base_test/tree/master/JNI_test

hello-jni项目用最简单的方法,生成了一个.so文件,通过加载.so文件(也就是linux动态库)的方式,让程序能调用C代码。

jni文件夹中,除了hello-jni.c以外还有两个文件:

  • Android.mk : 编译.so文件的Makefile,

  • Application.mk :注明编译成什么芯片架构,选择all就是全部,所有支持的abi都生成,像树莓派用的是armeabi-v7a

ndk-build工具链生成.so文件:

有了上述的3个文件,我们就可以生成.so文件,具体办法为:

#cd到jni文件夹,执行ndk-build,就可以在libs文件夹中找到不同abi的`.so`文件,而树莓派用到的是armeabi-v7a文件夹下的libhello-jni.so
​
cd D:\code\android\Android_base_test\androidserialportapi\app\jni
​
# 本机ndk-build工具默认路径:  D:\MyData\huangjy138\AppData\Local\Android\Sdk\ndk-bundle\build\ndk-build
​
D:\MyData\huangjy138\AppData\Local\Android\Sdk\ndk-bundle\build\ndk-build
​

使用.so动态库的方法:

  • 在app下的build.gradle中添加ndk相关配置

    defaultConfig {
        applicationId "com.example.jni_test"
        minSdkVersion 27
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
    ​
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        
        ## 添加NDK的描述。
        ndk {
            moduleName "hello-jni"
            ldLibs "log", "z", "m"
            abiFilters "armeabi", "armeabi-v7a", "x86"
        }
    }
  • 调用hello-jni.c文件中的函数前先执行:

    public class MainActivity extends AppCompatActivity {
    ​
    ​
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    ​
            TextView  tv = (TextView)findViewById(R.id.test1);
            tv.setText( stringFromJNI() );//调用函数
    ​
        }
    ​
        public native String  stringFromJNI();//声明函数是原生函数调用。
    ​
        static {
            System.loadLibrary("hello-jni"); //加载动态库
        }
    }
  • 生成对应的.h文件

    # 在此之前,请确保自己的JDK环境已经配置好。
    javah -jni com.example.jni_test.MainActivity  # 注意目录结构。
    ​
    # com_example_jni_test_MainActivity.h 就是生成的.h文件,里面主要描述了
    ​
    # 要确保com_example_jni_test_MainActivity.h里的函数声明,需要在hellop-jni.c中实现。
    # 如果添加了新的函数,需要重新生成.so文件。

程序运行

至此,我们已经实现了,在Android应用层,调用linux 动态库的所有步骤。

下面,我们试着运行程序:

运行时出现找不到lib的错误,因此需要手动的安装lib。

按理说,应该有办法直接加载的,但是实际上并不能,我们看一下这里的报错

## 报错提示
java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.example.jni_test-qgKx-PgXfuo3F9SVbseMPA==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.jni_test-qgKx-PgXfuo3F9SVbseMPA==/lib/arm, /system/lib, /system/product/lib, /vendor/lib]]] couldn't find "libhello-jni.so"
​
## 从报错提示可以看出,我们需要libhello-jni.so出现在这些路径中:[/data/app/com.example.jni_test-qgKx-PgXfuo3F9SVbseMPA==/lib/arm, /system/lib, /system/product/lib, /vendor/lib]]]
​
## 如果我们要打包发布时,驱动就直接放到/system/lib中即可,所有的应用程序都可以调用。
## 如果调试,我们先放在应用的目录下,但是每次运行时,应用所在的文件夹会有变化,所以每次修改代码后,需要重新push(其他目录是只读的不能被修改)
​

push 指令:

adb push D:\code\android\Android_base_test\JNI_test\app\libs\armeabi-v7a\libhello-jni.so /data/app/com.example.jni_test-vAVGdMirCc6J4JJlqoDUNQ==/lib/arm/libhello-jni.so 
# 注意修改权限。
chmod -R 777 libhello-jni.so

官方串口项目

参考文章:https://github.com/licheedev/Android-SerialPort-API

官网代码demo:https://github.com/cepr/android-serialport-api

同理根据官网提供的代码,我们可以直接调用,只要用刚才的方法,把C代码编译成.so库,我们就可以正常调用。

gitlib链接:https://ce4.midea.com:8078/huangjy138/Android_base_test/tree/master/androidserialportapi

push 指令:

adb push D:\code\android\Android_base_test\androidserialportapi\app\libs\armeabi-v7a\libserial_port.so /data/app/com.example.android_serialport_api-dBNRLlkz31N02HFvth0jeg==/lib/arm/libserial_port.so

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐