본문 바로가기

6. With IT/6.2 NDK

Native to Android


Native단에서 Java쪽의 Method를 호출하는 방법이 되겠다.!!!(이 내용은 Android code)

(NDK쪽에 공부하시는 분들중, 나같이 개고생하시는 분들이 없기를 바라며....,,ㅡㅡ'')

<<Here is Java inside....>>
 
<Native.java>
public class Native {

static {
System.loadLibrary(함수명); // c파일명
}

// java --> C
public native void execute();

private static EventListener listener;

public static interface EventListener {
// java function 등록
int printConsole(String str);
}

/***********************************************************
* JAVA LISTENER
***********************************************************/
public static void setListener(EventListener l) {
listener = l;
}

/***********************************************************
* C - Callbacks
***********************************************************/
@SuppressWarnings("unused")
public static int printConsole(String str) {
if (listener != null)
return listener.printConsole(str);
return -1;
}

}
/* ********  ********  ********  ********  ********  ********  ********  ********  ********  ********  ******** **/
<Description>
 

0. Native 함수명 셋팅
-(지극히 당연한 내용....ㅡ.ㅡ;; 설명필요없겠지??)

1. Android
에서 사용할 EventListener선언 
-  
Native에서 Android쪽을 호출할 , Android쪽에서는 이를 받는 
EventListener 필요하다.


2. Android
에서 사용될(Native 호출할) Method등록
-
Native쪽에서 함수명을 통하여 Android쪽과 교신한다.


3. listener셋팅

- (1.에서)선언한listner에 사용될(2.에서 선언) Java func등록


4.Native callback 처리

- Native쪽에서 보내온 결과를 받아, 이벤트 리턴 



<DisplayView.java>
TextView tvConsole;

    
@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.display);
   // TODO Auto-generated method stub
   
}
public void onResume(){
super.onResume();
tvConsole = (TextView)findViewById(R.id.DisplayView);
   tvConsole.setText("");
   
Intent intent = getIntent();
   String sef_path = intent.getStringExtra("seffile");
   
   
   Native nati = new Native();
   Native.setListener(this);
   nati.execute();
 
 public int printConsole(String str) {
// TODO Auto-generated method stub
tvConsole.append(str);
return 0;
}
/* ********  ********  ********  ********  ********  ********  ********  ********  ********  ********  ******** **/
<Description>
 1.  Textview선언

 
2.  findViewId연결 , Native함수 호출
 
(주의 : Native함수를 호출하기전에 반드시 먼저 TextView 셋팅시켜놔야함)

3. 
Native 인스턴스 생성후, 리스너 셋팅.

4. 
Native함수 호출

5. 
Android func작성 : Native쪽에서 호출한 녀석(처리할 내용 작성) (여기서는 String값을 파라미터로 받아옴)





<<Here is Native inside....>>
 
<main.cpp> ==> JavaVM을 얻어오기위한 셋팅과정

JavaVM *g_VM = NULL;
JNIEnv *_env;
jclass jNativesCls;
 
JNIEXPORT void JNICALL Java_com_android_pl_Native_execute(JNIEnv* env, jobject thiz)
{
...


       // Native에서 Java쪽과 교신하기위한 임의의 JavaVM을 생성 및 얻기
//(*env)->GetJavaVM(env, &g_VM);   
env->GetJavaVM(&g_VM);

if( _env == NULL ) {
_env = env;
}

if( g_VM == NULL ) {
//(*_env)->GetJavaVM( _env, &g_VM );
_env->GetJavaVM(&g_VM );
}


if( jNativesCls == NULL ) {
//jclass localCls = env->FindClass("com/AndroidExplorer/Native");
jNativesCls = env->FindClass("com/android/pl/Native");
// jNativesCls = env->NewGlobalRef(env, localCls);
//jNativesCls = env->NewGlobalRef(localCls);
}

const char *test[] = {(env)->GetStringUTFChars(seffile,0), (env)->GetStringUTFChars(svmfile,0)};

main_svm(2, test);
... 
 }
=========
1. JavaVM환경을 얻어오기위한 셋팅
- 단, 여기서 주의해야될 점은, 원래는 주석처리된 부분처럼만해도 동작이 되어야 하는데,
  C++이라 그런지 몰라도 저런식으로 JNI쪽 Method쓰는 방식이 달라졌음;;;;;;; 이런 신~~~발--;;
 

2. Java쪽에 있는 func을 부르기위한 셋팅
- 도대체 Java쪽에 선언되어있는 어떤 Class에 있는 Methodㄹ를 사용할 것인가?? 를 결정!!!
주의 : FindClass(패키지명/해당 method가 들어가있는 class명) 




<antoher.cpp> ==>실제로 Native 2 Java call이 이루어지는녀석

#include <jni.h>
extern JavaVM *g_VM;
extern jclass jNativesCls;

...
{
                                char buff[4096]; 
                                 ...

JNIEnv *env;
g_VM->AttachCurrentThread (&env, NULL);

jint ret = 0;
jmethodID mid = env->GetStaticMethodID(jNativesCls
, "printConsole"
, "(Ljava/lang/String;)I" );

jstring js;
js = env->NewStringUTF(buff);
// js = env->NewStringUTF(SendBytes);

if (mid) {
ret = (jint)(env)->CallStaticIntMethod(jNativesCls, mid, js );
}


... 
===========
1.  g_vm에 Java쪽의 기능을 사용하기위해 새로운 JNIEnv를 생성 및 셋팅. 
- (
 The Java™ Native Interface Programmer’s Guide and Specificationd에서 발췌. 알아서 이해해라....ㅋㅋㅋㅋ)
 

We explained earlier that a JNIEnv pointer is only valid in its associated thread.This is generally not a problem for native methods because they receive the JNIEnv pointer from the virtual machine as the first argument. Occasionally, however,it may be necessary for a piece of native code not called directly from the virtual machine to obtain the JNIEnv interface pointer that belongs to the current thread. For example, the piece of native code may belong to a “callback” function called by the operating system, in which case the JNIEnv pointer will probably not be available as an argument. 
 
2. Java쪽 func을 사용하기위한 작업(CallStaticIntMethod())
2-1. 무슨 method를 사용할 것인가?
GetStaticMethodID(
해당함수가선언된 클래스, 해당함수, <자바 패키지명/해당 함수의 리턴타입>)
 

2-2  사용될 파라미터는 무엇인가? 
 NewStringUTF(buff) <= 나는 buf을 UTF형식으로 받아올꺼임ㅋㅋㅋㅋ


3. java쪽 func 콜 
CallStaticIntMethod(해당함수가선언된 클래스, method, ...) 


====================
이상이당 

'6. With IT > 6.2 NDK' 카테고리의 다른 글

c에서 java호출(Native to Java)  (2) 2012.03.26
NDK-static library빌드 관련...  (0) 2012.03.06
android-ndk-r7오류  (0) 2012.02.12
cygwin삭제  (0) 2012.02.11
이클립스_NDK자동 컴파일  (0) 2012.02.09