2012-11-14 20 views
7

Ho un requisito per la creazione di richiamate tra codice nativo (codice lingua c) e codice Android. Ho scritto funzioni JNI per chiamare C code dal Android come questo codiceCome creare callback tra codice Android e codice nativo?

JNI qui

#include <android/log.h> 

void initSocket(); 

#ifdef __cplusplus 
extern "C" { 
#endif 

    JNIEXPORT void JNICALL Java_org_pjsip_pjsua_pjsua_1appJNI_initSocket(JNIEnv *jenv, jclass jcls) { 

    __android_log_write(ANDROID_LOG_INFO, " JNI CODE ", " APP INIT SOCKET");   
    initSocket();   
    } 
} 

codice C si presenta così

void initSocket() 
{ 
    /// some more stuff 
    printf(" initSocket function ");   
} 

static int worker_thread(void *unused) 
{  
    /// some more stuff 
    return 0; 
} 

pj_bool_t on_rx_data1(pj_stun_sock *stun_sock, void *pkt, unsigned pkt_len, const pj_sockaddr_t *src_addr, unsigned addr_len) 
{  
    /// some more stuff  
    return PJ_TRUE; 
} 

pj_bool_t on_data_sent1 (pj_stun_sock *stun_sock, pj_ioqueue_op_key_t *send_key, pj_ssize_t sent) 
{   
    /// some more stuff 
    return PJ_TRUE; 
} 
pj_bool_t on_status1(pj_stun_sock *stun_sock, pj_stun_sock_op op, pj_status_t status) 
{   
    /// some more stuff 
    returnsockaddress();    
    return PJ_TRUE; 
} 

char* returnsockaddress() 
{  
    /// some more stuff 
    return ipinttostring(sock_address); 
} 

char* ipinttostring(unsigned int addr) 
{  
    /// some more stuff 
    return fullIP; 
} 

questo è il codice che sto usando in linguaggio C, chiamando la funzioneda JNI. Ora voglio creare un callback da questo C code quando la funzione on_status1 chiama in questo codice. questo on_status1 si ripeterà in pochi secondi ogni volta che viene chiamato voglio chiamare una funzione nel codice di Android.

EDIT

ho provato in questo modo, ma non riuscii

JNIEXPORT void JNICALL Java_org_pjsip_pjsua_pjsua_1appJNI_initSocket(JNIEnv *jenv, jobject obj) { 

     __android_log_write(ANDROID_LOG_INFO, " JNI CODE ", " APP INIT SOCKET");    
     initSocket();    
     jclass cls = jenv->GetObjectClass(obj); 
     jmethodID methodid = env->GetMethodID(cls, "callback", "()V");    
     if(!methodid) { 
      return; 
     }    
     jenv->CallVoidMethod(obj , methodid);    
    } 

mi è stato dichiarato funzione come questa nel codice Android.

public static void callback(String value) { 
    Log.e(TAG, "value:" + value); 
} 

risposta

6

Prova questo:

JNIEXPORT void JNICALL Java_org_pjsip_pjsua_pjsua_1appJNI_initSocket(JNIEnv *jenv, jobject obj) { 
    __android_log_write(ANDROID_LOG_INFO, " JNI CODE ", " APP INIT SOCKET");    
    initSocket();    
    // jclass cls = (*jenv)->GetObjectClass(jenv, obj); 
    // or something like this : 
    jclass cls = (*jenv)->FindClass(jenv, "org/pjsip/pjsua/pjsua_appJNI"); 
    jmethodID methodid = (*jenv)->GetStaticMethodID(jenv, cls, "callback", "(Ljava/lang/String;)V");    
    if(!methodid) { 
     return; 
    }  
    jstring jstr = (*jenv)->NewStringUTF(jenv, "Hello from C"); 
    (*jenv)->CallStaticVoidMethod(jenv, cls, methodid, jstr); 
    } 
1

dal codice Java:

public static void callback(String value){ 
    Log.e(TAG, "value:"+value); 
} 

E chiama in C:

typedef struct JniSMSMethodInfo 
{ 
    JNIEnv * env; 
    jclass  classID; 
    jmethodID methodID; 
} JniMethodInfo; 

extern "C" 
{ 
static JNIEnv* getJNIEnv(void) 
{ 

    JavaVM* jvm = cocos2d::JniHelper::getJavaVM(); 
    if (NULL == jvm) { 
     LOGD("Failed to get JNIEnv. JniHelper::getJavaVM() is NULL"); 
     return NULL; 
    } 

    JNIEnv *env = NULL; 
    // get jni environment 
    jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4); 

    switch (ret) { 
     case JNI_OK : 
      // Success! 
      return env; 

     case JNI_EDETACHED : 
      // Thread not attached 

      // TODO : If calling AttachCurrentThread() on a native thread 
      // must call DetachCurrentThread() in future. 
      // see: http://developer.android.com/guide/practices/design/jni.html 

      if (jvm->AttachCurrentThread(&env, NULL) < 0) 
      { 
       LOGD("Failed to get the environment using AttachCurrentThread()"); 
       return NULL; 
      } else { 
       // Success : Attached and obtained JNIEnv! 
       return env; 
      } 

     case JNI_EVERSION : 
      // Cannot recover from this error 
      LOGD("JNI interface version 1.4 not supported"); 
     default : 
      LOGD("Failed to get the environment using GetEnv()"); 
      return NULL; 
    } 
} 
// get class and make it a global reference, release it at endJni(). 
static jclass getClassID(JNIEnv *pEnv) 
{ 
    jclass ret = pEnv->FindClass(CLASS_NAME); 
    if (! ret) 
    { 
     LOGD("Failed to find class of %s", CLASS_NAME); 
    } 

    return ret; 
} 
static bool getStaticMethodInfo(JniMethodInfo &methodinfo, const char *methodName, const char *paramCode) 
{ 
    jmethodID methodID = 0; 
    JNIEnv *pEnv = 0; 
    bool bRet = false; 

    do 
    { 
     pEnv = getJNIEnv(); 
     if (! pEnv) 
     { 
      break; 
     } 

     jclass classID = getClassID(pEnv); 

     methodID = pEnv->GetStaticMethodID(classID, methodName, paramCode); 
     if (! methodID) 
     { 
      LOGD("Failed to find static method id of %s", methodName); 
      break; 
     } 

     methodinfo.classID = classID; 
     methodinfo.env = pEnv; 
     methodinfo.methodID = methodID; 

     bRet = true; 
    } while (0); 

    return bRet; 
} 
void callback(char* value){ 
    JniMethodInfo methodInfo; 
    if (! getStaticMethodInfo(methodInfo, "callback", METHOD_SIGNATURE)) 
    {    
     return; 
    } 

    jstring stringArg = methodInfo.env->NewStringUTF(value); 
    methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, stringArg1); 
    methodInfo.env->DeleteLocalRef(stringArg); 
    methodInfo.env->DeleteLocalRef(methodInfo.classID); 
} 

} 

NOME_DELLA_CLASSE:/ METHOD_SIGNATURE: vedere dal file * .class

+0

già ho una funzione init() nel codice JNI, sto chiamando solo il codice init() da jni chiamerà functio() nel codice c, quando function() chiamato devo chiamare una funzione in android forma codice nativo questo è il requisito, non ho ricevuto il codice. Non posso espanderlo brevemente perché sono nuovo di NDK e JNI .. –

+0

sono stato modificato con qualche codice posso aiutarmi su questo .. –