简体   繁体   English

在Android应用程序中使用现有的共享库(.so)

[英]Using existing shared library (.so) in Android application

I have the follow scenario to work on. 我有以下方案需要处理。 I was given a shared library (libeffect.so) to use in a Android project i am working for a client. 我获得了一个共享库(libeffect.so),可在我为客户端工作的Android项目中使用。 I dont have the shared library source code, i have just the .so file with me. 我没有共享库的源代码,我只有.so文件。 The library is pre-compiled to work on android devices. 该库已预编译为可在android设备上使用。 Along with the shared library I have the method signature 与共享库一起,我还有方法签名

public static native void doEffect(int param1, IntBuffer intBuffer);

So now I have some questiosn on how to make the call to this native method, of source, if this is possible having just the .so file, so there they are: 所以现在我有一些关于如何调用此本机方法的问题,如果只有.so文件,可以这样做:

  1. Do I need to place the native method signature in the same package/class as those defined when the .so was or I can use this signature in any package/class in my project that during runtime the jvm will be able to find the method in the shared library? 我是否需要将本机方法签名放置在与.so之前定义的包/类相同的包/类中,否则我可以在我的项目中的任何包/类中使用此签名,以便在运行时jvm能够在其中找到该方法。共享库? For example, if this shared library was firstly used in a class mypackage.MyClass, do I need to create the same package, class and then put the method signature there? 例如,如果此共享库首先在mypackage.MyClass类中使用,是否需要创建相同的包,类,然后在其中放置方法签名?

  2. Where do I need to place this .so file inside my eclipse android project to get this file deployed inside my apk file? 我需要将该.so文件放在我的Eclipse Android项目中的什么位置,才能将该文件部署到我的apk文件中?

These question might sound noob, but I have never worked with jndi before so I am a bit concerned if calling the method doEffect without any error can be achieve. 这些问题听起来有些菜鸟,但是我之前从未与jndi一起工作过,所以我有点担心是否可以实现没有任何错误的doEffect方法。 Any answer that can guide me is very welcome. 任何可以指导我的答案都非常欢迎。

Many Thanks Thiago 非常感谢Thiago

  1. Do I need to place the native method signature in the same package/class as those defined when the .so was or I can use this signature in any package/class in my project that during runtime the jvm will be able to find the method in the shared library? 我是否需要将本机方法签名放置在与.so之前定义的包/类相同的包/类中,否则我可以在我的项目中的任何包/类中使用此签名,以便在运行时jvm能够在其中找到该方法。共享库? For example, if this shared library was firstly used in a class mypackage.MyClass, do I need to create the same package, class and then put the method signature there? 例如,如果此共享库首先在mypackage.MyClass类中使用,是否需要创建相同的包,类,然后在其中放置方法签名?

No need to create same package/class. 无需创建相同的包/类。 You can put the method signature in any package. 您可以将方法签名放在任何包中。

public class NativeLib {

  static {
    System.loadLibrary("so_file");
  }

  public static native void doEffect(int param1, IntBuffer intBuffer);

}

2.Where do I need to place this .so file inside my eclipse android project to get this file deployed inside my apk file? 2.我需要将这个.so文件放在我的Eclipse android项目中的什么位置才能将该文件部署到我的apk文件中?

You have put this .so file in lib folder of your application . 您已将此.so文件放入了应用程序的lib文件夹中。 IF lib folder is not there then you can create a lib folder and put the .so file. 如果没有lib文件夹,则可以创建一个lib文件夹并放入.so文件。 you can call it by using System.loadLibrary("so_ file"); 您可以使用System.loadLibrary(“ so_ file”)来调用它

1 Do I need to place the native method signature in the same package/class as those defined when the .so was or I can use this signature in any package/class in my project that during runtime the jvm will be able to find the method in the shared library? 1我是否需要将本机方法签名放置在与.so之前定义的包/类相同的包/类中,否则我可以在项目中的任何包/类中使用此签名,以便在运行时jvm能够找到该方法在共享库中?

