在活动中调用本地方法的两倍第三方库会导致Android应用程序,以关闭第三方、两倍、应用程序、活动中

2023-09-12 01:52:51 作者:叼着烟、装酷男

我有两个本地库(.so)在我的应用程序集成。该库编译很好,我可以在我的应用程序加载它们。我第一次调用的正常工作库中的本地方法,但如果我在活动再次调用相同的方法在应用程序关闭。

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 method of a library it works fine, but if I call the same method again in the Activity the application shuts down.

我现在面临的问题是完全一样提到在这里: http://grokbase.com/t/gg/android-ndk/1226m68ydm/app-exit-on-second-native-call

The problem I am facing is exactly the same as mentioned in here : http://grokbase.com/t/gg/android-ndk/1226m68ydm/app-exit-on-second-native-call

这是工作的解决方法是调用本地方法的另一个活动,并通过System.exit(0)关闭它有力。继文章中,我尝试了成功操作后,指针设置为调用方法的NULL,但是这也没有帮助我。也是其无法卸载库一旦其通过的System.loadLibrary()加载。

The solution that works is to invoke the native method in another Activity and shut it down forcefully via System.exit(0). Following the article I tried setting the pointers to NULL of the called method after a successful operation, but this too didn't help me. Also its not possible to unload a library once its loaded by System.loadLibrary().

我要调用的本地方法不止一次,而无需创建一个新的活动。任何想法如何解决这个问题呢?

I want to call the native methods more than once without creating a new Activity. Any ideas how to solve this issue ?

(我终于找到了一个解决方案......这里是)

(I FINALLY FOUND A SOLUTION ... HERE IT IS)

好了,我终于找到了一种方法来解决这个问题。该解决方案实际上是pretty的简单。建一个独立的本地库(工具库)加载和卸载其他库。我们需要做的是使用的dlopen()和dlclose()的实用程序的本地方法。我们可以通过的System.loadLibrary()加载实用程序库像以前一样。

Okay, I have finally found a way to resolve this issue. The solution is actually pretty simple. Build another independent native library (utility library) to load and unload the other libraries. What we need to do is use dlopen() and dlclose() in the native method of the utility. We can load the utility library like before via System.loadLibrary().

所以在实用程序库的本地方法,我们需要做的是:

So in the native method of the utility library what we need to do is:

使用的#include< dlfcn.h中> //这是需要调用的dlopen()和dlclose()函数 提供处理器和函数原型:

Use#include <dlfcn.h> // this is required to call dlopen() and dlclose() functions. Provide handler and function prototype:

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

通过的dlopen打开库():

Open the library via dlopen() :

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

获取和调用库函数:

Get and Call the function of the library:

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

现在该调用完成。通过dlclose关闭它():

Now that the call is done. Close it via dlclose():

dlclose(handle);

希望这将帮助其他面临同样的问题。

Hope this will help others facing the same issue.

推荐答案

由于这是最高命中这个问题,并为自身仍然存在的问题,似乎是ZakiMak与我们分享的方法仍然是最流行的解决方案。

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.

有关其他人谁可能要实现它,并愿意为最新的Andr​​oid版本的更详细一点,这里有一些注意事项我做了,因为我通过这个迷迷糊糊:

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:

首先,有一个解决方案,实现了在GitHub上这种方法了。我还没有尝试过个人,但我已经用它作为参考。怎么看Android.mk文件的结构和库如何打开和方法被称为这是非常有用的。链接是在这里: https://github.com/jhotovy/android-ffmpeg 的路径上的Andr​​oid版本的本地库文件夹变化,它也出现改变每次运行应用程序时(尽管这可能只是在调试模式下)。无论哪种方式,最好是从调用源的Java方法如果可能的话在传递的路径。例如:

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

}

在第一或外本机库:

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

的Andr​​oid.mk文件是一个有点片状礼貌地说。因为你正在建设两个独立的库在一个Android.mk文件,这可能是一个稍微复杂一些,其他NDK使文件,因此,如果你得到一些奇怪的错误,做一些搜索,你开始把你的项目分开了。例如: http://stackoverflow.com/a/6243727/334402

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: http://stackoverflow.com/a/6243727/334402