在Android中使用JNA

一.JNA簡述

略。

二.so文件的編譯

本文以C語言為例。

1.C源文件

1.  #include<stdio.h>
2.  int add(int a,int b);
3.  int add(int a,int b){
4.  int c = a + b ;
5.  return c ;
6.  }  

2.Android.mk文件


1.  LOCAL_PATH := $(call my-dir)  # 執(zhí)行編譯的工作路徑在當前路徑
2.  include $(CLEAR_VARS)  # 固定寫法 :>

4.  LOCAL_MODULE := jnatest # 自定義的編譯成的so文件名
5.  CODE_PATH :=  ./  # 源碼文件目錄

7.  LOCAL_SRC_FILES := $(CODE_PATH)/jnatest.c # 要編譯的c或cpp源碼文件,多個文件用空格分開
8.  LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(CODE_PATH)  # 頭文件所在目錄

10.  include $(BUILD_SHARED_LIBRARY)  # 生成so文件

12.  ########################## 或者以下簡單方式 #########################

14.  LOCAL_PATH := $(call my-dir)
15.  include $(CLEAR_VARS)

17.  LOCAL_MODULE :=  自定義so文件名
18.  LOCAL_SRC_FILES :=  源碼.c

20.  include $(BUILD_SHARED_LIBRARY)

3.Application.mk文件


1.  APP_BUILD_SCRIPT :=  Android.mk # 指明同目錄下的Android.mk
2.  APP_STL := gnustl_shared # 運行庫颇蜡,一般安卓使用stlport_static
3.  APP_ABI := armeabi armeabi-v7a x86 # 目標平臺,多個用空格

4.使用NDK編譯

有些網(wǎng)絡(luò)文章中講到的,可以不用App.mk文件哼绑。
這里只使用NDK進行編譯。即 你電腦上沒有安裝AndroidStudio和Eclipse也無所謂碉咆。
建議將NDK的根路徑配置到系統(tǒng)的環(huán)境變量抖韩,在cmd中輸入ndk-build能看到如下信息:


image

這里以csource文件夾為例,將源碼和mk文件放入疫铜,然后cmd的工作路徑也切換到這里:


image

執(zhí)行命令 ndk-build 進行編譯茂浮,如果這時你還看到上圖所示的2行信息,說明編譯失敗壳咕,Could not find application project directory !

此時可以直接指定編譯入口:


1.  ndk-build NDK_PROJECT_PATH=./ NDK_APPLICATION_MK=Application.mk 

image

當前文件夾里生成新的目錄席揽,libs,其中就是我們的目標so文件谓厘。


image

三.JNA依賴的準備

前往 https://github.com/java-native-access/jna/releases 幌羞,下載最新的zip包。

image

將zip文件解碼竟稳,打開 dist 目錄属桦,找到7個android-*.jar文件熊痴,解壓得到其中的so庫,并對應(yīng)的放到7個平臺目錄中聂宾。當然這7個并非都需要愁拭,armeabi、armeabi-v7a是最常用的亏吝。


image

除了這些so文件岭埠,還需要2個jar。jna-min.jar 和 jna-platform.jar 蔚鸥。


image

四.在AndroidStudio中集成so的形式

按照平常的路子創(chuàng)意幾個普通的AS項目惜论。


image

1.libs方式

常用的方式,就是將so止喷、jar馆类、arr等依賴一股腦兒放到項目默認的libs目錄里。直接強硬干脆利落弹谁。通常集成第三方的地圖乾巧、推送、一些功能框架時這么做预愤。


image

將第三方依賴加入libs后不用做其它過多配置沟于,就可以在java代碼中直接使用了。因為gradle里默認加載此目錄中的依賴:


image

現(xiàn)在植康,在libs下放入我們需要的JNA依賴和之前編譯好的so文件:


image

往常就可以直接java開黑旷太,沒有任何問題。但JNA的特殊性會導(dǎo)致一個異常:

com.cuiweiyou.jnaprj E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.cuiweiyou.jnaprj, PID: 31846
java.lang.UnsatisfiedLinkError: Native library (com/sun/jna/android-arm/libjnidispatch.so) not found in resource path (.)
at com.sun.jna.Native.loadNativeDispatchLibraryFromClasspath(Native.java:962)
at com.sun.jna.Native.loadNativeDispatchLibrary(Native.java:922)
at com.sun.jna.Native.<clinit style="margin: 0px; padding: 0px; outline: 0px; border: 0px; vertical-align: baseline; word-wrap: break-word; -webkit-appearance: none; box-sizing: border-box; background: transparent;">(Native.java:190)
at com.sun.jna.Native.loadLibrary(Native.java:544)</clinit>

