Android 将自定义的 SO 打进 APK 里

在 Android 开发过程中,我们经常会遇到需要使用一些 C 或 C++ 编写的本地库(即 .so 文件)来实现一些性能敏感或者平台相关的功能。将这些 .so 文件集成到 APK 中,可以使得应用更加便携,方便分发。本文将详细介绍如何将自定义的 .so 文件集成到 APK 中。

准备工作

首先,确保你的 Android Studio 环境已经配置好 NDK(Native Development Kit),这是 Android 官方提供的开发本地应用的工具集。

集成 .so 文件

1. 创建 JNI 层

src/main/cpp 目录下创建 JNI 层的 C 或 C++ 源文件,例如 native-lib.cpp

#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapp_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
2. 配置 CMakeLists.txt

src/main/cpp 目录下创建 CMakeLists.txt 文件,配置编译 .so 文件的规则:

cmake_minimum_required(VERSION 3.4.1)

add_library( native-lib SHARED native-lib.cpp )

find_library( log-lib log )

target_link_libraries( native-lib ${log-lib} )
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
3. 配置 build.gradle

app/build.gradle 文件中,添加如下配置:

android {
    ...
    defaultConfig {
        ...
        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }
        ...
    }
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
        }
    }
    ...
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
4. 编译 APK

编译 APK 时,Gradle 会自动调用 CMake 编译 .so 文件,并将其集成到 APK 中。

调用 JNI 层

在 Java 层,你可以像调用普通 Java 方法一样调用 JNI 层的方法:

public class MainActivity extends AppCompatActivity {
    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

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

        // Example of a call to a native method
        TextView tv = (TextView) findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
    }

    // 声明 JNI 方法
    public native String stringFromJNI();
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

类图

以下是 JNI 层和 Java 层的类图:

调用 MainActivity +stringFromJNI() : String native-lib +stringFromJNI() : String

结语

通过上述步骤,我们可以将自定义的 .so 文件集成到 APK 中,并在 Java 层调用其方法。这种方式可以提高应用的性能,同时保持应用的便携性。希望本文能帮助到需要集成本地库的 Android 开发者。