Android技术知识Android开发Android开发

Android Studio快速实现一个JNI示例

2018-12-03  本文已影响1人  kevinsong0810

前提:Android Studio 3.0,预先通过SDK Manager安装好CMake(生成so库的编译相关工具),3.6.4版

  1. 定义一个Java类,其中定义native方法,并调用System.loadLibrary加载so库
public class TestJni {
    static {
        System.loadLibrary("test-jni");
    }
    public static native String getStringFromNativeMethod();
}

测试调用的例子:

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // call native method, LogUtils是封装的Log类
        LogUtils.d("print: " + TestJni.getStringFromNativeMethod());
    }
}
  1. 通过javah指令生成C/C++头文件.h
    sudo javah -jni com.kevin.test.TestJni
    生成的头文件名称:com_kevin_test_TestJni.h,内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_kevin_test_TestJni */

#ifndef _Included_com_kevin_test_TestJni
#define _Included_com_kevin_test_TestJni
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_kevin_test_TestJni
 * Method:    getStringFromNativeMethod
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_kevin_test_TestJni_getStringFromNativeMethod
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

注意,javah前:
a. 需要先make project一次,生成TestJni.class文件
b. 先cd至命令执行的路径:app/build/intermediates/classes/debug,否则会找不到TestJni.class

  1. 复制头文件至源代码路径下面,例如:app/src/main/jni,并新建一个cpp文件,名字:com_kevin_test_TestJni.cpp,完成函数getStringFromNativeMethod的C++定义,如下:
#include "com_kevin_test_TestJni.h"

JNIEXPORT jstring JNICALL Java_com_kevin_test_TestJni_getStringFromNativeMethod
  (JNIEnv *env, jclass thiz) {
      return (*env).NewStringUTF("this is c++ code");
  }

注意:
这里C/C++都可以,C的source文件结尾为.c,C++的source文件结尾为.cpp,但是语法实现时不能有错,否则编译时会报错。这里选用C++

  1. Java代码,C++代码都准备完成后,这时要准备编译C++的CMakeList.txt,新建即可。作用是CMake工具的配置文件,必不可少。简单配置如下:
cmake_minimum_required(VERSION 3.4.1)

add_library( # Specifies the name of the library.
             test-jni
             # Sets the library as a shared library.
             SHARED
             # Provides a relative path to your source file(s).
             com_kevin_test_TestJni.cpp )

注意:这里定义了编译生成的库文件名字,test-jni,编译完成后,文件名称为:libtest-jni.so。

  1. 更新app下build.gradle文件,添加Cmake相关信息
android {
    ...
    defaultConfig {
        ...
        externalNativeBuild {
            cmake {
                abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a' // 定义编译的ABI类型,每种会编译生成一个对应的so库文件
            }
        }
    }
    ...
    externalNativeBuild {
        cmake {
            path 'src/main/jni/CMakeLists.txt'
        }
    }
}
  1. 重新编译新的Project,并安装至手机,运行。此时打印的日志:
    12-03 18:47:03.636 9016 9016 D kevintest: print: this is c++ code
    说明Activity运行时,调用native方法getStringFromNativeMethod成功,方法实现在libtest-jni.so库中。另外,可以通过Build->Anaylze APK,查看apk中,lib路径下已打包4个libtest-jni.so库,分别存放至arm64-v8a等文件夹下,提供不同的ABI支持

最后,附上示例Project结构的截图:




参考文档:https://developer.android.com/studio/projects/add-native-code#create-cmake-script


作者:kevin song,2018.12.3于南京建邺区

上一篇下一篇

猜你喜欢

热点阅读