2011-06-23 7 views
6

J'ai le scénario suivant sur lequel travailler. On m'a donné une bibliothèque partagée (libeffect.so) à utiliser dans un projet Android, je travaille pour un client. Je n'ai pas le code source de la bibliothèque partagée, je n'ai que le fichier .so avec moi. La bibliothèque est pré-compilée pour fonctionner sur les appareils Android. En plus de la bibliothèque partagée J'ai la signature de la méthodeUtilisation de la bibliothèque partagée existante (.so) dans l'application Android

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

Alors maintenant, j'ai quelques questiosn sur la façon de faire l'appel à cette méthode native, de la source, si cela est possible d'avoir juste le fichier .so, donc il ils sont:

  1. Ai-je besoin de placer la signature de la méthode native dans le même package/classe que ceux définis lorsque le .donc était ou je peux utiliser cette signature dans un paquet/classe dans mon projet que lors de l'exécution le jvm sera capable de trouver la méthode dans la bibliothèque partagée? Par exemple, si cette bibliothèque partagée a d'abord été utilisée dans une classe mypackage.MyClass, ai-je besoin de créer le même package, la même classe et d'y mettre la signature de la méthode? Où dois-je placer ce fichier .so à l'intérieur de mon projet android eclipse pour obtenir ce fichier déployé dans mon fichier APK?

Ces questions peut sembler noob, mais je n'ai jamais travaillé avec JNDI avant, donc je suis un peu inquiet si vous appelez la méthode doEffect sans erreur peut être atteindre. Toute réponse qui peut me guider est la bienvenue.

Merci beaucoup Thiago

Répondre

6
  1. Ai-je besoin de placer la signature de la méthode native dans le même package/classe ceux définis lorsque l'.donc était ou je peux utiliser cette signature dans un package/class dans mon projet que pendant l'exécution le jvm sera en mesure de trouver la méthode dans la bibliothèque partagée? Par exemple, si cette bibliothèque partagée a été utilisée pour la première fois dans une classe mypackage.MyClass, dois-je créer le même package, classe, puis mettre la signature de méthode là?

Pas besoin de créer le même package/classe. Vous pouvez mettre la signature de la méthode dans n'importe quel paquet.

public class NativeLib { 

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

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

} 

2.Lorsqu'un dois-je placer ce fichier .so dans mon projet Eclipse android pour obtenir ce fichier déployé dans mon fichier apk?

Vous avez mis ce fichier .so dans le dossier lib de votre application. Si le dossier lib n'est pas là, vous pouvez créer un dossier lib et mettre le fichier .so. vous pouvez l'appeler en utilisant System.loadLibrary ("so_ file");

+0

Merci @Sujit. Je regardais ce tutoriel, http://www.android10.org/index.php/articlesother/276-call-c-code-from-application-using-ndk, et je vois que l'extrait de code C++ généré a le nom de la méthode composé du package java et du nom de la méthode. Est-ce que cela n'affecte pas la façon dont j'utilise la signature native? Je pensais que je devais suivre les mêmes conventions de nom utilisées lors de la création de la bibliothèque partagée. Une autre question, une fois que j'ai le fichier .so dans mon dossier AndroidProject/lib, ce fichier sera exporté avec le fichier APK? Ai-je besoin de créer le dossier sous-dossier armeabi? Merci beaucoup, T – Thiago

1

1 Ai-je besoin de placer la signature de la méthode native dans le même package /classe que ceux définis lorsque le.donc était ou je peux utiliser cette signature dans un paquet/classe dans mon projet que pendant l'exécution le jvm sera en mesure de trouver la méthode dans la bibliothèque partagée?

Selon http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/design.html, vous devez utiliser un package et un nom de classe correspondants.

J'ai seulement observé des méthodes JNI où les fonctions de côté C sont appelées des choses comme Java_com_company_whatever_SomeClass_someMethod, ce qui signifie que vous devez mettre les déclarations 'natives' dans une classe Java de même nom. Utilisez l'outil 'nm' ou 'nm ++' (ils se trouvent dans les dossiers précompilés du NDK) pour examiner le fichier .so et voir les fonctions qui y sont définies. Si vous voyez un Java_ commençant, c'est ce que vous voulez.

Je suis sceptique de la revendication précédente que vous pouvez appeler des fonctions qui ne sont pas nommées dans le format Java_PACKAGE_CLASS_METHOD; il peut s'agir d'un comportement hérité si cela fonctionne réellement, mais même si vous le pouvez, cela semble dangereux - vous risquez d'obtenir le mauvais.

2 Où dois-je placer ce fichier .so dans mon projet Eclipse android pour obtenir ce fichier déployé dans mon fichier apk?

Votre .donc vit dans libs/armeabi, libs/armeabi-V7A, libs/x86, et/ou libs/MIPS selon le nombre de plates-formes que vous travaillez avec, où 'libs' est un pair de 'src' et 'res'. Je ne sais pas si Android regarde dans libs/sans qualificatif de plate-forme, mais il n'y a aucun avantage évident dans cela. La situation est légèrement compliquée par la plupart/tous les périphériques Intel, y compris la technologie de fantaisie leur permettant d'exécuter la plupart des bibliothèques ARM sur le matériel x86. En outre, j'aime déclarer une interface d'une classe JNI et fournir une usine (c'est une méthode ici pour la brièveté, mais je préfère une classe usine) qui fournit une implémentation sans opération de l'interface si les choses tournent mal: il facilite les tests unitaires et évite d'avoir à tester les valeurs nulles avant d'appeler ses méthodes (en supposant que vous êtes sûr que votre bibliothèque livrée n'aura jamais manqué ou modifié les signatures de méthodes - vos tests d'intégration devraient vérifier cela):

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

Je n'appelle normalement pas les interfaces 'xxxI' mais je suppose que la classe JNI de votre bibliothèque n'est pas appelée quelque chose de sympa comme UtilityJNI (sur quoi j'appellerais l'interface 'Utility').

Questions connexes