Android ICS 4.0 NDK NewStringUTF sta crollando l'App

Ho un metodo in JNI C / C ++ che prende jstring e ritorna indietro jstring qualcosa come sotto,

NATIVE_CALL(jstring, method)(JNIEnv * env, jobject obj, jstring filename) { // Get jstring into C string format. const char* cs = env->GetStringUTFChars (filename, NULL); char *file_path = new char [strlen (cs) + 1]; // +1 for null terminator sprintf (file_path, "%s", cs); env->ReleaseStringUTFChars (filename, cs); reason_code = INTERNAL_FAILURE; char* info = start_module(file_path); jstring jinfo ; if(info==NULL) { jinfo = env->NewStringUTF(NULL); } else { jinfo = env->NewStringUTF(info); } delete info; info = NULL; return jinfo; } 

Il codice funziona perfettamente con versioni precedenti di android 4.0 come 2.2,2.3 e così via. Con ICS 4.0 controllare che JNI è attivo per impostazione predefinita e per questo l'app si blocca che lancia il seguente errore

  • Autenticazione FirebaseUI con Facebook non funziona
  • ListView personalizzato con la data come SectionHeader (utilizzato SimpleCursorAdapter personalizzato)
  • C'è un ascoltatore per ascoltare le modifiche del volume in android?
  • Come aprire il button
  • Inserimento di 1000000 righe in database sqlite3
  • Gestire notifiche multiple / notifiche impilate da GCM
  •   08-25 22:16:35.480: W/dalvikvm(24027): **JNI WARNING: input is not valid Modified UTF-8: illegal continuation byte 0x40** 08-25 22:16:35.480: W/dalvikvm(24027): 08-25 22:16:35.480: W/dalvikvm(24027): ========== 08-25 22:16:35.480: W/dalvikvm(24027): /tmp/create 08-25 22:16:35.480: W/dalvikvm(24027): ========== 08-25 22:16:35.480: W/dalvikvm(24027): databytes,indoorgames,drop 08-25 22:16:35.480: W/dalvikvm(24027): ==========   c_ag    ϋ@ ډ@     @' 08-25 22:16:35.480: W/dalvikvm(24027): in Lincom/inter /ndk/comNDK;.rootNDK:(Ljava/lang/String;)Ljava/lang/String; **(NewStringUTF)** 08-25 22:16:35.480: I/dalvikvm(24027): "main" prio=5 tid=1 NATIVE 08-25 22:16:35.480: I/dalvikvm(24027): | group="main" sCount=0 dsCount=0 obj=0x40a4b460 self=0x1be1850 08-25 22:16:35.480: I/dalvikvm(24027): | sysTid=24027 nice=0 sched=0/0 cgrp=default handle=1074255080 08-25 22:16:35.490: I/dalvikvm(24027): | schedstat=( 49658000 26700000 48 ) utm=1 stm=3 core=1 08-25 22:16:35.490: I/dalvikvm(24027): at comrootNDK(Native Method) 

    Sono indifeso di where mi sbaglio. Se vedi sopra NewStringUTF sta aggiungendo un valore di spazzatura ai c char * byte.

    1. Qualche idea del perché questo sta succedendo
    2. Qualsiasi soluzione alternativa per conseguire quanto sopra è benvenuto

    Apprezzo veramente se uno di voi possa aiutarmi. Grazie in anticipo

    mi regna

  • Come impedire che la tastiera appaia per EditText che non sia abilitata
  • jsPDF con Cordova - Aggiunta di immagini
  • Sqlite - Nessun errore di tale colonna durante la cancellazione di tabella da sqlite_sequence
  • Espresso: restituisce boolean se esiste la vista
  • Come get l'attività di accesso solo una volta che ho eseguito per la prima volta e la prossima volta che le attività differnt dovrebbero venire
  • La variazione di performance dell'encoder usando MediaCodec codifica dalla superficie
  • 8 Solutions collect form web for “Android ICS 4.0 NDK NewStringUTF sta crollando l'App”

    La causa di questo problema è direttamente correlata a un bug noto UTF-8 nella function NDK / JNI GetStringUTFChars () e probabilmente funzioni correlate come NewStringUTF. Queste funzioni NDK non convertono correttamente i caratteri Unicode supplementari (cioè i caratteri Unicode con un valore di U + 10000 e superiori). Ciò port ad errori UTF-8 e successivi arresti anomali.

    Ho riscontrato l'incidente durante la manipolazione del text di input dell'utente contenente caratteri emoticon ( vedere il corrispondente grafico Unicode ). I caratteri degli emoticon si trovano nell'area di caratteri Unicode Supplementare.

    Analisi del problema

    1. Il client Java passa una string contenente un carattere Unicode supplementare a JNI / NDK.
    2. JNI utilizza la function NDK GetStringUTFChars () per estrarre il contenuto della string Java.
    3. GetStringUTFChars () restituisce i dati della string come UTF-8 errato e non valido.

    C'è un bug NDK noto per cui GetStringUTFChars () converte in modo errato i caratteri Unicode supplementari, generando una sequenza UTF-8 errata e non valida.

    Nel mio caso, la string risultante era un buffer JSON. Quando il buffer è stato passato al parser JSON, il parser ha subito un errore perché uno dei caratteri UTF-8 dell'UTF-8 estratto ha un byte prefisso non valido UTF-8.

    Possibile soluzione alternativa

    La soluzione che ho usato può essere sintetizzata come segue:

    1. L'objective è quello di impedire a GetStringUTFChars () di eseguire la codifica errata UTF-8 del carattere Unicode supplementare.
    2. Questo viene fatto dal client Java che codifica la string di richiesta come Base64.
    3. La richiesta codificata Base64 viene passata al JNI.
    4. JNI chiama GetStringUTFChars (), che estrae la string codificata Base64 senza eseguire alcuna codifica UTF-8.
    5. Il codice JNI quindi decodifica i dati Base-64, generando la string di richiesta originale UTF-16 (ampia grandezza), incluso il carattere Unicode supplementare.

    In questo modo aggiriamo il problema dell'estrazione di caratteri Unicode supplementari dalla string Java. Invece, convertiamo i dati in Base-64 ASCII prima di call GetStringUTFChars (), estrarre i caratteri ASCII di Base-64 usando GetStringUTFChars () e convertire i dati Base-64 in caratteri larghi.

    Ho risolto questo problema restituendo l'arrays di byte invece di String. Sul lato Java sto convertendo la matrix di byte alle stringhe. Funziona bene! Stai lontano dall'uso di NewStringUTF () per Android 4.0 e superiori poiché c'è già un bug segnalato su Google Android NDK.

    Così ho fatto questo.

    1- Char Array di JByteArray.

    2- JByteArray a JString.

    3- Ritorna jstring al lato java.

    Codice JNI; (.c)

     jstring Java_com_x_y_z_methodName(JNIEnv *env, jobject thiz) { int size = 16; char r[] = {'P', 'K', 'd', 'h', 't', 'X', 'M', 'm', 'r', '1', '8', 'n', '2', 'L', '9', 'K'}; jbyteArray arrays = (*env)->NewByteArray(env, size); (*env)->SetByteArrayRegion(env, arrays, 0, size, r); jstring strEncode = (*env)->NewStringUTF(env, "UTF-8"); jclass cls = (*env)->FindClass(env, "java/lang/String"); jmethodID ctor = (*env)->GetMethodID(env, cls, "<init>", "([BLjava/lang/String;)V"); jstring object = (jstring) (*env)->NewObject(env, cls, ctor, arrays, strEncode); return object; } 

    Codice Java;

     native String methodName(); 

    L'altro metodo non funziona per me;

    Ho anche provato a return (*env)->NewStringUTF(env, r) ma restituisce alcuni caratteri che non sono nell'arrays char, alla fine della string where con l'avviso di JNI WARNING: l'input non è valido UTF-8 modificato : byte di continuazione illegale 0x40 .

    Esempio; PKdhtXMmr18n2L9K ؾ- DL

    Edit:

    Versione C ++

     jstring clientStringFromStdString(JNIEnv *env,const std::string &str){ // return env->NewStringUTF(str.c_str()); jbyteArray arrays = env->NewByteArray(str.size()); env->SetByteArrayRegion(arrays, 0, str.size(), (const jbyte*)str.c_str()); jstring strEncode = env->NewStringUTF("UTF-8"); jclass cls = env->FindClass("java/lang/String"); jmethodID ctor = env->GetMethodID(cls, "<init>", "([BLjava/lang/String;)V"); jstring object = (jstring) env->NewObject(cls, ctor, arrays, strEncode); return object; } 

    Ho avuto questo problema quando cambio il file Application.mk

    Da questa linea:

     APP_STL := stlport_static 

    A:

     APP_STL := gnustl_static 

    Una volta che l'ho cambiato, ha risolto il problema.

    Le stringhe che passate a NewStringUTF () devono essere valide UTF-8 modificate. Sembra che la string restituita dalla function start_Inauthroot () sia in alcuna altra codifica o sta solo restituendo una string non valida. È necessario convertire la string in UTF-8 prima di passarla alle funzioni JNI. Oppure potresti utilizzare uno dei costruttori String a conoscenza di charset per build invece l'object String.

    Questo funziona per me in c ++

     extern "C" JNIEXPORT jstring Java_com_example_ndktest_MainActivity_TalkToJNI(JNIEnv* env, jobject javaThis, jstring strFromJava) { jboolean isCopy; const char* szHTML = env->GetStringUTFChars(strFromJava, &isCopy); std::string strMine; strMine = szHTML; strMine += " --- Hello from the JNI!!"; env->ReleaseStringUTFChars(strFromJava, szHTML); return env->NewStringUTF(strMine.c_str()); } 

    A mio parere, non è un bug.

    NewStringUTF Costruisce un nuovo object java.lang.String da una matrix di caratteri nella codifica UTF-8 modificata .

    L'UTF-8 modificato non è UTF-8 standard. Vedere UTF-8 modificato

    Nella maggior parte dei casi, la string codificata UTF-8 è valida UTF-8 modificata. Poiché UTF-8 e UTF-8 modificati sono abbastanza simili. Tuttavia, quando si tratta di string Unicode al di là del piano di base multilingue, non sono compatibili.

    Soluzione: passare byte UTF-8 a livello Java e nuova string (byte, "UTF-8") quindi passare jstring a JNI.

    Per me, la soluzione è stata quella di mettere il contenuto su un char * const:

     const char* string = name_sin.c_str(); jstring utf8 = env_r->NewStringUTF(string); 

    e la function:

     jclass cls_Env = env_r->FindClass(CLASS_ACTIVITY_NAME); jmethodID mid = env_r->GetMethodID(cls_Env, "Delegate", "(Ljava/lang/String;)V"); //todo importnte hacerlo asi, si pasas directamente c_str a veces da error de carater no UTF 8 const char* string = name_sin.c_str(); jstring utf8 = env_r->NewStringUTF(string); env_r->CallVoidMethod(*object_r, mid, utf8); env_r->DeleteLocalRef(utf8); 
    L'Android è un fan Android di Google, tutto su telefoni Android, Android Wear, Android Dev e applicazioni Android Games e così via.