返回

Android JNI 技术指南:入门 JNI 工程详解

Android

深入探究 Android Java 原生接口 (JNI) 的细节

前言

在移动应用程序开发的世界中,Android Java 原生接口 (JNI) 扮演着不可或缺的角色。它赋予开发人员利用原生代码强大功能的能力,从而显著提升应用程序的性能和效率。本博客将带你深入了解 JNI 的运作原理,一步步构建一个 JNI 工程,并深入分析其关键细节。

JNI 工程结构

一个典型的 JNI 工程包含以下主要文件:

  • Java 代码(.java): 负责与原生代码交互的 Java 代码。
  • C/C++ 代码(.c/.cpp): 原生代码,包含应用程序的业务逻辑。
  • Android.mk: 用于构建原生代码的 Makefile。
  • Application.mk: 用于配置和管理整个工程的 Makefile。

编写 Java 代码

Java 代码负责加载原生库并与之交互。首先,我们需要包含必要的头文件并声明一个原生方法,该方法将调用原生代码中的函数:

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

    // Declare the native method
    public native String getNativeString();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Load the native library
        System.loadLibrary("native-lib");

        // Call the native method
        TextView textView = findViewById(R.id.text_view);
        textView.setText(getNativeString());
    }
}

编写 C/C++ 代码

C/C++ 代码包含要从 Java 代码调用的实际业务逻辑。使用 extern "C" 指定符,以允许 Java 代码访问原生函数:

#include <string>

extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_native_MainActivity_getNativeString(JNIEnv *env, jobject instance) {
    std::string hello = "Hello from JNI!";
    return env->NewStringUTF(hello.c_str());
}

构建和运行工程

要构建工程,请运行以下命令:

ndk-build

如果构建成功,使用以下命令运行应用程序:

adb install -r app/build/outputs/apk/debug/app-debug.apk

JNI 工程细节分析

1. extern "C"

extern "C" 指定符告知编译器将函数声明为 C 函数,以便 Java 代码可以访问它。这是因为 Java 使用 Java 名称规范,而 C/C++ 使用 C++ 名称规范。

2. 动态库加载

System.loadLibrary() 方法用于加载原生库。它接受一个字符串参数,表示要加载的库的名称。在本例中,我们加载了名为 "native-lib" 的库。

3. 原生方法调用

getNativeString() 方法是 JNIEXPORT 修饰的,该修饰符指定该方法可从 Java 代码导出。它接受两个参数:JNIEnv* 和 jobject,并返回一个 jstring,其中包含要返回的字符串。

结论

本博客深入探讨了 Android JNI 工程的细节,包括 JNI 工程结构、Java 和 C/C++ 代码编写以及构建和运行工程。通过理解这些细节,你可以构建高效、强大的 JNI 应用程序,充分利用原生代码的优势。在后续的文章中,我们将进一步探索 JNI 的高级特性,例如数据类型映射、异常处理和线程管理。

常见问题解答

  1. 什么是 JNI?
    JNI 是 Android Java 原生接口,它允许 Java 代码与原生代码交互。

  2. 为什么使用 JNI?
    JNI 可用于提高应用程序的性能、访问特定于平台的功能或集成外部库。

  3. 如何编写 JNI 代码?
    需要编写 Java 代码以加载原生库和调用原生方法,并编写 C/C++ 代码以实现这些原生方法。

  4. 如何构建和运行 JNI 工程?
    使用 ndk-build 命令构建工程,并使用 adb install 命令运行应用程序。

  5. extern "C" 有什么作用?
    extern "C" 指定符确保原生函数可以从 Java 代码访问。