Android/Android Native
[Android Native] 예제: JNI에서 Singleton 객체의 메서드 함수 호출하기
2024. 8. 9. 01:12반응형
Keyboard라는 싱글돈 객체가 있다. 아래와 같이 호출 구조를 따르는 경우에 대해서, 코드를 작성해 본다.
MainActivity.java
public class MainActivity extends AppCompatActivity {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
...
Log.i(TAG, "Keyboard instance = Keyboard.getInstance();");
Keyboard instance = Keyboard.getInstance();
Log.i(TAG, "instance.onClick();");
instance.onClick();
...
}
...
Keyboard.java
package edu.gatech.seclass.sdpencryptor;
import android.util.Log;
public class Keyboard {
static {
System.loadLibrary("native-lib");
}
private static String TAG = "TEST123";
private static Keyboard sMe = null;
private Keyboard() { }
public static Keyboard getInstance() {
if (sMe == null) {
sMe = new Keyboard();
}
return sMe;
}
public void onNotified(String type, byte[] data) {
Log.i(TAG, "onClick. type: " + type + ", data: " + new String(data));
}
public native void onClick();
}
cpp/native-lib.cpp
#include <jni.h>
#include <string>
#include <android/log.h>
#include <stdio.h>
#include <string.h>
static JavaVM* gJavaVm;
static jclass gKeyboardClass;
#define LOG_TAG "TEST123"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved __attribute__((unused))) {
JNIEnv *env;
if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
LOGE("Failed to get JNI environment");
return -1;
}
gJavaVm = vm;
gKeyboardClass = env->FindClass("edu/gatech/seclass/sdpencryptor/Keyboard");
if (gKeyboardClass == NULL) {
return -1;
}
gKeyboardClass = (jclass) env->NewGlobalRef(gKeyboardClass);
// 반드시 return을 해주어야 한다. 그렇지 않으면 에러 발생한다.
return JNI_VERSION_1_6;
}
extern "C" JNIEXPORT jstring JNICALL
Java_edu_gatech_seclass_sdpencryptor_MainActivity_stringFromJNI(JNIEnv* env, jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C"
JNIEXPORT void JNICALL
Java_edu_gatech_seclass_sdpencryptor_Keyboard_onClick(JNIEnv *env, jobject thiz) {
// 1. 정적 메서드 ID 얻기
jmethodID getInstanceMethod = env->GetStaticMethodID(gKeyboardClass, "getInstance",
"()Ledu/gatech/seclass/sdpencryptor/Keyboard;");
if (getInstanceMethod == NULL) {
printf("Failed to get getInstance method ID\n");
return; // 메서드가 존재하지 않으면 종료
}
// 2. 정적 메서드 호출 (객체를 얻기 위해)
jobject keyboardInstance = env->CallStaticObjectMethod(gKeyboardClass,
getInstanceMethod);
if (keyboardInstance == NULL) {
printf("Failed to call getInstance method\n");
return; // 메서드 호출 실패 시 종료
}
// 여기 까지 Single 객체 얻는 것이 완료.
// ---- ---- ---- ---- ---- ---- ---- ----
// 4. 해당 객체에서, onNotified 메서드 ID 얻기
jmethodID onNotifiedMethod = env->GetMethodID(gKeyboardClass, "onNotified", "(Ljava/lang/String;[B)V");
if (onNotifiedMethod == NULL) {
printf("Failed to get onNotified method ID\n");
return; // 메서드가 존재하지 않으면 종료
}
// type에 "SHIFT" 문자열 전달
jstring type = env->NewStringUTF("SHIFT");
// data에 "hello world" 문자열 바이트 배열로 전달
const char* helloWorld = "hello world";
jbyteArray data = env->NewByteArray(strlen(helloWorld));
env->SetByteArrayRegion(data, 0, strlen(helloWorld), (const jbyte*)helloWorld);
// onNotified 메서드 호출
env->CallVoidMethod(keyboardInstance, onNotifiedMethod, type, data);
// 예외 체크
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
}
출력 결과화면
2024-08-09 00:57:58.899 29312-29312 TEST123 edu.gatech.seclass.sdpencryptor I Keyboard instance = Keyboard.getInstance();
2024-08-09 00:57:58.900 29312-29312 TEST123 edu.gatech.seclass.sdpencryptor I instance.onClick();
2024-08-09 00:57:58.900 29312-29312 TEST123 edu.gatech.seclass.sdpencryptor I onClick. type: SHIFT, data: hello world
반응형
'Android > Android Native' 카테고리의 다른 글
[Android Native] JNI 멀티스레드에서 함수 호출하기 (0) | 2024.08.09 |
---|---|
[Android Native][JNI] CMakeLists.txt에 원하는 CPP파일 추가하기 (0) | 2024.08.09 |
[Android Native] Abort message: 'JNI DETECTED ERROR IN APPLICATION: JNI ERROR (app bug): jclass is an invalid local reference: XXXX (0) | 2024.08.09 |
[Android] JNI method signature에 대한 고찰 (0) | 2024.08.09 |
[Android][JNI] 멀티쓰레드 관련 Stack overflow 정리 (0) | 2024.08.05 |