Calling native method twice of third party library in an Activity causes the Android application to close down

前端 未结 2 1529
别跟我提以往
别跟我提以往 2020-11-28 09:17

I have integrated two native libraries (.so ) in my application. The libraries compile fine and I can load them in my application too. The first time I invoke a native metho

相关标签:
2条回答
  • 2020-11-28 09:40

    As this is the top hit for this issue and as the issue itself still exists, it seems that the approach that ZakiMak shared with us is still the most popular solution.

    For others who may want to implement it and would like a little more detail for the latest Android releases, here are some notes I made as I stumbled through this:

    • Firstly, there is a solution which implements this approach on GitHub now. I have not tried it personally, but I have used it as a reference. It is very useful to see how the Android.mk file is structured and how the library is opened and methods called. Link is here: https://github.com/jhotovy/android-ffmpeg
    • The path to the native library folder changes over Android releases and it also appears to change every time you run the app (although this may be just in debug mode). Either way, it is best to pass the path in from the calling Java method if possible. For example:

    In the Java wrapping class:

    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);
    
    }
    

    In the 'first' or 'outer' native library:

    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);
    }
    
    • The Android.mk file is a little 'flaky' to put it politely. Because you are building two separate libraries in one Android.mk file, this may be a little more complex that other NDK make files so if you get some strange errors do some searching before you start taking your project apart. For example: https://stackoverflow.com/a/6243727/334402
    0 讨论(0)
  • 2020-11-28 09:41

    So ... my solution was starting a service that runs the shared library code, this service has a different process name ( you can set it in the Android Manifest ), as it is a different process you can kill it ( Using Process.killProcess(Process.myPid()) when it finishes running, without affecting your application in any way.

    Worked very well for me, hope it helps someone else.

    0 讨论(0)
提交回复
热议问题