NDK 是 Android 所提供的一个开发工具集,通过 NDK 可以在 Android 中更加方便的通过 JNI 来访问本地代码,比如 C 或者 C++。

相关概念

  1. 什么是交叉编译?
    交叉编译就是一个平台上生成另一个平台上可执行的代码。如在 x86 平台编译成可在 arm 平台运行的程序。
  2. JNI 是什么?
    它允许 Java 代码和其他语言写的代码进行交互,交互用到这个接口进行中转。
  3. JNI 实现流程
    编写 Java 类代码 — 编译成字节代码 — 产生 c 头文件 — 编写 JNI 实现代码 — 编译成连接库 — 运行程序

NDK 示例

  • 创建 Android 工程,工程名为 HelloNDK。

  • 在 MainActivity 中声明 native 方法

    public static native String getStringFromC();

  • 通过 javah 命令生成头文件

    javah 生成 Java 类对应的头文件必须要用到 javah 命令。
    -d 表示生成一个目录。
    …/jni 表示在当前目录的上一层目录,当前在Java目录下,那么它的上层目录就是 main 目录。
    com.example.hellondk.MainActivity 完整类名

  • 实现 JNI 方法,在 jni 目录下创建 hello.c 文件,代码如下。

#include#include#include "com_example_hellondk_MainActivity.h"/** * JNIEnv*  表示一个指向 JNI 环境的指针,可以通过它来访问 JNI 提供的借口方法 * JNIEXPORT  JNICALL 是 JNI 所定义的宏,可以在 jni.h 头文件中找到 */ JNIEXPORT jstring JNICALL Java_com_example_hellondk_MainActivity_getStringFromC(JNIEnv *env,jclass jclass){    return (*env) -> NewStringUTF(env,"Hello from JNI");}
  • 同样在 jni 目录下创建 Android.mk 文件
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE     := hello        //模块名称,需要加载的 so 库文件 LOCAL_SRC_FILES  := hello.c      //需要参与编译的源文件include $(BUILD_SHARED_LIBRARY)
  • 可以通过 ndk-build 命令编译产生 so 库,也可以让 AndroidStudio 自动编译 JNI 生成,采用自动编译的方法。
    1. 在 gradle.properties 文件中最后一行添加代码 andorid.useDeprecatedNdk=true
    2. 在 app 目录下 build.gradle 文件中添加代码如下
    defaultConfig {      applicationId "com.example.hellondk"      minSdkVersion 15      targetSdkVersion 28      versionCode 1      versionName "1.0"      testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"      ndk{          moduleName "hello"    //指定打包后的 so 库文件名          abiFilters "armeabi-v7a","x86"   //指定某个 CPU 平台的 so 库      }  }
  • 最后一步加载 so 库文件,并调用方法测试。
public class MainActivity extends AppCompatActivity {    static {        System.loadLibrary("hello");    }    public static native String getStringFromC();        @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        TextView textView = findViewById(R.id.textView);        textView.setText(getStringFromC());    }}

NDK 打印 log 信息

  • app 目录下 build.grade 文件 ndk 包层添加代码

    ldLibs "log"

  • 修改 Android.mk 文件添加 log 库,加入如下代码

    LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog

  • 在实现 JNI 方法的 .c 文件需要引入头文件,以及宏定义,完整代码如下

#include#include#include "com_example_hellondk_MainActivity.h"#include    //引入头文件#define TAG "seeker"      ////第一个参数 log 级别,第二个参数 key,第三个参数打印信息#define LOGV(...)__android_log_print(ANDROID_LOG_VERBOSE,TAG,__VA_ARGS__)/** * JNIEnv*  表示一个指向 JNI 环境的指针,可以通过它来访问 JNI 提供的接口方法 * JNIEXPORT  JNICALL 是 JNI 所定义的宏,可以在 jni.h 头文件中找到 */JNIEXPORT jstring JNICALL Java_com_example_hellondk_MainActivity_getStringFromC(JNIEnv *env,jclass jclass){    LOGV("hello");   //打印 log 调用    return (*env) -> NewStringUTF(env,"Hello from JNI");}

更多相关文章

  1. 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
  2. 一款常用的 Squid 日志分析工具
  3. GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
  4. RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
  5. Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
  6. [置顶] 那些你应该知道却不一定知道的——View坐标分析汇总
  7. Android(安卓)小项目之--Mini音乐播放器
  8. Android开发网上的一些重要知识点_4
  9. ApiDemos导入时No projects are found to import

随机推荐

  1. 2010年Android随想!
  2. Android(安卓)Socket 发送广播包的那些坑
  3. Android的ps命令介绍和技巧
  4. Android(安卓)面试题(2)
  5. android:layout_gravity 和 android:grav
  6. [时间线]Android市场的发展
  7. 【Android】MVC模式在Android系统中的应
  8. Android开发-一个简单的五子棋游戏
  9. 1.1 Android历史与版本进化
  10. Android(安卓)的Margin和Padding属性以及