La llamada al método nativo dos veces de una biblioteca de terceros en una actividad hace que la aplicación de Android se cierre

He integrado dos bibliotecas nativas (.so) en mi aplicación. Las bibliotecas compilar bien y puedo cargarlos en mi aplicación también. La primera vez que invoco un método nativo de una biblioteca que funciona bien, pero si vuelvo a llamar al mismo método en la actividad de la aplicación se cierra.

El problema al que me enfrento es exactamente el mismo que se menciona aquí:
Http://grokbase.com/t/gg/android-ndk/1226m68ydm/app-exit-on-second-native-call

La solución que funciona es invocar el método nativo en otra actividad y cerrarlo con fuerza a través de System.exit (0). Después del artículo intenté fijar los punteros a NULL del método llamado después de una operación acertada, pero esto también no me ayudó. También no es posible descargar una biblioteca una vez cargada por System.loadLibrary ().

Quiero llamar a los métodos nativos más de una vez sin crear una nueva Actividad. ¿Alguna idea de cómo resolver este problema?

(FINALMENTE ENCONTRÉ UNA SOLUCIÓN … AQUÍ ES)

Bueno, finalmente he encontrado una manera de resolver este problema. La solución es bastante simple. Cree otra biblioteca nativa independiente (biblioteca de utilidades) para cargar y descargar las otras bibliotecas. Lo que necesitamos hacer es usar dlopen () y dlclose () en el método nativo de la utilidad. Podemos cargar la biblioteca de utilidades como antes a través de System.loadLibrary ().

Así que en el método nativo de la biblioteca de servicios públicos lo que tenemos que hacer es:

Utilice #include <dlfcn.h> // Esto es necesario para llamar a las funciones dlopen () y dlclose ().

Proporcione el manipulador y el prototipo de la función:

 void *handle; typedef int (*func)(int); // define function prototype func myFunctionName; // some name for the function 

Abra la biblioteca a través de dlopen ():

 handle = dlopen("/data/data/my.package.com/lib/somelibrary.so", RTLD_LAZY); 

Obtener y llamar a la función de la biblioteca:

 myFunctionName = (func)dlsym(handle, "actualFunctionNameInLibrary"); myFunctionName(1); // passing parameters if needed in the call 

Ahora que la llamada está terminada. Cierre a través de dlclose ():

 dlclose(handle); 

Espero que esto ayude a otros enfrentando el mismo problema.

Así que … mi solución estaba iniciando un servicio que ejecuta el código de la biblioteca compartida, este servicio tiene un nombre de proceso diferente (se puede configurar en el manifiesto de Android), ya que es un proceso diferente que puede matar (Using Process.killProcess (Process.myPid ()) cuando termine de ejecutarse, sin afectar su aplicación de ninguna manera.

Trabajó muy bien para mí, espero que ayude a alguien más.

Como este es el primer hit para este tema y como el problema aún existe, parece que el enfoque que ZakiMak compartió con nosotros sigue siendo la solución más popular.

Para otros que quieran implementarla y quieran un poco más de detalle para los últimos lanzamientos de Android, he aquí algunas notas que hice al tropezar con esto:

  • En primer lugar, hay una solución que implementa este enfoque en GitHub ahora. No lo he probado personalmente, pero lo he utilizado como referencia. Es muy útil ver cómo está estructurado el archivo Android.mk y cómo se abre la biblioteca y se llaman a los métodos. El enlace está aquí: https://github.com/jhotovy/android-ffmpeg
  • La ruta a la carpeta de la biblioteca nativa cambia a través de las versiones de Android y también parece cambiar cada vez que ejecuta la aplicación (aunque esto puede ser sólo en modo de depuración). De cualquier manera, lo mejor es pasar la ruta desde el método Java llamante si es posible. Por ejemplo:

En la clase de envolvente de Java:

 import android.content.Context; import android.util.Log; public class FfmpegJNIWrapper { //This class provides a Java wrapper around the exposed JNI ffmpeg functions. static { //Load the 'first' or 'outer' JNI library so this activity can use it System.loadLibrary("ffmpeg_wraper_multi_invoke_jni"); } public static int call_ffmpegWrapper(Context appContext, String[] ffmpegArgs) { //Get the native libary path String nativeLibPath = appContext.getApplicationInfo().nativeLibraryDir; //Call the method in the first or 'outer' library, passing it the //native library past as well as the original args return ffmpegWrapper(nativeLibPath, ffmpegArgs); } // Native methods for ffmpeg functions public static native int ffmpegWrapper(String nativeLibPath, String[] argv); } 

En la biblioteca nativa "primera" o "externa":

 JNIEXPORT jint JNICALL Java_com_yourpackage_androidffmpegwrapper_FfmpegJNIWrapper_ffmpegWrapper(JNIEnv *pEnv, jobject pObj, jstring nativeLibPath, jobjectArray javaArgv) { //Get the second or 'inner' native library path char* nativePathPassedIn = (char *)(*pEnv)->GetStringUTFChars(pEnv, nativeLibPath, NULL); char ourNativeLibraryPath[256]; snprintf(ourNativeLibraryPath, sizeof (ourNativeLibraryPath), "%s%s", nativePathPassedIn, "/libffmpeg_wraper_jni.so"); //the name of your ffmpeg library //Open the so library void *handle; typedef int (*func)(JNIEnv*, jobject, jobjectArray); handle = dlopen(ourNativeLibraryPath, RTLD_LAZY); if (handle == NULL) { __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "could not open library: %s", dlerror()); printf("Could not dlopen(\"libbar.so\"): %s\n", dlerror()); return(-1); } //Call the ffmpeg wrapper functon in the second or 'inner' library func reenterable_ffmpegWrapperFunction; reenterable_ffmpegWrapperFunction = (func)dlsym(handle, "Java_com_yourpackage_androidffmpegwrapper_FfmpegJNIWrapper_ffmpegWrapper"); reenterable_ffmpegWrapperFunction(pEnv, pObj, javaArgv); //the original arguments //Close the library dlclose(handle); // return return(1); } 
  • El archivo de Android.mk es un poco escamoso para ponerlo cortésmente. Debido a que está construyendo dos bibliotecas separadas en un archivo de Android.mk, esto puede ser un poco más complejo que otros NDK hacer archivos así que si usted consigue algunos errores extraños hacer una cierta búsqueda antes de que usted comience a tomar su proyecto aparte. Por ejemplo: https://stackoverflow.com/a/6243727/334402
  • Cómo obtener el tiempo de computación en NDK
  • ¿El enlace JavaScript de JNI de Android pasa eficientemente TypedArray / ArrayBuffer a Java como una matriz?
  • ¿Cuál es la forma correcta de usar v8 :: Locker, y por qué debo usarlo?
  • Acceder al acelerómetro de jni
  • Cómo crear jni y Android.mk?
  • Android ndk (cmake): 'referencia indefinida a `__android_log_write' cuando se usa log api en la segunda biblioteca jni
  • Android, genera archivos de encabezado jni con javah, muestra error que no puede encontrar org.opencv.core.Mat
  • Android OpenGL ES: auto-corrección env-> self y NvRmChannelSubmit fallaron
  • Excepción actualizando juego a cocos2d-x v2.0
  • JNI: Cómo obtener el tamaño jbyteArray
  • ¿Qué causa exactamente un error de "spin on suspend" en Android?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.