1 Нужно ли размещать подпись нативного метода в той же
пакет / класс, как те, которые определены, когда .so был, или я могу использовать это
подпись в любом пакете / классе в моем проекте, который во время выполнения
jvm сможет найти метод в общей библиотеке?
Согласно http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/design.html вы должны использовать соответствующий пакет и имя класса.
Я наблюдал только методы JNI, в которых функции на стороне C называются такими вещами, как Java_com_company_whwhat_SomeClass_someMethod, что означает, что вы должны поместить «нативные» объявления в класс Java с аналогичным именем.
Используйте инструмент «nm» или «nm ++» (они находятся в предварительно скомпилированных папках в NDK), чтобы посмотреть файл .so и увидеть, как называются определенные в нем функции. Если вы видите стартовую Java_, это то, что вы хотите.
Я скептически отношусь к предыдущему утверждению, что вы можете вызывать функции, которые не названы в формате Java_PACKAGE_CLASS_METHOD; это может быть устаревшее поведение, если оно действительно работает, но даже если вы можете, это кажется опасным - вы можете ошибиться.
2 Где мне нужно разместить этот .so файл внутри моего затмения android
проект для развертывания этого файла внутри моего apk-файла?
Ваш .so живет в libs / armeabi, libs / armeabi-v7a, libs / x86 и / или libs / mips, в зависимости от того, сколько платформ вы работаете, где libs является пэром src и «res». Я не знаю, выглядит ли Android в libs / без классификатора платформы, но в этом нет очевидного преимущества. Ситуация несколько усложняется большинством / всеми устройствами Intel, включая причудливую технологию, позволяющую им выполнять большинство библиотек ARM на оборудовании x86.
Кроме того, мне нравится объявлять интерфейс класса 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»).