Как создать обратные вызовы между кодом android и собственным кодом?
у меня есть требование для создания обратных вызовов между родным кодом ( код языка c) и кодом Android .
Я написал функции JNI для вызова C code
от андроида, как это
код JNI здесь
#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();
}
}
код C выглядит так
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;
}
это код, который я использую на языке C, вызывая initSocket()
функция от JNI. Теперь я хочу создать callback
отсюда C code
, когда on_status1
функция вызывается в этом коде. это on_status1 будет повторите через несколько секунд, когда это называется, Я хочу вызвать функцию в коде android.
редактировать
Я пробовал так, но не получилось
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);
}
Я был объявлен функцией, как это в коде android.
public static void callback(String value) {
Log.e(TAG, "value:" + value);
}
2 ответов
попробуйте это :
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);
}
из кода java:
public static void callback(String value){
Log.e(TAG, "value:"+value);
}
и вызовите 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);
}
}
ИМЯ_КЛАССА: / METHOD_SIGNATURE: см. Его из файла *.класс!--3-->