Android studio调用C++代码
JNI原理
JNI(Java Native Interface)叫做JAVA本地接口。
JAVA是一种跨平台的语言,这种特性依赖的是Java虚拟机,虚拟机由C/C++编写。适配各个系统,通过JNI为上层的JAVA应用提供各种服务,保证跨平台性。
JNI查找
Android系统在启动启动过程中,先启动Kernel创建init进程,紧接着由init进程fork第一个横穿Java和C/C++的进程,即Zygote进程。Zygote启动过程中会AndroidRuntime.cpp
中的startVm
创建虚拟机,VM创建完成后,紧接着调用startReg
完成虚拟机中的JNI方法注册。
Java层怎么去找到相应的native代码的相应位置
package android.os;
public final class MessageQueue {
private native void nativePollOnce(long ptr, int timeoutMillis);
}
步骤1: MessageQueue.java
的全限定名为android.os.MessageQueue.java,完整的方法名为android.os.MessageQueue.nativePollOnce(),与之相对应的native层方法名是将点号替换为下划线,即android_os_MessageQueue_nativePollOnce()。
步骤2: 有了native方法,那么接下来需要知道该native方法所在那个文件。前面已经介绍过Android系统启动时就已经注册了大量的JNI方法,见AndroidRuntime.cpp的gRegJNI
数组。这些注册方法命令方式:
register_[包名]_[类名]
那么MessageQueue.java所定义的jni注册方法名应该是register_android_os_MessageQueue
,的确存在于gRegJNI数组,说明这次JNI注册过程是在开机过程完成。 该方法在AndroidRuntime.cpp
申明为extern方法:
extern int register_android_os_MessageQueue(JNIEnv* env);
这些extern方法绝大多数位于/framework/base/core/jni/
目录,大多数情况下native文件命名方式:
[包名]_[类名].cpp
[包名]_[类名].h
Tips: /android/os路径下的MessageQueue.java ==> android_os_MessageQueue.cpp
打开android_os_MessageQueue.cpp
文件,搜索android_os_MessageQueue_nativePollOnce方法,这便找到了目标方法:
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj, jlong ptr, jint timeoutMillis) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
}
到这里完成了一次从Java层方法搜索到所对应的C++方法的过程。
Android studio调用c++
构建流程
首先创建一个Native C++的工程
就会发现IDE为我们自动生了一系列文件。这里讲一下重点的几个文件
在app/src/java
里面存放点是java源代码。app/src/cpp
存放的是c++源代码
cpp
目录下面有CMakeLists.txt
文件,里面包含着动态库生成的规则设置。
add_library( # Sets the name of the library.
jin_text
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp)
app
下面的项目build、gradle
如下
plugins {
id 'com.android.application'
}
android {
compileSdk 32
defaultConfig {
applicationId "com.example.jin_text"
minSdk 23
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags '-std=c++11'
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
externalNativeBuild {
cmake {
path file('src/main/cpp/CMakeLists.txt')
version '3.18.1'
}
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
Plugiuns 是使用的插件,一般有两个
- ‘com.android.application’,表示该模块为应用程序模块,可以直接运行,打包得到的是.apk文件
- ‘com.android.library’,表示该模块为库模块,只能作为代码库依附于别的应用程序模块来运行,打包得到的是.aar文件
android是一个闭包。配置项目的各种属性
具体闭包功能可以自己百度。
Implementation 远程依赖声明。
之后只需要编写JNI接口(可以使用javah)生成,之后就可以调用C++代码。
Gradle
Gradle是一个架构项目的框架,真正起作用的还是plugin。Gradle中主要有两个对象Project和Task。其中Project为Task提供了上下文。Gradle脚本采用groovy书写。
Gradle的构建由一个或者多个project构成,每个project可以构建成你想要的样子,比如web应用、jar包等。
每个projext都是由多个Tasks组成的,每个task都代表着构建过程中的一个原子操作(编译、打包等)
Gradle的执行是分为两个阶段
- 配置阶段,读取所有build.gradle的内容来配置project和task等。
- 执行阶段
- Gradle为每个build.gradle都会创建一个相应的Project领域对象,在编写Gradle脚本时,我们实际上是在操作诸如Project这样的Gradle领域对象。在多Project的项目中,我们会操作多个Project领域对象。Gradle提供了强大的多Project构建支持。
- 要创建多Project的Gradle项目,我们首先需要在根(Root)Project中加入名为settings.gradle的配置文件,该文件应该包含各个子Project的名称。Gradle中的Project可以简单的映射为AndroidStudio中的Module。
- 在最外层的build.gradle。一般干得活是:配置其他子Project的。比如为子Project添加一些属性。
- 在项目根目录下有个一个名为settings.gradle。这个文件很重要,名字必须是settings.gradle。它里边用来告诉Gradle,这个multiprojects包含多少个子Project(可以理解为AndroidStudio中Module)。
参考链接
链接1
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)