2011-06-23 18 views
6

Tengo el siguiente escenario para trabajar. Me dieron una biblioteca compartida (libeffect.so) para usar en un proyecto de Android. Estoy trabajando para un cliente. No tengo el código fuente de la biblioteca compartida, solo tengo el archivo .so conmigo. La biblioteca está precompilada para funcionar en dispositivos Android. Junto con la biblioteca compartida tengo el método de firmaUso de la biblioteca compartida existente (.so) en la aplicación de Android

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

Así que ahora tengo algunas questiosn sobre cómo hacer la llamada a este método nativo, de la fuente, si esto es posible tener sólo el archivo .so, por lo que hay que son:

  1. ¿es necesario colocar la firma del método nativo en el mismo paquete/clase como los que se definen cuando el .so era o puedo usar esta firma en cualquier paquete/clase en mi proyecto que durante el tiempo de ejecución ¿el jvm podrá encontrar el método en la biblioteca compartida? Por ejemplo, si esta biblioteca compartida se utilizó por primera vez en una clase mypackage.MyClass, ¿necesito crear el mismo paquete, clase y luego poner la firma del método allí?

  2. ¿Dónde debo colocar este archivo .so dentro de mi proyecto eclipse de Android para que este archivo se implemente dentro de mi archivo apk?

Estos pregunta puede sonar novato, pero nunca he trabajado con jndi antes, así que estoy un poco preocupado si una llamada al método doEffect sin ningún tipo de error puede ser lograr. Cualquier respuesta que pueda guiarme es muy bienvenida.

Muchas Gracias Thiago

Respuesta

6
  1. ¿Es necesario colocar la firma del método nativo en el mismo paquete/clase como los definidos cuando el .so era o yo puedo usar esta firma en cualquier paquete/clase en mi proyecto que durante el tiempo de ejecución el jvm podrá encontrar el método en la biblioteca compartida? Por ejemplo, si esta biblioteca compartida se usó por primera vez en una clase mypackage.MyClass, ¿necesito crear el mismo paquete, clase y luego poner la firma del método allí?

No es necesario crear el mismo paquete/clase. Puedes poner la firma del método en cualquier paquete.

public class NativeLib { 

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

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

} 

2.Cuando qué es necesario colocar este archivo .so dentro de mi proyecto androide Eclipse para obtener este archivo desplegado dentro de mi archivo apk?

Has puesto este archivo .so en la carpeta lib de tu aplicación. Si la carpeta lib no está allí, entonces puedes crear una carpeta lib y poner el archivo .so. puede llamarlo usando System.loadLibrary ("so_ file");

+0

Gracias @Sujit. Estaba viendo este tutorial, http://www.android10.org/index.php/articlesother/276-call-c-code-from-application-using-ndk, y veo que el fragmento de código C++ generado tiene el nombre del método compuesto por el paquete java y el nombre del método. ¿Esto no afectará la forma en que uso la firma nativa? Pensé que debería seguir las mismas convenciones de nombre utilizadas cuando se creó la biblioteca compartida. Otra pregunta, una vez que tenga el archivo .so en mi carpeta AndroidProject/lib, ¿se exportará este archivo con el archivo APK? ¿Debo crear la carpeta sub armeabi? Muchas gracias, T – Thiago

1

1 ¿Es necesario colocar la firma del método nativo en el mismo paquete/clase como los que se definen cuando el.Entonces, ¿o puedo usar esta firma en cualquier paquete/clase en mi proyecto que durante el tiempo de ejecución, el jvm podrá encontrar el método en la biblioteca compartida?

De acuerdo con http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/design.html, tiene que usar un paquete y nombre de clase coincidentes.

Solo he observado los métodos JNI donde las funciones del lado C se llaman cosas como Java_com_company_whatever_SomeClass_someMethod, lo que significa que debe colocar las declaraciones 'native' en una clase Java de nombre similar.

Utilice la herramienta 'nm' o 'nm ++' (están en las carpetas precompiladas en el NDK) para mirar el archivo .so y ver cómo se llaman las funciones definidas en él. Si ve algún Java_ inicial, eso es lo que quiere.

Soy escéptico de la afirmación anterior de que puede llamar a funciones que no están nombradas en el formato Java_PACKAGE_CLASS_METHOD; puede ser un comportamiento heredado si realmente funciona, pero incluso si puedes, parece peligroso; es posible que te equivoques.

2 ¿Dónde tengo que colocar este archivo .so dentro de mi proyecto Eclipse androide para obtener este archivo desplegado dentro de mi archivo apk?

Su .so vive en libs/armeabi, libs/armeabi-V7A, libs/x86, y/o libs/MIPS dependiendo del número de plataformas que está trabajando, donde 'libs' es un par de 'src' y 'res'. No sé si Android busca en libs/sin el calificador de plataforma, pero no hay un beneficio evidente en eso. La situación es un poco complicada para la mayoría de los dispositivos Intel, incluida la tecnología sofisticada que les permite ejecutar la mayoría de las bibliotecas ARM en hardware x86.

Además, me gusta declarar una interfaz de clase JNI y proporcionar una fábrica (es un método aquí por brevedad, pero prefiero una clase de fábrica) que proporciona una implementación no operativa de la interfaz si las cosas van mal: facilita las pruebas unitarias y también evita tener que preocuparse por probar valores nulos antes de llamar a sus métodos (suponiendo que se siente cómodo de que su biblioteca enviada nunca tenga firmas de método faltantes o cambiadas; sus pruebas de integración deberían verificar eso):

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

Normalmente no llamo a las interfaces 'xxxI', pero supongo que la clase JNI de su biblioteca no se llama algo bueno como UtilityJNI (con lo cual llamaría a la interfaz 'Utility').

Cuestiones relacionadas