日志打印优化
#include <jni.h>
#include <string>
#include <android/log.h>
#define TAG "XTY_NDK"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__);
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO , TAG, __VA_ARGS__);
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__);
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_cdemo_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
LOGD("DEBUG");
LOGI("INFO");
LOGE("ERROR");
return env->NewStringUTF(hello.c_str());
}
多线程开发
创建线程
#include <jni.h>
#include <string>
#include <android/log.h>
#include <pthread.h>
#define TAG "XTY_NDK"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__);
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO , TAG, __VA_ARGS__);
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__);
void* test(void* arg){
for (int i = 0; i < 10; ++i) {
LOGD("i=%d", i);
}
pthread_exit(0);
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_cdemo_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
pthread_t thread;
pthread_create(&thread, NULL, test, NULL);
pthread_join(thread, nullptr);
return env->NewStringUTF(hello.c_str());
}
线程传参(int)
#include <jni.h>
#include <string>
#include <android/log.h>
#include <pthread.h>
#define TAG "XTY_NDK"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__);
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO , TAG, __VA_ARGS__);
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__);
void* test(void* arg){
for (int i = 0; i < *(int*)arg; ++i) {
LOGD("%d i=%d", *(int*)arg, i);
}
pthread_exit(0);
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_cdemo_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
pthread_t thread;
int num = 11;
pthread_create(&thread, NULL, test, &num);
pthread_join(thread, nullptr);
return env->NewStringUTF(hello.c_str());
}
线程传参(C结构体struct写法)
#include <jni.h>
#include <string>
#include <android/log.h>
#include <pthread.h>
#define TAG "XTY_NDK"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__);
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO , TAG, __VA_ARGS__);
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__);
struct node{
int num;
std::string str;
};
void* test(void* arg){
struct node* p = (struct node*)arg;
for (int i = 0; i < p->num; ++i) {
LOGD("%d i=%d", p->num, i);
}
LOGD("%s", (p->str).c_str())
pthread_exit(0);
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_cdemo_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
pthread_t thread;
int num = 11;
struct node abc;
abc.num = 18;
abc.str = "xty";
pthread_create(&thread, NULL, test, &abc);
pthread_join(thread, nullptr);
return env->NewStringUTF(hello.c_str());
}
线程传参(C++结构体struct写法)
#include <jni.h>
#include <string>
#include <android/log.h>
#include <pthread.h>
#define TAG "XTY_NDK"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__);
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO , TAG, __VA_ARGS__);
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__);
typedef struct {
int num;
std::string str;
} node;
void* test(void* arg) {
node *p = (node *) arg;
for (int i = 0; i < p->num; ++i) {
LOGD("%d i=%d", p->num, i);
}
LOGD("%s", (p->str).c_str())
pthread_exit(0);
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_cdemo_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
pthread_t thread;
int num = 11;
node abc;
abc.num = 18;
abc.str = "xty";
pthread_create(&thread, NULL, test, &abc);
pthread_join(thread, nullptr);
return env->NewStringUTF(hello.c_str());
}
NDK开发(JavaVM与JNIEnv)
-
获取JavaVM的几种方式 JNI_OnLoad JNI_OnUnload env->GetJavaVM
-
获取JNIEnv的几种方式 函数静态注册传参 vm->GetEnv globalVM->AttachCurrentThread
JNI_OnLoad 必须返回JNI版本 JNI_VERSION_1_6 对比各种方式获取的JavaVM与JNIEnv指针是否一致
-
进程中只有一个JavaVM,但可以有多个JNIEnv
#include <jni.h>
#include <string>
#include <android/log.h>
#include <pthread.h>
#define TAG "XTY_NDK"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__);
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO , TAG, __VA_ARGS__);
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__);
JavaVM *globalVM = nullptr;
typedef struct {
int num;
std::string str;
} node;
void *test(void *arg) {
node *p = (node *) arg;
for (int i = 0; i < p->num; ++i) {
LOGD("%d i=%d", p->num, i);
}
LOGD("%s", (p->str).c_str())
pthread_exit(0);
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_cdemo_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
JavaVM* vm;
env->GetJavaVM(&vm);
LOGD("GetJavaVM %p", vm);
LOGD("Java_com_example_cdemo_MainActivity_stringFromJNI JNIEnv %p", env);
pthread_t thread;
node abc;
abc.num = 18;
abc.str = "xty";
pthread_create(&thread, NULL, test, &abc);
pthread_join(thread, nullptr);
return env->NewStringUTF(hello.c_str());
}
void *myThread(void *args) {
JNIEnv *myThreadEnv = nullptr;
if (globalVM->GetEnv((void **) &myThreadEnv, JNI_VERSION_1_6) == JNI_OK) {
LOGD("globalVM->GetEnv success");
LOGD("globalVM->GetEnv JNIEnv %p", myThreadEnv);
} else {
LOGD("globalVM->GetEnv failed");
}
if (globalVM->AttachCurrentThread(&myThreadEnv, nullptr) == JNI_OK){
LOGD("globalVM->AttachCurrentThread success");
LOGD("globalVM->AttachCurrentThread JNIEnv %p", myThreadEnv);
}else {
LOGD("globalVM->AttachCurrentThread failed");
}
globalVM->DetachCurrentThread();
pthread_exit(0);
}
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
globalVM = vm;
LOGD("JNI_OnLoad JavaVM %p", vm);
JNIEnv *env = nullptr;
if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
LOGD("GetEnv failed");
return -1;
}
LOGD("JNI_OnLoad JNIEnv %p", env);
pthread_t thread;
pthread_create(&thread, nullptr, myThread, nullptr);
pthread_join(thread, nullptr);
LOGD("线程结束");
return JNI_VERSION_1_6;
}
异常处理
#include <jni.h>
#include <string>
#include <android/log.h>
#include <pthread.h>
#define TAG "XTY_NDK"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__);
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO , TAG, __VA_ARGS__);
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__);
JavaVM *globalVM = nullptr;
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_cdemo_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
void *myThread(void *args) {
JNIEnv *myThreadEnv = nullptr;
if (globalVM->GetEnv((void **) &myThreadEnv, JNI_VERSION_1_6) == JNI_OK) {
LOGD("globalVM->GetEnv success");
LOGD("globalVM->GetEnv JNIEnv %p", myThreadEnv);
} else {
LOGD("globalVM->GetEnv failed");
}
if (globalVM->AttachCurrentThread(&myThreadEnv, nullptr) == JNI_OK){
LOGD("globalVM->AttachCurrentThread success");
LOGD("globalVM->AttachCurrentThread JNIEnv %p", myThreadEnv);
}else {
LOGD("globalVM->AttachCurrentThread failed");
}
jclass TestJclass = nullptr;
TestJclass = myThreadEnv->FindClass("com/xty/Cdemo/ReflectDemo");
myThreadEnv->ExceptionDescribe();
myThreadEnv->ExceptionClear();
if (TestJclass == nullptr) {
LOGD("myThreadEnv->FindClass failed");
};
globalVM->DetachCurrentThread();
pthread_exit(0);
}
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
globalVM = vm;
JNIEnv *env = nullptr;
if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
LOGD("GetEnv failed");
return -1;
}
pthread_t thread;
pthread_create(&thread, nullptr, myThread, nullptr);
pthread_join(thread, nullptr);
LOGD("线程结束");
return JNI_VERSION_1_6;
}
C与C++的区别
C
源码
#include <jni.h>
JNIEXPORT jstring JNICALL
Java_com_example_cdemo_MainActivity_stringFromJNI(
JNIEnv* env,
jobject obj /* this */) {
char* hello = "Hello from C++";
return (*env)->NewStringUTF(env, hello);
}
伪代码
__int64 __fastcall Java_com_xiaojianbang_demo2_MainActivity_stringFromJNI(_JNIEnv *a1)
{
return ((__int64 (__fastcall *)(_JNIEnv *, const char *))a1->functions->NewStringUTF)(a1, "Hello from C++");
}
C++
源码
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_cdemo_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
伪代码
int __fastcall Java_com_xiaojianbang_demo_MainActivity_stringFromJNI(_JNIEnv *a1)
{
_JNIEnv *v1; // ST24_4
const char *v2; // r0
int result; // r0
int v4; // [sp+0h] [bp-40h]
char v5; // [sp+28h] [bp-18h]
int v6; // [sp+34h] [bp-Ch]
v1 = a1;
sub_8E60();
v2 = (const char *)sub_8EC2((int)&v5);
v4 = _JNIEnv::NewStringUTF(v1, v2);
std::__ndk1::basic_string<char,std::__ndk1::char_traits<char>,std::__ndk1::allocator<char>>::~basic_string(&v5);
result = _stack_chk_guard;
if ( _stack_chk_guard == v6 )
result = v4;
return result;
}
JNI函数动态注册
jstring encodeFromC(JNIEnv* env, jobject obj, jint a, jstring b, jbyteArray jbt){
return env->NewStringUTF("this string from cpp");
}
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
globalVM = vm;
JNIEnv *env = nullptr;
if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
LOGD("GetEnv failed");
return -1;
}
auto clazz = env->FindClass("com/example/demo/MainActivity");
JNINativeMethod methods[] = {
//public native String encode(int i, String str, byte[] byt);
{"encode", "(ILjava/lang/String;[B)Ljava/lang/String;", (void *)encodeFromC}
};
env->RegisterNatives(clazz, methods, sizeof(methods)/sizeof(JNINativeMethod));
return JNI_VERSION_1_6;
}
JNI中创建对象
Java代码示例
package com.example.demo;
import android.util.Log;
public class ExampleClass {
public static String publicStaticStringField = "this is publicStaticStringField";
public String publicStringField = "this is publicStringField";
private static String privateStaticStringField = "this is privateStaticStringField";
private String privateStringField = "this is privateStringField";
public ExampleClass(){
Log.d("example", "this is ExampleClass()");
}
public ExampleClass(String str){
Log.d("example", "this is ExampleClass(String str)");
}
public ExampleClass(String str, int i){
Log.d("example", i + " " + str);
Log.d("example", "this is ExampleClass(String str, int i)");
}
public static void publicStaticFunc(){
Log.d("example", "this is publicStaticFunc");
}
public void publicFunc(){
Log.d("example", "this is publicFunc");
}
private static void privateStaticFunc(){
Log.d("example", "this is privateStaticFunc");
}
private void privateFunc(){
Log.d("example", "this is privateFunc");
}
}
方法一:
jstring encodeFromC(JNIEnv* env, jobject obj, jint a, jstring b, jbyteArray jbt){
//NewObject创建对象
auto clazz = env->FindClass("com/example/demo/ExampleClass");
auto methodID = env->GetMethodID(clazz, "<init>", "()V");
auto ExampleClassObj = env->NewObject(clazz, methodID);
LOGD("ExampleClassObj %p", ExampleClassObj);
return env->NewStringUTF("this string from cpp");
}
方法二:
jstring encodeFromC(JNIEnv* env, jobject obj, jint a, jstring b, jbyteArray jbt){
//AllocObject创建对象
auto clazz = env->FindClass("com/example/demo/ExampleClass");
auto methodID = env->GetMethodID(clazz, "<init>", "()V");
auto ExampleClassObj = env->AllocObject(clazz);
env->CallNonvirtualVoidMethod(ExampleClassObj, clazz, methodID);
return env->NewStringUTF("this string from cpp");
}
JNI中访问Java属性
访问静态属性
jstring encodeFromC(JNIEnv* env, jobject obj, jint a, jstring b, jbyteArray jbt){
auto clazz = env->FindClass("com/example/demo/ExampleClass");
//获取静态字段
auto privateStaticStringField = env->GetStaticFieldID(clazz, "privateStaticStringField", "Ljava/lang/String;");
jstring privateStaticString = static_cast<jstring>(env->GetStaticObjectField(clazz,
privateStaticStringField));
const char* privatecstr = env->GetStringUTFChars(privateStaticString, nullptr);
LOGD("privateStaticString: %s", privatecstr);
return env->NewStringUTF("this string from cpp");
}
访问非静态属性
jstring encodeFromC(JNIEnv* env, jobject obj, jint a, jstring b, jbyteArray jbt){
auto clazz = env->FindClass("com/example/demo/ExampleClass");
auto ExampleClassObj = env->AllocObject(clazz);
//获取对象字段
auto publicStringField = env->GetFieldID(clazz, "publicStringField", "Ljava/lang/String;");
jstring publicString = static_cast<jstring>(env->GetObjectField(ExampleClassObj,
publicStringField));
const char* publiccstr = env->GetStringUTFChars(publicString, nullptr);
LOGD("publicStringField: %s", publiccstr);
return env->NewStringUTF("this string from cpp");
}
JNI中访问Java数组
jstring encodeFromC(JNIEnv* env, jobject obj, jint a, jstring b, jbyteArray jbt){
//NewObject创建对象
auto clazz = env->FindClass("com/example/demo/ExampleClass");
auto methodID = env->GetMethodID(clazz, "<init>", "()V");
auto ExampleClassObj = env->NewObject(clazz, methodID);
LOGD("ExampleClassObj %p", ExampleClassObj);
//获取数组字段ID
auto byteArrayID = env->GetFieldID(clazz, "byteArray", "[B");
jbyteArray byteArray = static_cast<jbyteArray>(env->GetObjectField(ExampleClassObj,
byteArrayID));
int _byteArrayLength = env->GetArrayLength(byteArray);
//修改数组字段
char javaByte[10];
for(int i = 0; i < 10; i++){
javaByte[i] = static_cast<char>(100 - i);
}
const jbyte *java_array = reinterpret_cast<const jbyte *>(javaByte);
env->SetByteArrayRegion(byteArray, 0, _byteArrayLength, java_array);
//获取数组字段
byteArray = static_cast<jbyteArray>(env->GetObjectField(ExampleClassObj,
byteArrayID));
_byteArrayLength = env->GetArrayLength(byteArray);
char* str = reinterpret_cast<char *>(env->GetByteArrayElements(byteArray, nullptr));
for(int i = 0; i< _byteArrayLength; i++){
LOGD("str[%d]=%d", i, str[i]);
}
return env->NewStringUTF("this string from cpp");
}
JNI中访问Java函数
调用静态函数
//public native String encodeB(int i, String str, byte[] byt);
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_demo_MainActivity_encodeB(
JNIEnv* env,
jobject /* this */,
jint a, jstring b, jbyteArray c) {
//1、调用静态函数
jclass ExampleClassClazz = env->FindClass("com/example/demo/ExampleClass");
jmethodID publicStaticFuncID = env->GetStaticMethodID(ExampleClassClazz, "publicStaticFunc", "()V");
env->CallStaticVoidMethod(ExampleClassClazz, publicStaticFuncID);
return env->NewStringUTF("");
}
调用对象函数(CallObjectMethod)
//public native String encodeB(int i, String str, byte[] byt);
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_demo_MainActivity_encodeB(
JNIEnv* env,
jobject /* this */,
jint a, jstring b, jbyteArray c) {
//2、调用对象函数
jclass ExampleClassClazz = env->FindClass("com/example/demo/ExampleClass");
jmethodID privateFuncID = env->GetMethodID(ExampleClassClazz, "privateFunc",
"(Ljava/lang/String;I)Ljava/lang/String;");
jmethodID ExampleClassInit = env->GetMethodID(ExampleClassClazz, "<init>", "(Ljava/lang/String;)V");
jstring str1 = env->NewStringUTF("this is from NDK");
jobject ExampleClassObj = env->NewObject(ExampleClassClazz, ExampleClassInit, str1);
jstring str2 = env->NewStringUTF("this is from JNI");
jstring retval = static_cast<jstring>(env->CallObjectMethod(ExampleClassObj, privateFuncID, str2, 1000));
const char* cpp_retval = env->GetStringUTFChars(retval, nullptr);
LOGD("cpp_retval: %s", cpp_retval);
env->ReleaseStringUTFChars(retval, cpp_retval);
return env->NewStringUTF("");
}
调用对象函数(CallObjectMethodA)
//public native String encodeB(int i, String str, byte[] byt);
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_demo_MainActivity_encodeB(
JNIEnv* env,
jobject /* this */,
jint a, jstring b, jbyteArray c) {
jclass ExampleClassClazz = env->FindClass("com/example/demo/ExampleClass");
jmethodID privateFuncID = env->GetMethodID(ExampleClassClazz, "privateFunc",
"(Ljava/lang/String;I)Ljava/lang/String;");
jmethodID ExampleClassInit = env->GetMethodID(ExampleClassClazz, "<init>", "(Ljava/lang/String;)V");
jstring str1 = env->NewStringUTF("this is from NDK");
jobject ExampleClassObj = env->NewObject(ExampleClassClazz, ExampleClassInit, str1);
jstring str2 = env->NewStringUTF("this is from JNI");
jvalue args[2];
args[0].l = str2;
args[1].i = 1000;
jstring retval = static_cast<jstring>(env->CallObjectMethodA(ExampleClassObj, privateFuncID,
args));
const char* cpp_retval = env->GetStringUTFChars(retval, nullptr);
LOGD("cpp_retval: %s", cpp_retval);
env->ReleaseStringUTFChars(retval, cpp_retval);
return env->NewStringUTF("");
}
参数是数组返回值是数组
//public native String encodeB(int i, String str, byte[] byt);
extern "C" JNIEXPORT jstring JNICALL
Java_com_xiaojianbang_demo_MainActivity_encodeB(
JNIEnv* env,
jobject /* this */,
jint a, jstring b, jbyteArray c) {
jclass ExampleClassClazz = env->FindClass("com/example/demo/ExampleClass");
// 参数是数组 返回值是数组
//private static int[] privateStaticFunc(String[] str)
jclass StringClazz = env->FindClass("java/lang/String");
jobjectArray StringArr = env->NewObjectArray(3, StringClazz, nullptr);
for(int i = 0; i < 3; i++){
jstring str3 = env->NewStringUTF("NDK");
env->SetObjectArrayElement(StringArr, i, str3);
}
jmethodID privateStaticFuncID = env->GetStaticMethodID(ExampleClassClazz, "privateStaticFunc", "([Ljava/lang/String;)[I");
jintArray intArr = static_cast<jintArray>(env->CallStaticObjectMethod(ReflectDemoClazz,
privateStaticFuncID,
StringArr));
int *cintArr = env->GetIntArrayElements(intArr, nullptr);
LOGD("cintArr[0]=%d", cintArr[0]);
//3、调用父类函数
return env->NewStringUTF("");
}
JNI中访问父类方法
extern "C" JNIEXPORT void JNICALL
Java_com_xiaojianbang_demo_MainActivity_onCreate(JNIEnv *env, jobject thiz,
jobject saved_instance_state) {
//调用父类函数
jclass AppCompatActivityClazz = env->FindClass("androidx/appcompat/app/AppCompatActivity");
jmethodID onCreateID = env->GetMethodID(AppCompatActivityClazz, "onCreate", "(Landroid/os/Bundle;)V");
env->CallNonvirtualVoidMethod(thiz, AppCompatActivityClazz, onCreateID, saved_instance_state);
}
onCreateNative化
Java源码
package com.example.demo;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements OnClickListener {
// Used to load the 'native-lib' library on application startup.
String nativePathA = null;
String nativePathB = null;
static {
System.loadLibrary("exampleA");
System.loadLibrary("exampleB");
}
@Override
protected native void onCreate(Bundle savedInstanceState);
// protected void onCreate(Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
//
// setContentView(R.layout.activity_main);
// TextView tv = findViewById(R.id.sample_text);
//
// nativePathA = new Utils().getPath(getApplicationContext()) + "/libexampleA.so";
// nativePathB = new Utils().getPath(getApplicationContext()) + "/libexampleB.so";
// getApplicationContext();
// tv.setText(stringFromJNIA(nativePathB));
// stringFromJNIB(nativePathA);
//
// Log.d("example", encode(100, "example", new byte[]{49,50,51,52,53,54,55,56,57,58,59}));
// Log.d("example", encodeB(100, "example", new byte[]{49,50,51,52,53,54,55,56,57,58,59}));
//
// findViewById(R.id.button).setOnClickListener(this);
// }
public void onClick(View v) {
stringFromJNIA(nativePathB);
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNIA(String str);
public native String stringFromJNIB(String str);
public native String encode(int i, String str, byte[] byt);
public native String encodeB(int i, String str, byte[] byt);
}
JavaToC
extern "C" JNIEXPORT void JNICALL
Java_com_xiaojianbang_demo_MainActivity_onCreate(JNIEnv *env, jobject thiz,
jobject saved_instance_state) {
//super.onCreate(savedInstanceState);
jclass AppCompatActivityClazz = env->FindClass("androidx/appcompat/app/AppCompatActivity");
jmethodID onCreateID = env->GetMethodID(AppCompatActivityClazz, "onCreate", "(Landroid/os/Bundle;)V");
env->CallNonvirtualVoidMethod(thiz, AppCompatActivityClazz, onCreateID, saved_instance_state);
//R.layout.activity_main
jclass R$layoutClazz = env->FindClass("com/example/demo/R$layout");
jfieldID activity_mainID = env->GetStaticFieldID(R$layoutClazz, "activity_main", "I");
int activity_mainValue = env->GetStaticIntField(R$layoutClazz, activity_mainID);
LOGD("activity_mainValue=%d", activity_mainValue);
//setContentView(R.layout.activity_main);
jmethodID setContentViewID = env->GetMethodID(AppCompatActivityClazz, "setContentView", "(I)V");
env->CallVoidMethod(thiz, setContentViewID, activity_mainValue);
//R.id.sample_text
jclass R$idClazz = env->FindClass("com/example/demo/R$id");
jfieldID sample_textID = env->GetStaticFieldID(R$idClazz, "sample_text", "I");
int sample_textValue = env->GetStaticIntField(R$idClazz, sample_textID);
LOGD("sample_textValue=%d", sample_textValue);
//TextView tv = findViewById(R.id.sample_text);
jmethodID findViewByIdID = env->GetMethodID(AppCompatActivityClazz, "findViewById", "(I)Landroid/view/View;");
jobject TextViewObj = env->CallObjectMethod(thiz, findViewByIdID, sample_textValue);
//nativePathA = new Utils().getPath(getApplicationContext()) + "/libexampleA.so";
//nativePathB = new Utils().getPath(getApplicationContext()) + "/libexampleB.so";
jclass UtilsClazz = env->FindClass("com/example/demo/Utils");
jmethodID getPathID = env->GetMethodID(UtilsClazz, "getPath", "(Landroid/content/Context;)Ljava/lang/String;");
jmethodID UtilsInitID = env->GetMethodID(UtilsClazz, "<init>", "()V");
jobject UtilsObj = env->NewObject(UtilsClazz, UtilsInitID);
jclass ContextWrapperClazz = env->FindClass("android/content/ContextWrapper");
jmethodID getApplicationContextID = env->GetMethodID(ContextWrapperClazz, "getApplicationContext", "()Landroid/content/Context;");
jobject ContextObj = env->CallObjectMethod(thiz, getApplicationContextID);
jstring nativePath = static_cast<jstring>(env->CallObjectMethod(UtilsObj, getPathID, ContextObj));
std::string nativePathCStr = env->GetStringUTFChars(nativePath, nullptr);
std::string nativePathACStrA = nativePathCStr + "/libexampleA.so";
std::string nativePathACStrB = nativePathCStr + "/libexampleB.so";
LOGD("ndk nativePathA=%s", nativePathACStrA.c_str());
LOGD("ndk nativePathB=%s", nativePathACStrB.c_str());
jclass MainActivityClazz = env->GetObjectClass(thiz);
jfieldID nativePathBID = env->GetFieldID(MainActivityClazz, "nativePathB", "Ljava/lang/String;");
env->SetObjectField(thiz, nativePathBID, env->NewStringUTF(nativePathACStrB.c_str()));
//stringFromJNIA(nativePathB)
jmethodID stringFromJNIAID = env->GetMethodID(MainActivityClazz, "stringFromJNIA", "(Ljava/lang/String;)Ljava/lang/String;");
jstring stringFromJNIARetval = static_cast<jstring>(env->CallObjectMethod(thiz,
stringFromJNIAID,
env->NewStringUTF(
nativePathACStrB.c_str())));
//tv.setText(stringFromJNIA(nativePathB));
jclass TextViewClazz = env->GetObjectClass(TextViewObj);
jmethodID setTextID = env->GetMethodID(TextViewClazz, "setText", "(Ljava/lang/CharSequence;)V");
env->CallVoidMethod(TextViewObj, setTextID, stringFromJNIARetval);
//stringFromJNIB(nativePathA)
jmethodID stringFromJNIBID = env->GetMethodID(MainActivityClazz, "stringFromJNIB", "(Ljava/lang/String;)Ljava/lang/String;");
env->CallObjectMethod(thiz, stringFromJNIBID, env->NewStringUTF(nativePathACStrA.c_str()));
}