Android Studio 3.5 JNI (ndk-build)

记录下 Android Studio 嵌入 C 代码的过程,使用 ndk-build.
当前环境:Android Studio 3.51 NDK 20.1

创建 JNI 文件夹
Android结构下,直接在项目右键,选择 New - Folder - JNI Folder ,对话框直接点击 Finish 即可方便地在默认位置创建 jni 文件夹用于存放 c 源码。默认位置在 app/src/main/jni.
Android Studio 3.5 JNI (ndk-build)_第1张图片
创建 Java 类

package cn.sh.changxing.myled;

public class JniLib {
    static {
        System.loadLibrary("JniLib");
    }
    public native int led_open();
    public native int led_close();
    public native int ledIoctl(int num, int en);
}

生成头文件 (.h)
Android Studio 3.5 JNI (ndk-build)_第2张图片
这边可以在External Tools中配置:
每次都这样搞一遍很麻烦,我们可以配置一下扩展工具,这样一劳永逸。

点击File - Setting - Tools - External Tools 打开外部工具配置页,点击 + 新建一个工具。

先起个名字叫,这里叫做 javah.

Program: J D K P a t h JDKPath JDKPath\bin\javah.exe
Arguments: -classpath . -jni -d M o d u l e F i l e D i r ModuleFileDir ModuleFileDir\src\main\jni F i l e C l a s s FileClass FileClass
Working directory: M o d u l e F i l e D i r ModuleFileDir ModuleFileDir\src\main\Java
(上面三行直接复制添加)点击 OK 保存后就新建了一个工具。此时我们右击 JniTest.java,在菜单中选择 External Tools - javah 就可以快速生成头文件并放到 jni 目录。

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class cn_sh_changxing_myled_JniLib */

#ifndef _Included_cn_sh_changxing_myled_JniLib
#define _Included_cn_sh_changxing_myled_JniLib
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     cn_sh_changxing_myled_JniLib
 * Method:    led_open
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_cn_sh_changxing_myled_JniLib_led_1open
  (JNIEnv *, jobject);

/*
 * Class:     cn_sh_changxing_myled_JniLib
 * Method:    led_close
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_cn_sh_changxing_myled_JniLib_led_1close
  (JNIEnv *, jobject);

/*
 * Class:     cn_sh_changxing_myled_JniLib
 * Method:    ledIoctl
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_cn_sh_changxing_myled_JniLib_ledIoctl
  (JNIEnv *, jobject, jint, jint);

#ifdef __cplusplus
}
#endif
#endif

编写 c 代码

//
// Created by cheng on 2019/10/26.
//
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include "cn_sh_changxing_myled_JniLib.h"

    #undef  TCSAFLUSH
    #define TCSAFLUSH  TCSETSF
    #ifndef _TERMIOS_H_
    #define _TERMIOS_H_
    #endif

    int fd=0;
        JNIEXPORT jint JNICALL Java_cn_sh_changxing_myled_JniLib_led_1open
          (JNIEnv *env, jobject obj)
          {
            if(fd<=0)fd = open("/dev/leds", O_RDWR|O_NDELAY|O_NOCTTY);
            if(fd <=0 )__android_log_print(ANDROID_LOG_INFO, "serial", "open /dev/leds Error");
            else __android_log_print(ANDROID_LOG_INFO, "serial", "open /dev/leds Sucess fd=%d",fd);
          }

        /*
         * Class:     com_topeet_ledtest_led
         * Method:    Close
         * Signature: ()I
         */
        JNIEXPORT jint JNICALL Java_cn_sh_changxing_myled_JniLib_led_1close
          (JNIEnv *env, jobject obj)
          {
            if(fd > 0)close(fd);
          }

        /*
         * Class:     com_topeet_ledtest_led
         * Method:    Ioctl
         * Signature: ()I
         */
        JNIEXPORT jint JNICALL Java_cn_sh_changxing_myled_JniLib_ledIoctl
          (JNIEnv *env, jobject obj, jint num, jint en)
          {
            ioctl(fd, en, num);
          }

创建 mk 文件
mk 文件用于告诉 ndk-build 该如何编译 c 源码,详情见官方指南。
在 jni 目录下创建 Android.mk:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS += -llog
LOCAL_LDLIBS +=-lm
LOCAL_MODULE := JniLib
LOCAL_SRC_FILES =: JniLib.c
include $(BUILD_SHARED_LIBRARY)

其中 LOCAL_SRC_FILES 列出了所有要编译的 c 源码文件
然后创建 Application.mk:

APP_MODULES := JniLib
APP_ABI := all

在 module 的 build.gradle 里,amndroid.defaultConfig 下加入下面配置:
Android Studio 3.5 JNI (ndk-build)_第3张图片
代码:

        ndk{
            moduleName "JniLib"
            //abiFilters \"armeabi-v7a", "x86" //输出指定abi下的so库
        }
        sourceSets.main{
            jni.srcDirs = []
            jniLibs.srcDir "src/main/libs"
        }

编译:
编译需要使用 ndk-build,其位于 ndk 目录下。如果要直接在命令行使用需要添加环境变量。类似的,为了方便我也添加了一个外部工具。
注意改成你自己的目录。

Program: D:\Android_sdk\ndk\20.0.5594570\build\ndk-build.cmd
Working directory: F:\android_project\Myled

任意找个第地方右击,选择 External Tools - ndk-build 即可编译 c 源码。成功后可以看见创建了 libs 目录,里面包含了不同平台下的 so 文件。

运行
最后修改下 Activity 的代码:

package cn.sh.changxing.myled;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    private JniLib jniTest = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        jniTest = new JniLib();
        jniTest.led_open();
    }
    public void led1_en(View view) {
        //Toast.makeText(this, "test", Toast.LENGTH_SHORT).show();
        jniTest.ledIoctl(0, 1);
    }

    public void led1_off(View view) {
        jniTest.ledIoctl(0, 0);
    }

    public void led2_en(View view) {
        jniTest.ledIoctl(1, 1);
    }

    public void led2_off(View view) {
        jniTest.ledIoctl(1, 0);
    }
    
}

参考:https://blog.csdn.net/slaughteryou/article/details/88235000

你可能感兴趣的:(Android,studio,JNI)