NDK配置
Windows10 64
AndroidStudio Chipmunk | 2021.2.1 Patch 1
创建NDK工程之前,请先保证本地已经搭建好了NDK的相关环境。
-
依次选择【Tools】->【SDK Manager】下载配置NDK,如下所示。
ndk_1.jpg -
新建一个Native C++工程,如下所示。
NDK2.jpg
-
NDK项目结构
NDK5.jpg
我们接下来看一下,Android的NDK工程和普通的Android应用工程有哪些不一样的地方。首先,我们来看下build.gradle配置。
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
compileSdk 32
defaultConfig {
applicationId "com.example.helloworldndk"
minSdk 21
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ''
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
externalNativeBuild {
cmake {
path file('src/main/cpp/CMakeLists.txt')
version '3.18.1'
}
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
可以看到,相比普通的Android应用,build.gradle配置中多了两个externalNativeBuild配置项。其中,defaultConfig里面的的externalNativeBuild主要是用于配置Cmake的命令参数,而外部的
externalNativeBuild的主要是定义了CMake的构建脚本CMakeLists.txt的路径。
然后,我们来看一下CMakeLists.txt文件,CMakeLists.txt是CMake的构建脚本,作用相当于ndk-build中的Android.mk,代码如下。
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.18.1)
# Declares and names the project.
project("helloworldndk")
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
helloworldndk
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
helloworldndk
# Links the target library to the log library
# included in the NDK.
${log-lib})
关于CMake的更多知识,可以查看CMake官方手册。
- 官方示例
默认创建Android NDK工程时,Android提供了一个简单的JNI交互示例,返回一个字符串给Java层,方法名的格式为:Java_包名类名方法名 。首先,我们看一下native-lib.cpp的代码。
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_helloworldndk_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
然后,我们在看一下Android的MainActivity.kt 的代码。
package com.example.helloworldndk
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import com.example.helloworldndk.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// Example of a call to a native method
binding.sampleText.text = stringFromJNI()
}
/**
* A native method that is implemented by the 'helloworldndk' native library,
* which is packaged with this application.
*/
external fun stringFromJNI(): String
companion object {
// Used to load the 'helloworldndk' library on application startup.
init {
System.loadLibrary("helloworldndk")
}
}
}
- 运行程序
我们看一下生成的so文件所在的位置
NDK7.jpg
网友评论