其实第一弹已经实现了,不过第一弹重点是为了引入外部so库文件,导致写得有些杂乱,这里转专门开一弹写Cmake引入的方法
- 创建Android Studio项目,省略
- MainActivity内容,提供了调用的可视化方法
package org.eu.uiai.jnilearn;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
static {
//加载写的 C 库
System.loadLibrary("my_lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
JniApi jApi=new JniApi();
//将本Activity传给JniApi,方便静态方法的调用
jApi.setsActivity(this);
//实现c代码调用java的入口方法
jApi.updateTextView();
}
//更新界面方法,共JniApi调用更新界面
public void updateTextView(){
int a=9,b=10;
TextView ss=findViewById(R.id.show_string);
TextView st=findViewById(R.id.show_text);
ss.setText("你好 C to Java");
st.setText(a+"+"+b+"="+(a+b));
}
}
- 写API接口类JniApi
package org.eu.uiai.jnilearn;
public class JniApi {
//C要实现的方法
public native void updateTextView();
//静态变量,需要传入
private static MainActivity sActivity;
//设置静态变量的方法
public void setsActivity(MainActivity activity){
sActivity=activity;
}
//静态方法,C中会调用该方法,调用后会更新Activity界面
public static int update(){
if(sActivity!=null){
sActivity.updateTextView();
return 1;
}
return 0;
}
}
- 通过指令生产jni头文件
javac ./app/src/main/java/org/eu/uiai/jnilearn/JniApi.java -h ./app/src/main/jni
- 生成的头文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class org_eu_uiai_jnilearn_JniApi */
#ifndef _Included_org_eu_uiai_jnilearn_JniApi
#define _Included_org_eu_uiai_jnilearn_JniApi
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_eu_uiai_jnilearn_JniApi
* Method: updateTextView
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_eu_uiai_jnilearn_JniApi_updateTextView
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
- 根据头文件写Cpp的实现
#include "org_eu_uiai_jnilearn_JniApi.h"
// log 输出相关部分
#include
#define LOG_TAG "MyLibTag"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
JNIEXPORT void JNICALL Java_org_eu_uiai_jnilearn_JniApi_updateTextView
(JNIEnv *env, jobject api){
//获取JinApi的class
jclass cls = env->GetObjectClass(api);
//根据Class,方法名,传入和返回参数;通过获取静态方法的函数获取方法ID
jmethodID id = env->GetStaticMethodID(cls,"update", "()I");
//通过Call执行方法,在通过static_cast获取结果
jint res = static_cast(env->CallStaticIntMethod(cls,id));
//从log输出执行结果
LOGE("执行结果Code:%d", (int)res);
}
- 修改build.gradle文件
......
android {
......
defaultConfig {
......
//{添加内容开始
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_shared"
}
}
//添加内容结束}
......
}
//{添加内容开始
externalNativeBuild {
cmake {
path "src/main/jni/CMakeLists.txt"
}
}
//添加内容结束}
......
}
dependencies {
......
}
- CMakeList.txt文件内容
add_library(my_lib SHARED my_lib.cpp)
# 链接log库必须加的,由于是连接到my_lib,所不能放在my_lib的add_library前
target_link_libraries(my_lib log)
效果与第一弹相同,这是我测试后比较简洁的配置,复杂的代码可能还有其他配置
评论区