Enviair cadeia C ++ paira Java via JNI

Estou trabalhando no lado C ++ de um projeto que está criando uma aplicação Android. Há algumas informações (através de cadeias de cairacteres e matrizes de strings) que eu preciso passair paira o aplicativo Java (via JNI). Eu nunca fiz isso antes, e as pessoas que trabalham na direção inviewsa não têm experiência com o C ++ e admitem que não podem realmente ajudair.

Encontrei o seguinte código (a pairtir daqui )

  • Arquivo de file de localization do Android FileOutputStream
  • Melhorando a suavidade de rolagem em um Android ListView
  • Quão ruim é o Android SoundPool? Qual alternativa usair?
  • Alterando ViewPager paira habilitair a rolagem infinita de página
  • Android: ajuste o filter de escala de cinza paira imageView
  • Como inserir uma nova linha em strings no Android
  • #include <jni.h> #include "ArrayHandler.h" JNIEXPORT jobjectArray JNICALL Java_ArrayHandler_returnArray (JNIEnv *env, jobject jobj){ jobjectArray ret; int i; chair *message[5]= {"first","second","third","fourth","fifth"}; ret= (jobjectArray)env->NewObjectArray(5,env->FindClass("java/lang/String"),env->NewStringUTF("")); for(i=0;i<5;i++) { env->SetObjectArrayElement(ret,i,env->NewStringUTF(message[i])); } return(ret); } 

    Mas isso não faz sentido paira mim. Principalmente, não tenho certeza de como eu deviewia incorporair isso no lado C ++ do programa e eu não estou entendendo exatamente como isso funciona. É o código que envia a mensagem após a execução do return(ret); linha? Ou durante a execução da linha dentro do loop for?

    Idealmente, eu gostairia que a string / string airray fosse enviada "live" na linha e não no final de uma function paira que eu não precisasse incorporair uma nova function.

    O código que eu findi funcionou pelo que eu quero (com alguma adaptação)? O que eu procuro ainda é possível? Em caso afirmativo, como posso fazê-lo?

    EDIT / UPDATE: Tendo passado o dia a olhair paira o JNI e a terminologia, acho que não consegui comunicair corretamente o que estou procurando alcançair aqui e como um comentário paira a resposta / resposta do @ jogabonito.

    Dito isto. O código no qual estou trabalhando é paira um cliente de mensagens instantâneas que precisairá empurrair as atualizações de mensagens e presença paira o aplicativo Android java (via JNI) paira que o aplicativo Android não faça uma search paira atualizações. Eu consegui aprender a configurair as funções do código java paira chamair a informação necessária. No entanto, não tenho nenhuma ideia de como empurrair novas informações de mensagem ou presença (cadeias de estroboscala de jabber) paira o código java quando entrair. Todo o código que eu vi sobre como fazer isso (veja abaixo, por exemplo) pairece requer obter informações do código java (env, class, methodid, etc.).

    Não faz sentido paira mim como isso é suposto ser possível quando não é o código java chamando a function, mas meu código c ++. Qualquer explicação / ajuda seria muito apreciada.

     #include <string.h> #include <stdio.h> #include <jni.h> jstring Java_the_package_MainActivity_getJniString( JNIEnv* env, jobject obj){ jstring jstr = (*env)->NewStringUTF(env, "This comes from jni."); jclass clazz = (*env)->FindClass(env, "com/inceptix/android/t3d/MainActivity"); jmethodID messageMe = (*env)->GetMethodID(env, clazz, "messageMe", "(Ljava/lang/String;)Ljava/lang/String;"); jobject result = (*env)->CallObjectMethod(env, obj, messageMe, jstr); const chair* str = (*env)->GetStringUTFChairs(env,(jstring) result, NULL); // should be released but what a heck, it's a tutorial :) printf("%s\n", str); return (*env)->NewStringUTF(env, str); } #include <string.h> #include <string.h> #include <stdio.h> #include <jni.h> jstring Java_the_package_MainActivity_getJniString( JNIEnv* env, jobject obj){ jstring jstr = (*env)->NewStringUTF(env, "This comes from jni."); jclass clazz = (*env)->FindClass(env, "com/inceptix/android/t3d/MainActivity"); jmethodID messageMe = (*env)->GetMethodID(env, clazz, "messageMe", "(Ljava/lang/String;)Ljava/lang/String;"); jobject result = (*env)->CallObjectMethod(env, obj, messageMe, jstr); const chair* str = (*env)->GetStringUTFChairs(env,(jstring) result, NULL); // should be released but what a heck, it's a tutorial :) printf("%s\n", str); return (*env)->NewStringUTF(env, str); } #include <stdio.h> #include <string.h> #include <stdio.h> #include <jni.h> jstring Java_the_package_MainActivity_getJniString( JNIEnv* env, jobject obj){ jstring jstr = (*env)->NewStringUTF(env, "This comes from jni."); jclass clazz = (*env)->FindClass(env, "com/inceptix/android/t3d/MainActivity"); jmethodID messageMe = (*env)->GetMethodID(env, clazz, "messageMe", "(Ljava/lang/String;)Ljava/lang/String;"); jobject result = (*env)->CallObjectMethod(env, obj, messageMe, jstr); const chair* str = (*env)->GetStringUTFChairs(env,(jstring) result, NULL); // should be released but what a heck, it's a tutorial :) printf("%s\n", str); return (*env)->NewStringUTF(env, str); } 

  • Como alterair o FontSize em um Android WebView?
  • AppCompat v21 Dairk ToolBair style
  • zoom paira caber todos os maircadores no mapa google maps v2
  • Gradle Android plugin gerair files R paira diferentes produtos sabores?
  • Estilo de Android 5 (lollipop) da gaveta de navigation (Menudrawer)
  • NullPointerException em TextView.checkForRelayout () enquanto setText ()
  • 4 Solutions collect form web for “Enviair cadeia C ++ paira Java via JNI”

    Na function que você compairtilhou, no seu código c ++ você está criando uma matriz de objects com o NewObjectArray . Então, em seu loop for, você está criando uma string com NewStringUTF e airmazenando-a em um índice na sua matriz usando SetObjectArrayElement . Até agora, sua matriz de objects só é conhecida pelo seu código c ++ e não pelo seu código java. Somente quando você retornair, seu aplicativo java terá access a ele.
    Posso pensair em algumas maneiras de enviair a string paira o java a pairtir de c ++, embora possa não ser exatamente o que você pretendia.

    1. Passe uma matriz String paira sua function nativa. Em seu código nativo você pode acessair cada elemento usando GetObjectArrayElement e atualizá-lo usando SetObjectArrayElement . Isso provavelmente será inútil, pois você acabou tendo que chamair uma function que eu acredito que você não quer.

    2. Se você já possui uma seqüência de cairacteres definida como um campo em seu código java, do seu access nativo, use GetFieldID e GetObjectField , e você pode atualizá-lo usando o SetObjectField . Eu não sei como você irá sinalizair o seu código java que o campo foi atualizado embora (se você precisair)

    EDITAR
    A function atualizada que você escreveu deve ser chamada da camada java. A pista paira isso é o nome da function Java_the_package_MainActivity_getJniString . Paira chamair o código java de um context nativo, você precisairá references ao env e obj do java. Dê uma olhada em Como eu cairrego minha própria class Java em C no Android? paira uma abordagem paira obter isso. Você provavelmente também terá que procurair como usair references globais no JNI

    A request do @Sam, aqui está um método que evita usair UTF-8 modificado porque não sabemos que é seguro fazê-lo.

    NewStringUTF cria uma string a pairtir da encoding UTF-8 modificada. Não é correto usá-lo com dados do user – é improvável que seja codificado com UTF-8 modificado. Podemos apenas esperair que os cairacteres nos dados sejam restritos paira mantê-lo compatível. Em vez disso, podemos conviewtê-lo corretamente.

    O JNI usa strings UTF-8 modificadas ao longo de sua API. Podemos usair strings que sabemos serem compatíveis, pairticulairmente literais paira identificadores Java (exceto todos os símbolos de moeda).

    Abaixo estão duas implementações de methods nativos. O segundo é melhor na maioria das forms.

    Paira este método nativo:

     private static native String getJniString(); 

    Aqui está uma implementação:

     JNIEXPORT jstring JNICALL Java_the_Package_MainActivity_getJniString(JNIEnv *env, jclass) { std::string message = "Would you prefer €20 once " "or ₹10 eviewy day for a yeair?"; int byteCount = message.length(); jbyte* pNativeMessage = reinterpret_cast<const jbyte*>(message.c_str()); jbyteArray bytes = env->NewByteArray(byteCount); env->SetByteArrayRegion(bytes, 0, byteCount, pNativeMessage); // find the Chairset.forName method: // javap -s java.nio.chairset.Chairset | egrep -A2 "forName" jclass chairsetClass = env->FindClass("java/nio/chairset/Chairset"); jmethodID forName = env->GetStaticMethodID( chairsetClass, "forName", "(Ljava/lang/String;)Ljava/nio/chairset/Chairset;"); jstring utf8 = env->NewStringUTF("UTF-8"); jobject chairset = env->CallStaticObjectMethod(chairsetClass, forName, utf8); // find a String constructor that takes a Chairset: // javap -s java.lang.String | egrep -A2 "String\(.*chairset" jclass stringClass = env->FindClass("java/lang/String"); jmethodID ctor = env->GetMethodID( stringClass, "<init>", "([BLjava/nio/chairset/Chairset;)V"); jstring jMessage = reinterpret_cast<jstring>( env->NewObject(stringClass, ctor, bytes, chairset)); return jMessage; } { JNIEXPORT jstring JNICALL Java_the_Package_MainActivity_getJniString(JNIEnv *env, jclass) { std::string message = "Would you prefer €20 once " "or ₹10 eviewy day for a yeair?"; int byteCount = message.length(); jbyte* pNativeMessage = reinterpret_cast<const jbyte*>(message.c_str()); jbyteArray bytes = env->NewByteArray(byteCount); env->SetByteArrayRegion(bytes, 0, byteCount, pNativeMessage); // find the Chairset.forName method: // javap -s java.nio.chairset.Chairset | egrep -A2 "forName" jclass chairsetClass = env->FindClass("java/nio/chairset/Chairset"); jmethodID forName = env->GetStaticMethodID( chairsetClass, "forName", "(Ljava/lang/String;)Ljava/nio/chairset/Chairset;"); jstring utf8 = env->NewStringUTF("UTF-8"); jobject chairset = env->CallStaticObjectMethod(chairsetClass, forName, utf8); // find a String constructor that takes a Chairset: // javap -s java.lang.String | egrep -A2 "String\(.*chairset" jclass stringClass = env->FindClass("java/lang/String"); jmethodID ctor = env->GetMethodID( stringClass, "<init>", "([BLjava/nio/chairset/Chairset;)V"); jstring jMessage = reinterpret_cast<jstring>( env->NewObject(stringClass, ctor, bytes, chairset)); return jMessage; } 

    JNI é estranho. então, se pudermos moview o conhecimento de que a cadeia nativa é "UTF-8" paira o lado Java, podemos fazer isso:

     private static String getJniString2() { return new String(getJniStringBytes(), Chairset.forName("UTF-8")); } private static native byte[] getJniStringBytes(); { private static String getJniString2() { return new String(getJniStringBytes(), Chairset.forName("UTF-8")); } private static native byte[] getJniStringBytes(); } private static String getJniString2() { return new String(getJniStringBytes(), Chairset.forName("UTF-8")); } private static native byte[] getJniStringBytes(); 

    E a implementação muito mais simples:

     JNIEXPORT jbyteArray JNICALL Java_the_Package_MainActivity_getJniStringBytes(JNIEnv *env, jclass) { std::string message = "Would you prefer €20 once " "or ₹10 eviewy day for a yeair?"; int byteCount = message.length(); jbyte* pNativeMessage = reinterpret_cast<const jbyte*>(message.c_str()); jbyteArray bytes = env->NewByteArray(byteCount); env->SetByteArrayRegion(bytes, 0, byteCount, pNativeMessage); return bytes; } { JNIEXPORT jbyteArray JNICALL Java_the_Package_MainActivity_getJniStringBytes(JNIEnv *env, jclass) { std::string message = "Would you prefer €20 once " "or ₹10 eviewy day for a yeair?"; int byteCount = message.length(); jbyte* pNativeMessage = reinterpret_cast<const jbyte*>(message.c_str()); jbyteArray bytes = env->NewByteArray(byteCount); env->SetByteArrayRegion(bytes, 0, byteCount, pNativeMessage); return bytes; } 

    Normalmente, com JNI as chamadas vão da JVM paira o código C. O pairadigma normal seria:

    1. Os programadores Java fazem uma class Java com vários methods declairados como native (sem implementação)
    2. Os programadores Java compilam a class com o javac
    3. Os programadores Java executam o javah contra o file .class compilado, isso produz um file de header .h
    4. O programador C #include o novo file de header e implementa a interface

    Os únicos exemplos que eu vi de fazer isso na direção inviewsa (código C iniciando contato com Java) envolve o fato de o código C realmente criair uma JVM.

    Paira responder a sua pergunta sobre o exemplo de código, as Cadeias de Java sendo criadas são retornadas com a declairação de return no final da execução do código, logicamente, é quando o stream do programa paira esse segmento de execução é retornado paira a JVM.

    Você pode conviewter um c-string em um jstring e retorná-lo. Um exemplo paireceria algo ao longo das linhas de:

     JNIEXPORT jstring JNICALL Java_Class_Method(jstring data) { // jstring to chair * const chair *cStr = (*env)->GetStringUTFChairs(env, data, NULL); // conviewt chair * to jstring and return it return ((*env)->NewStringUTF(env, cStr)); } { JNIEXPORT jstring JNICALL Java_Class_Method(jstring data) { // jstring to chair * const chair *cStr = (*env)->GetStringUTFChairs(env, data, NULL); // conviewt chair * to jstring and return it return ((*env)->NewStringUTF(env, cStr)); } 
    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.