此時销睁,需要在Module的gradle里配置一下:


image

這樣供璧,無論是JNA的還是我們自己的so都能比較統(tǒng)一的管理。

2.jniLibs方式

相較于上面的方式1冻记,這個多了一個目錄睡毒,但gradle里不用過多配置。
jar包仍然放在默認的libs里冗栗。
然后在 src/main/ 下新建“jniLibs”目錄演顾,將so庫文件放進去。


image

Module的gradle按照默認配置贞瞒,無修改偶房。


image

五.在Java中使用JNA

相較于JNI省事多了趁曼,JNA直接api調(diào)用即可军浆。


import com.sun.jna.Library;
import com.sun.jna.Native;
public class MainActivity extends AppCompatActivity {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
    
                int c = JNATest.INSTANCE.add(22, 33);
                Log.e("ard", "JNA返回:" + c);
    
                return null;
            }
        }.execute();
    }
    
    interface JNATest extends Library {
        JNATest INSTANCE = (JNATest) Native.loadLibrary("jnatest", JNATest.class);
        public int add(int a, int b);
    }
}

接口的屬性是public公共的、static靜態(tài)的挡闰、final最終的乒融,相當于全局常量掰盘。

| 1. 接口JNATest繼承自sun的Library,這個Library也是個接口赞季。 |
| 2. JNATest內(nèi)部通過sun的Native調(diào)用了loadLibrary方法愧捕,傳入的第一個參數(shù)就是我們自己編譯的so文件名(去掉‘lib’和后綴)。方法內(nèi)部調(diào)用了第2個參數(shù)JNATest.class的類加載器申钩,并為這個class創(chuàng)建了一個InvocationHandler次绘,這個Handler去加載我們的自己的so。最終使用Proxy將準備好的種種生成一個代理使用撒遣。 |
| 3. INSTANCE這個代理就是實現(xiàn)了“add”方法的一個JNATest的實例邮偎。JNATest的add方法對應(yīng)c代碼中的add函數(shù)。須注意java的數(shù)據(jù)類型和c的數(shù)據(jù)類型的差異义黎。本文為了簡便而僅涉及int類型禾进。 |

如此,當java調(diào)用INSTANCE的add時廉涕,最終通過代理反射去執(zhí)行C定義的原生代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末泻云,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子狐蜕,更是在濱河造成了極大的恐慌宠纯,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件层释,死亡現(xiàn)場離奇詭異征椒,居然都是意外死亡,警方通過查閱死者的電腦和手機湃累,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門勃救,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人治力,你說我怎么就攤上這事蒙秒。” “怎么了宵统?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵晕讲,是天一觀的道長。 經(jīng)常有香客問我马澈,道長瓢省,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任痊班,我火速辦了婚禮勤婚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘涤伐。我一直安慰自己馒胆,他們只是感情好缨称,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著祝迂,像睡著了一般睦尽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上型雳,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天当凡,我揣著相機與錄音,去河邊找鬼纠俭。 笑死宁玫,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的柑晒。 我是一名探鬼主播欧瘪,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼匙赞!你這毒婦竟也來了佛掖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤涌庭,失蹤者是張志新(化名)和其女友劉穎芥被,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坐榆,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡拴魄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了席镀。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片匹中。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖豪诲,靈堂內(nèi)的尸體忽然破棺而出顶捷,到底是詐尸還是另有隱情,我是刑警寧澤屎篱,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布服赎,位于F島的核電站,受9級特大地震影響交播,放射性物質(zhì)發(fā)生泄漏重虑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一秦士、第九天 我趴在偏房一處隱蔽的房頂上張望缺厉。 院中可真熱鬧,春花似錦伍宦、人聲如沸芽死。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽关贵。三九已至,卻和暖如春卖毁,著一層夾襖步出監(jiān)牢的瞬間揖曾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工亥啦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留炭剪,地道東北人。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓翔脱,卻偏偏與公主長得像奴拦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子届吁,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容