1 我需要将本机方法签名放在同一个
包/类作为.so 时定义的那些,或者我可以使用它
在我的项目中的任何包/类中签名,在运行时
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 文件中的项目?
您的 .so 位于 libs/armeabi、libs/armeabi-v7a、libs/x86 和/或 libs/mips 中,具体取决于您使用的平台数量,其中“libs”是“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();
}
我通常不将接口称为“xxxI”,但我假设您的库的 JNI 类没有像 UtilityJNI 那样被称为很好的东西(因此我将接口称为“Utility”)。