2011-06-23 97 views
6

我有以下方案進行工作。我得到了一個共享庫(libeffect.so),用於我爲客戶端工作的Android項目中。我沒有共享庫源代碼,我只有.so文件。該庫已預編譯爲可在Android設備上運行。隨着共享庫我有方法簽名在Android應用程序中使用現有的共享庫(.so)

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

所以現在我對如何使調用此本地方法,源的一些questiosn,如果這是有可能只是.so文件,所以有它們分別是:

  1. 我需要放置機方法簽名在同一個包/班那些當了。所以我也可以在任何包/班在我的項目中使用這個簽名定義運行時jvm將能夠在共享庫中找到該方法?例如,如果這個共享庫首先被用在類mypackage.MyClass中,我是否需要創建相同的包,類,然後將方法簽名放在那裏?

  2. 我需要將這個.so文件放在我的eclipse android項目中,以便將此文件部署到我的apk文件中?

這些問題可能聽起來菜鳥,但我從來沒有使用JNDI工作之前,所以我有點擔心,如果調用該方法doEffect沒有任何錯誤可以實現。任何可以指導我的答案都非常受歡迎。

非常感謝 蒂亞戈

回答

6
  1. 我需要放置機方法簽名在同一個包/班的 那些或定義時。所以是我 可以在任何 使用這個簽名我的項目中的包/類 在運行時jvm將能夠在共享庫中找到方法 ? 例如,如果這個共享庫 首次被用於mypackage.MyClass類 ,我是否需要創建 相同的包,類,然後將 方法簽名放在那裏?

無需創建相同的包/類。您可以將方法簽名放入任何包中。

public class NativeLib { 

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

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

} 

2.Where做我需要把這個.so文件我的日食Android項目 裏面獲得該文件部署了我的apk文件裏面?

您已將此.so文件放在應用程序的lib文件夾中。如果lib文件夾不存在,則可以創建一個lib文件夾並放入.so文件。你可以通過使用System.loadLibrary(「so_file」)來調用它。

+0

謝謝@Sujit。我在看這個教程,http://www.android10.org/index.php/articlesother/276-call-c-code-from-application-using-ndk,我看到生成的C++代碼片段有方法名由java包和方法名組成。這不會影響我使用本地簽名的方式嗎?我希望我應該遵循共享庫創建時使用的相同名稱約定。另一個問題,一旦我在我的AndroidProject/lib文件夾中有.so文件,這個文件將與APK文件一起導出嗎?我是否需要創建子文件夾armeabi文件夾?非常感謝,T – Thiago

1

1我需要放置機方法簽名在同 包/班那些定義的時候。因此,或者我可以在我的項目中的任何程序包/類中使用此 簽名,因此在運行時期間,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文件中?

你。所以住在庫/取決於你有多少與平臺,其中「庫」是一個對工作armeabi,庫/ armeabi-V7A,庫/ X86,和/或庫/ MIPS '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(); 
} 

我通常不會調用接口'xxx',但我假設您的庫的JNI類不像UtilityJNI那樣被調用(因此我會調用接口'Utility')。

相關問題