2011-06-23 99 views
6

我有以下方案进行工作。我得到了一个共享库(libeffect.so),用于我为客户端工作的Android项目中。我没有共享库源代码,我只有.so文件。该库已预编译为可在Android设备上运行。随着共享库我有方法签名在Android应用程序中使用现有的共享库(.so)

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

所以现在我对如何使调用此本地方法,源的一些questiosn,如果这是有可能只是.so文件,所以有它们分别是:

  1. 我需要放置机方法签名在同一个包/班那些当了。所以我也可以在任何包/班在我的项目中使用这个签名定义运行时jvm将能够在共享库中找到该方法?例如,如果这个共享库首先被用在类mypackage.MyClass中,我是否需要创建相同的包,类,然后将方法签名放在那里?

  2. 我需要将这个.so文件放在我的eclipse android项目中,以便将此文件部署到我的apk文件中?

这些问题可能听起来菜鸟,但我从来没有使用JNDI工作之前,所以我有点担心,如果调用该方法doEffect没有任何错误可以实现。任何可以指导我的答案都非常受欢迎。

非常感谢 蒂亚戈

回答

6
  1. 我需要放置机方法签名在同一个包/班的 那些或定义时。所以是我 可以在任何 使用这个签名我的项目中的包/类 在运行时jvm将能够在共享库中找到方法 ? 例如,如果这个共享库 首次被用于mypackage.MyClass类 ,我是否需要创建 相同的包,类,然后将 方法签名放在那里?

无需创建相同的包/类。您可以将方法签名放入任何包中。

public class NativeLib { 

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

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

} 

2.Where做我需要把这个.so文件我的日食Android项目 里面获得该文件部署了我的apk文件里面?

您已将此.so文件放在应用程序的lib文件夹中。如果lib文件夹不存在,则可以创建一个lib文件夹并放入.so文件。你可以通过使用System.loadLibrary(“so_file”)来调用它。

+0

谢谢@Sujit。我在看这个教程,http://www.android10.org/index.php/articlesother/276-call-c-code-from-application-using-ndk,我看到生成的C++代码片段有方法名由java包和方法名组成。这不会影响我使用本地签名的方式吗?我希望我应该遵循共享库创建时使用的相同名称约定。另一个问题,一旦我在我的AndroidProject/lib文件夹中有.so文件,这个文件将与APK文件一起导出吗?我是否需要创建子文件夹armeabi文件夹?非常感谢,T – Thiago

1

1我需要放置机方法签名在同 包/班那些定义的时候。因此,或者我可以在我的项目中的任何程序包/类中使用此 签名,因此在运行时期间,jvm将能够在共享库中找到该方法?

根据http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/design.html,您必须使用匹配的包和类名称。

我只观察到JNI方法,其中C端函数被称为诸如Java_com_company_whatever_SomeClass_someMethod之类的东西,这意味着您必须将“本机”声明放入类似名称的Java类中。

使用工具“nm”或“nm ++”(它们位于NDK中的预编译文件夹中)查看.so文件并查看其中定义的函数的调用。如果你看到任何启动的Java_,那就是你想要的。

我对前面的声明持怀疑态度,您可以调用未在Java_PACKAGE_CLASS_METHOD格式中命名的函数;如果它真的有效,它可能是一种遗留行为,但即使可以,它看起来也很危险 - 你可能会得到错误的结果。

2我在哪里需要将这个.so文件放在我的eclipse android 项目中以便将此文件部署到我的apk文件中?

你。所以住在库/取决于你有多少与平台,其中“库”是一个对工作armeabi,库/ armeabi-V7A,库/ X86,和/或库/ MIPS 'src'和'res'。我不知道Android是否在libs /没有平台限定符的情况下查找,但没有明显的好处。大多数/所有英特尔设备的情况稍微复杂一些,包括花哨的技术,允许他们在x86硬件上执行大多数ARM库。另外,我喜欢声明一个JNI类的接口并提供一个工厂(这里是一个简洁的方法,但我更喜欢一个工厂类),如果事情出错,它会提供一个无操作接口的实现:它便于进行单元测试,并且避免在调用其方法之前必须混淆空值的测试(假定您感到满意,您发布的库永远不会丢失或更改方法签名 - 您的集成测试应该检查它):

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

我通常不会调用接口'xxx',但我假设您的库的JNI类不像UtilityJNI那样被调用(因此我会调用接口'Utility')。

相关问题