Using an existing shared library (.so) in an Android app

I have the following script to work. I was provided with a shared library (libeffect.so) for use in an Android project that I work for a client. I do not have a common library source code, I only have a .so file with me. The library is precompiled to work on Android devices. Along with the shared library, I have a method signature

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

So, now I have some questions about how to make a call to this native method, the source, if possible, having only the .so file, so here they are:

  • Is it necessary to put the built-in signature of the method in the same package / class as those that were defined when .so was or can I use this signature in any package / class in my project, that during jvm execution it will be possible to find the method in the general the library? For example, if this shared library was first used in the mypackage.MyClass class, do I need to create the same package, class, and then put the method signature there?

  • Where do I need to place this .so file inside my android eclipse project so that this file is deployed inside my apk file?

This question may sound noob, but I never worked with jndi, so I'm a little worried that you can call the doEffect method without any errors. Any answer that might help me is very welcome.

Many thanks thiago

+6
source share
2 answers
  • Is it necessary to put the signature of the native method in the same package / class as those that were defined when .so was or can I use this signature in any package / class in my project that during jvm can find the method in the shared library ? For example, if this shared library was first used in the mypackage.MyClass class, do I need to create the same package, class, and then put the method signature there?

No need to create the 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 android eclipse project? so that this file is deployed inside my apk file?

You put this .so file in the lib folder of your application. If the lib lib folder is missing, you can create the lib folder and place the .so file. you can call it using System.loadLibrary ("so_ file");

+6
source

1 Do I need to put the signature of the native method in the same package / class as those defined when .so was or can I use this signature in any package / class in my project that can find the method in the shared library during jvm execution ?

According to http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/design.html , you should use the appropriate package and class name.

I have only observed JNI methods where C-side functions are called such as Java_com_company_whatever_SomeClass_someMethod, which means you have to put the "native" declarations in the so-called Java class.

Use the "nm" or "nm ++" tool (they are in precompiled folders in the NDK) to look in the .so file and see what functions defined in it are called. If you see any starting Java_, then this is what you want.

I am skeptical of the previous statement that you can call functions that are not called in the format Java_PACKAGE_CLASS_METHOD; it can be a legacy if it really works, but even if you can, it seems dangerous - you could be wrong.

2 Where do I need to place this .so file inside my android eclipse? project so that this file is deployed inside my apk file?

Your .so lives in libs / armeabi, libs / armeabi-v7a, libs / x86 and / or libs / mips depending on how many platforms you work on, where 'libs' is an equal member of 'src' and 'res'. I don't know if Android looks in libs / without a platform qualifier, but there is no obvious benefit to this. The situation is a little complicated by most / all Intel devices, including fancy technologies that allow them to run most ARM libraries on x86 hardware.

In addition, I would like to declare an interface of the JNI class and provide a factory (here, for brevity, this is a method, but I prefer the factory class), which supplies a non-op implementation of the interface if something goes wrong: this facilitates unit testing and also avoids the need to get confused with testing zero values ​​before calling its methods (provided that it is convenient for you that your submitted library will never have missing or changed method signatures - your integration tests should check this):

 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 usually don’t call the interfaces β€œxxxI”, but I assume that your JNI class library is not called something nice, like UtilityJNI (after which I would call the interface β€œUtility”).

+1
source

Source: https://habr.com/ru/post/891179/


All Articles