According to http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/design.html you have to use a matching package and class name. 根据http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/design.html,您必须使用匹配的包和类名。

I've only observed JNI methods where the C side functions are called things like Java_com_company_whatever_SomeClass_someMethod, which means that you have to put the 'native' declarations in a similarly-named Java class. 我仅观察到JNI方法,其中C端函数被称为诸如Java_com_company_whatever_SomeClass_someMethod之类的东西,这意味着您必须将“本机”声明放入类似名称的Java类中。

Use the tool 'nm' or 'nm++' (they're in the precompiled folders in the NDK) to look at the .so file and see what the functions defined in it are called. 使用工具“ nm”或“ nm ++”(它们位于NDK中的预编译文件夹中)查看.so文件,并查看其中定义的函数。 If you see any starting Java_, those're what you want. 如果您看到任何启动的Java_,那么这些就是您想要的。

I'm sceptical of the preceding claim that you can call functions which aren't named in the Java_PACKAGE_CLASS_METHOD format; 我对前面的说法表示怀疑,您可以调用未使用Java_PACKAGE_CLASS_METHOD格式命名的函数; it may be a legacy behaviour if it actually works, but even if you can, it seems dangerous - you might get the wrong one. 如果它确实有效,则可能是一种遗留行为,但即使可以,这似乎很危险-您可能会选择错误的行为。

2 Where do I need to place this .so file inside my eclipse android project to get this file deployed inside my apk file? 2我需要将该.so文件放在eclipse android项目中的什么位置才能将该文件部署到我的apk文件中?

Your .so lives in libs/armeabi, libs/armeabi-v7a, libs/x86, and/or libs/mips depending on how many platforms you're working with, where 'libs' is a peer of 'src' and 'res'. 您的.so根据您使用的平台数量而定,分别位于libs / armeabi,libs / armeabi-v7a,libs / x86和/或libs / mips中,其中“ libs”是“ src”和“ res”的对等体'。 I don't know whether Android looks in libs/ without the platform qualifier, but there's no evident benefit in that. 我不知道Android是否在没有平台限定符的libs /中查找,但是这样做没有明显的好处。 The situation is slightly complicated by most/all Intel devices including fancy technology allowing them to execute most ARM libraries on x86 hardware. 大多数/所有Intel设备(包括高级技术)使这种情况稍微复杂化,这些设备允许它们在x86硬件上执行大多数ARM库。

Further, I like to declare an interface of a JNI class and provide a factory (it's a method here for brevity, but I prefer a factory class) that supplies a no-op implementation of the interface if things go wrong: it facilitates unit testing and also avoids having to mess about testing for null values before calling its methods (assuming you're comfortable that your shipped library will never have missing or changed method signatures - your integration tests should check that): 此外,我想声明一个JNI类的接口并提供一个工厂(为简便起见,这里是一种方法,但我更喜欢一个工厂类),如果出问题了,该工厂将提供该接口的无操作实现:它有助于单元测试并且还避免了在调用其方法之前必须弄乱测试null值的情况(假设您很满意所提供的库永远不会丢失或更改方法签名-您的集成测试应该检查一下):

public interface YourLibI {
    @Override
    public native yourMethod();

    public static final NO_OP = new YourLibI() {
        @Override
        public void yourMethod(){}
    }
}

public class YourLib extends YourLibI {
    public newYourLibI() {
        try {
            return new YourLib();
        }
        catch (UnsatisfiedLinkError e) {
            Log.e("YourLibJNI", "Load failed, returning NO-OP dummy", e);
            return YourLibI.NO_OP;
        }
    }

    static {
        System.loadLibrary("arbitronSDK");
    }

    private YourLib() {
    }

    @Override
    public native void yourMethod();
}

I don't normally call interfaces 'xxxI' but I'm assuming your library's JNI class isn't called something nice like UtilityJNI (whereupon I'd call the interface 'Utility'). 我通常不将接口称为“ xxxI”,但我假设您的库的JNI类未如UtilityJNI那样好(因此我将接口称为“ Utility”)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM