J'écris une méthode native qui peut recevoir des données du socket, puis réécrire dans un ByteArray qui est un paramètre d'entrée de Java. Le socket a été créé dans BlueZ et transmis à mon programme par un message dBus. J'utilise un thread séparé pour faire toute la procédure.Problème de sondage JNI
Merci pour la suggestion de Cerber pour mon précédent problème GetPrimitiveArrayCritical(). Maintenant, le programme pourrait fonctionner sans erreur. Cependant, le nouveau problème est que parce que j'utilise Poll pour attendre l'événement POLLIN, s'il y a des données entrantes disponibles pour la lecture, il y aurait un événement POLLIN théoriquement et je pourrais faire la lecture du socket.
Malheureusement l'événement POLLIN est continuellement déclenché mais je n'ai pas pu lire de données !!! Mais ce comportement étrange ne s'est pas produit quand j'ai fait la même procédure dans le code de BlueZ. Je suis sûr que la prise est correcte.
Le morceau de mon code natif sont quelque chose comme:
struct socket_loop_native_data {
pthread_mutex_t thread_mutex;
pthread_t thread;
struct pollfd *pollData;
JavaVM *vm;
int envVer;
jobject me;
jbyteArray javaBuffer;
int bufferSize;
jbyte *nativeBuffer;
char *beginOfBuffer;
char *endOfBuffer;
int decodedDataSize;
bool running;
};
typedef socket_loop_native_data native_data_t;
static jfieldID field_mNativeDataSocket;
static inline native_data_t *get_native_data(JNIEnv *env, jobject object) {
return (native_data_t *)(env->GetIntField(object, field_mNativeDataSocket));
}
native_data_t *get_SocketLoop_native_data(JNIEnv *env, jobject object) {
return get_native_data(env, object);
}
JNIEXPORT void JNICALL Java_android_classInitNativeSocket(JNIEnv* env, jclass clazz) {
field_mNativeDataSocket = env->GetFieldID(clazz, "mNativeDataSocket", "I");
}
JNIEXPORT void JNICALL Java_android_initializeNativeDataNativeSocket(JNIEnv* env, jobject object) {
native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t));
if (NULL == nat) {
LOGD("%s: out of memory!", __FUNCTION__);
return;
}
memset(nat, 0, sizeof(native_data_t));
pthread_mutex_init(&(nat->thread_mutex), NULL);
env->SetIntField(object, field_mNativeDataSocket, (jint)nat);
}
JNIEXPORT jboolean JNICALL Java_android_startSocketLoopNative(JNIEnv *env, jobject object, jint sock, jbyteArray buffer, jint size) {
jboolean result = JNI_FALSE;
socket_loop_native_data *nat = get_native_data(env, object);
pthread_mutex_lock(&(nat->thread_mutex));
nat->running = false;
if (nat->pollData) {
LOGD("trying to start SocketLoop a second time!");
pthread_mutex_unlock(&(nat->thread_mutex));
return JNI_FALSE;
}
nat->pollData = (struct pollfd *)malloc(sizeof(struct pollfd));
if (!nat->pollData) {
LOGD("out of memory error starting SocketLoop!");
goto done;
}
memset(nat->pollData, 0, sizeof(struct pollfd));
nat->pollData[0].fd = sock;
nat->pollData[0].events = POLLIN;
env->GetJavaVM(&(nat->vm));
nat->envVer = env->GetVersion();
nat->me = env->NewGlobalRef(object);
nat->javaBuffer = (jbyteArray)(env->NewGlobalRef(buffer));
nat->bufferSize = (int)size;
nat->decodedDataSize = 0;
pthread_create(&(nat->thread), NULL, socketLoopMain, nat);
result = JNI_TRUE;
done:
if (JNI_FALSE == result) {
if (nat->me) env->DeleteGlobalRef(nat->me);
nat->me = NULL;
if (nat->pollData) free(nat->pollData);
nat->pollData = NULL;
}
pthread_mutex_unlock(&(nat->thread_mutex));
return result;
}
static void *socketLoopMain(void *ptr) {
native_data_t *nat = (native_data_t *)ptr;
JNIEnv *env;
JavaVMAttachArgs args;
char name[] = "SocketLoop";
args.version = nat->envVer;
args.name = name;
args.group = NULL;
nat->vm->AttachCurrentThread(&env, &args);
/* For poll result */
int ret = 0;
/* For receiving pollin data */
int rlen;
char *buffer = (char *)calloc(1, 65536);
...
while ((nat->running)) {
if ((ret = poll(nat->pollData, 1, -1)) < 0){
LOGD("In socketLoopMain() : The socket poll error !!!");
goto close;
}
if ((nat->pollData[0].revents & POLLIN)){
...
rlen = read(nat->pollData[0].fd, buffer, 65536);
LOGD("In socketLoopMain() : Read bytes = %d", rlen);
...
}
else if ((nat->pollData[0].revents & POLLOUT)){
LOGD("In socketLoopMain() : The socket poll revents [POLLOUT] !!! DO NOTHING");
continue;
}
else if ((nat->pollData[0].revents & POLLERR)){
LOGD("In socketLoopMain() : The socket poll revents [POLLERR] !!!");
goto close;
}
else if ((nat->pollData[0].revents & POLLHUP)){
LOGD("In socketLoopMain() : The socket poll revents [POLLHUP] !!!");
goto close;
}
else if ((nat->pollData[0].revents & POLLRDHUP) || (nat->pollData[0].revents & POLLNVAL)){
LOGD("In socketLoopMain() : The socket poll revents [POLLRDHUP][POLLNVAL] !!!");
goto close;
}
}
...
}
Sauf pour la première POLLIN, je ne pouvais pas lire toutes les données de prise, RLEN est toujours 0.
Je construis l'ensemble du code natif à lib partagé en utilisant la commande "make libxxx" dans le répertoire racine du code source Android pas "ndk-build".
Toute suggestion serait grandement appréciée !!!
Merci pour votre réponse –