androidjni調用so
① AndServer+Service打造Android伺服器實現so文件調用
通過AndServer+Service打造Android伺服器實現so文件調用的方法主要包括以下步驟:
環境配置:
so文件准備與調用:
- 編寫C/C++代碼並編譯成so動態鏈接庫。
- 在Java層通過JNI/NDK介面調用so文件中的native函數。例如,若有一個名為libyemu.so的so文件,它包含一個基於入參進行簡單字元串拼接的功能,則需在Java代碼中通過JNI介面調用該功能。
AndServer與Service結合:
- 引入AndServer庫:在Android項目中引入AndServer庫,以便在應用中構建HTTP服務。
- 創建Service:編寫一個Service來管理HTTP服務的生命周期。Service在創建HTTP服務方面具有優勢,可以簡化獲取上下文的過程。
- 配置AndServer:在Service中配置AndServer,包括創建控制器、定義介面、請求方式、參數等,以實現與so文件的交互。
- 啟動AndServer服務:在Activity或Service中啟動AndServer服務,通過網路介面調用so文件中的函數。
處理細節:
- 服務的啟動與管理:通過Service管理應用的持續運行,確保so文件調用的穩定性和效率。
- 訪問本機IP:配置網路許可權,確保應用可以訪問本機IP以訪問HTTP服務。
- 許可權管理:確保應用具有必要的許可權,如INTERNET許可權,以允許網路訪問。
驗證與測試:
- 在完成服務搭建後,通過瀏覽器訪問服務介面,驗證功能的正確性和穩定性。
- 可以通過日誌輸出、斷點調試等方式檢查so文件調用過程中的數據流和控制流。
總結:通過AndServer與Service結合,可以在Android應用中高效地調用so文件,同時提供HTTP服務介面以進行網路通信。這種方法不僅提升了應用性能,還增強了代碼的安全性和可維護性。
② 如何在Android Studio中導入JNI生成的.so庫
相信很多朋友在使用Android studio開發中,遇到過如何引入第三方so文件的問題,然而第三方官方僅僅給出了ADT環境下的集成方式。
Android studio中默認使用的是gradle編譯方式,與ADT編輯方式不一樣,那麼so文件應當如何引入呢?
其實很簡單。這里以集成JPUSH為例,看一下so文件如何引入到編譯環境,最終到JNI直接可以調用該so文件。
首先,在我們的Mole的根目錄中建立libs目錄,將jpush集成SDK中的so文件分別拷入,截圖如下:
然後就是編寫我們的build.gradle文件。
關於so文件引入的配置很簡單,代碼配置如下:
tasknativeLibsToJar(type:Zip,description:""){
destinationDirfile("$projectDir/libs")
baseName"Native_Libs2"
extension"jar"
fromfileTree(dir:"libs",include:"**/*.so")
into"lib"
}
tasks.withType(JavaCompile){
compileTask->compileTask.dependsOn(nativeLibsToJar)
}
applyplugin:'com.android.application'
android{
compileSdkVersion21
buildToolsVersion"21.1.0"
defaultConfig{
applicationId"com.wujay.footerballstar"
minSdkVersion8
targetSdkVersion21
versionCode1
versionName"1.0"
}
buildTypes{
release{
runProguardfalse
('proguard-android.txt'),'proguard-rules.pro'
}
}
tasknativeLibsToJar(type:Zip,description:""){
destinationDirfile("$projectDir/libs")
baseName"Native_Libs2"
extension"jar"
fromfileTree(dir:"libs",include:"**/*.so")
into"lib"
}
tasks.withType(JavaCompile){
compileTask->compileTask.dependsOn(nativeLibsToJar)
}
}
dependencies{
compilefileTree(dir:'libs',include:['*.jar'])
compile'com.android.support:appcompat-v7:21.0.0'
compilefiles('libs/jpush-sdk-release1.7.2.jar')
compilefiles('libs/umeng_sdk.jar')
compilefiles('libs/libammsdk.jar')
}
- sourceSets {
- main { jniLibs.srcDirs = ['libs']
- }
- }
自定義一個任務,在其中指定項目所依賴的so文件的目錄,這里用了**/*.so來寫,為了省事,指定需要拷入的目錄 into "lib",那麼動態運行庫就被拷入到lib目錄中。
完整的build.gradle文件如下:
基於有人在評論區提問,這里補充一下,有一個更為快捷輕快的配置方法
那就是在build.gradle配置中,配置如下的信息:
你的so包可以放在lib目錄下,跟jar包放在同樣的目錄,如lib/armeabi/libjpush172.so。
③ android ndk 怎樣調用第三方的so庫文件
問題描述:Android如何調用第三方SO庫;
已知條件:SO庫為Android版本連接庫(*.so文件),並提供了詳細的介面說明;
已了解解決方案:
1.將SO文件直接放到libs/armeabi下,然後代碼中System.loadLibrary("xxx");再public native static int xxx_xxx_xxx();接下來就可以直接調用xxx_xxx_xxx()方法;
2.第二種方案,創建自己的SO文件,在自己的SO文件里調用第三方SO,再在程序中調用自己的SO,這種比較復雜,需要建java類文件,生成.h文件,編寫C源文件include之前生成的.h文件並實現相應方法,最後用android NDK開發包中的ndk-build腳本生成對應的.so共享庫;
求解:
1.上面兩種方案是否可行?不可行的話存在什麼問題?
2.兩種方案有什麼區別?為什麼網上大部都是用的第二種方案?
3.只有一個*.so文件,並提供了詳細的介面說明,是否可在ANDROID中使用它?
首先要看這個SO是不是JNI規范的SO,比如有沒有返回JNI不直接支持的類型。也就是說這個SO是不是可以直接當作JNI來調用。如果答案是否定的,你只能選第二個方案。
如果答案是肯定的,還要看你是不是希望這個SO的庫直接暴露給JAVA層,如果答案是否定的,你只能選第二個方案,比如你本身也是一個庫的提供者。
一般如果你只有SO,就說明這個是別人提供給你的,你可以要求對方給你提供配套的JAVA調用文件。
1、這個要看這個SO是不是符合JNI調用的規范。還要看你自己的意願。
2、因為第二種方法最靈活,各種情況都可以實現。
3、可以
看能不能直接從JAVA調用的最簡單的方法就是看SO里的函數名是不是Java_XXX_XXX_XXX格式的
是就可以,你可以自己寫一個配套的JAVA文件,注意一下SO函數名和JAVA函數名的轉換規則,或者向SO提供方索要;
不是的話就選第二種方案吧。
1、檢查所需文件是否齊全
使用第三方動態庫,應該至少有2個文件,一個是動態庫(.so),另一個是包含
動態庫API聲明的頭文件(.h)
2、封裝原動態庫
原動態庫文件不包含jni介面需要的信息,所以我們需要對其進行封裝,所以我
們的需求是:將libadd.so 裡面的API封裝成帶jni介面的動態
3、編寫庫的封裝函數libaddjni.c
根據前面生成的com_android_libjni_LibJavaHeader.h 文件,編寫libaddjni.c,用
來生成libaddjni.so
Android中集成第三方軟體包(.jar, .so)
Android中可能會用到第三方的軟體包,這包括Java包.jar和Native包.so。jar包既可通過Eclipse開發環境集成,也可通過編譯源碼集成,看你的工作環境。
假定自己開發的程序為MyMaps,需要用到BaiMaps的庫,包括mapapi.jar和libBMapApiEngine_v1_3_1.so。
一、Eclipse中集成第三方jar包及.so動態庫
MyMaps工程下創建目錄libs以及libs/armeabi,把mapapi.jar放在的libs/目錄下,把libBMapApiEngine_v1_3_1.so放在libs/armeabi/下。
Eclipse中把第三方jar包mapapi.jar打包到MyMaps的步驟:
1. 右擊工程,選擇Properties;
2. Java Build Path,選擇Libraries;
3. Libraries頁面點擊右面按鈕「Add Library…」;
4. 選擇「User Library」,點擊「Next」;
5. 點擊「User Libraries」按鈕;
6. 在彈出界面中,點擊「New…」;
7. 輸入「User library name」,點擊「OK」確認;
8. 返回之後,選擇剛剛創建的User library,右面點擊「AddJARs」;
9. 選擇MyMaps/libs/下的mapapi.jar;
10. 確認,返回。
這樣,編譯之後,該jar包就會被打進MyMaps.apk中,libBMapApiEngine_v1_3_1.so也被打包在lib/armeabi/中。
程序運行過程中,libBMapApiEngine_v1_3_1.so被放在/data/data/<yourAppPackage>/lib/下,載入動態庫時系統會從程序的該lib/目錄下查找.so庫。
二、源碼中集成第三方集成jar包及.so動態庫
Android源碼中MyMaps放在packages/apps下。MyMaps下創建目錄libs以及libs/armeabi,並把mapapi.jar放在libs/,把libBMapApiEngine_v1_3_1.so放在libs/armeabi。
2.1 修改Android.mk文件
Android.mk文件如下:
[plain] view plain
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_JAVA_LIBRARIES := libmapapi
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := MyMaps
include $(BUILD_PACKAGE)
##################################################
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES :=libmapapi:libs/mapapi.jar
LOCAL_PREBUILT_LIBS :=libBMapApiEngine_v1_3_1:libs/armeabi/libBMapApiEngine_v1_3_1.so
LOCAL_MODULE_TAGS := optional
include $(BUILD_MULTI_PREBUILT)
# Use the following include to make our testapk.
include $(callall-makefiles-under,$(LOCAL_PATH))
1 集成jar包
LOCAL_STATIC_JAVA_LIBRARIES取jar庫的別名,可以任意取值;
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES指定prebuiltjar庫的規則,格式:別名:jar文件路徑。注意:別名一定要與LOCAL_STATIC_JAVA_LIBRARIES里所取的別名一致,且不含.jar;jar文件路徑一定要是真實的存放第三方jar包的路徑。
編譯用BUILD_MULTI_PREBUILT。
2 集成.so動態庫
LOCAL_PREBUILT_LIBS指定prebuilt so的規則,格式:別名:so文件路徑。注意:別名一般不可改變,特別是第三方jar包使用.so庫的情況,且不含.so;so文件路徑一定要是真實的存放第三方so文件的路徑。
編譯拷貝用BUILD_MULTI_PREBUILT。
2.2 加入到GRANDFATHERED_USER_MODULES
在文件user_tags.mk中,把libBMapApiEngine_v1_3_1加入到GRANDFATHERED_USER_MODULES中
[plain] view plain
GRANDFATHERED_USER_MODULES += \
… \
libBMapApiEngine_v1_3_1
user_tags.mk可以是build/core下的,也可以是$(TARGET_DEVICE_DIR)下的,推薦修改$(TARGET_DEVICE_DIR)下的。
2.3 編譯結果
MyMaps.apk編譯生成在out/target/proct/<YourProct>/system/app/下;
libBMapApiEngine_v1_3_1.so放在out/target/proct/<YourProct>/system/lib/下,這也是系統載入動態庫時搜索的路徑。
④ AndServer+Service打造Android伺服器實現so文件調用
在Android開發中,關鍵代碼下沉至native層以提升執行效率與安全性已成為常態,主要通過JNI/NDK完成Java層與native層(以C/C++為主)間的交互。native層編譯後生成so動態鏈接庫,其優點包括可移植性強、執行效率高、保密性好。
然而,如何調用so文件成為了關鍵問題。一種常見方法是利用基於Unicorn的實現,另一種則是通過在App內搭建HTTP服務實現so文件調用,前提為so文件通過了效驗等操作。AndServer的引入,是因為其提供了便捷的解決方案,無需深入研究so文件,而是通過在App內啟動HTTP服務來完成調用。
AndServer是一個用於構建Android伺服器的庫,允許在Android應用中實現HTTP服務,以調用so文件。結合Service使用,可以更靈活地控制服務生命周期,尤其在獲取上下文、包名等信息時更為方便。Service在創建HTTP服務方面具有優勢,通常會與Application集成以簡化獲取上下文的過程。
以libyemu.so為例,這是一個簡單的so文件,功能為基於入參進行簡單字元串拼接。在Android項目中調用so文件,首先需要配置環境,如使用AndroidStudio 3.4和具備特定架構(如armeabi-v7a)的Android 6系統。在項目中添加so文件和相關Java代碼,確保包名和類名的一致性。通過Activity或Service訪問so文件中的native函數,實現功能調用。
AndServer的代碼編寫涉及創建控制器、配置伺服器、處理請求等步驟。通過定義介面、請求方式、參數等,實現與so文件的交互。結合Service,可以在Activity或Service中啟動AndServer服務,通過網路介面調用so文件中的函數。
在實際應用中,服務的啟動、訪問本機IP、許可權管理等細節需要仔細處理。通過Service管理應用的持續運行,保證了so文件調用的穩定性和效率。在完成服務搭建後,通過瀏覽器訪問服務介面,驗證功能的正確性和穩定性。此過程不僅展示了AndServer在調用so文件上的便捷性,也體現了Android應用中HTTP服務的靈活應用。
整體而言,通過AndServer與Service結合,構建了從環境配置、so文件調用到HTTP服務搭建的完整流程,為Android應用提供了高效、安全的開發解決方案。實現這一過程,不僅能夠提升應用性能,還能增強代碼的安全性和可維護性。
⑤ Android怎麼調用第三方SO動態鏈接庫
在Android開發中,調用第三方SO動態鏈接庫有多種策略。一種簡便的方式是將SO文件放置於libs/armeabi目錄下,然後在代碼中使用System.loadLibrary("xxx")載入,並通過public native static int xxx_xxx_xxx()聲明方法,從而直接調用。
另一種方案較為復雜,涉及創建自己的SO文件,並在其中調用第三方SO。這種方法需要編寫Java類文件、生成.h文件、編寫C源文件並實現相應方法,最後利用android NDK開發包中的ndk-build腳本生成.so共享庫。盡管此過程較為繁瑣,但靈活性較高,能夠應對各種情況。
首先,需要檢查第三方SO是否遵循JNI調用規范。如果不符合,必須選擇第二種方案。即使符合,還需考慮是否希望將SO庫直接暴露給JAVA層。如果否,同樣應採用第二種方案。通常情況下,如果只有SO文件,意味著它是第三方提供的,可以請求對方提供配套的JAVA調用文件。
判斷SO是否遵循JNI規范的一個簡單方法是檢查其函數名是否為Java_XXX_XXX_XXX格式。如果是,可以自行編寫配套的JAVA文件,注意SO函數名與JAVA函數名之間的轉換規則。如果不是,建議採用第二種方案。
總體而言,選擇調用方式時需綜合考慮實際需求和第三方庫的具體情況,以確保代碼的簡潔性和功能的完整性。
⑥ Android怎麼調用第三方SO動態鏈接庫
對於Android調用第三方SO動態鏈接庫,我們可以從兩個主要的方案來考慮。第一個方案是直接將SO文件放置於libs/armeabi目錄下,然後在代碼中通過System.loadLibrary("xxx")來載入,緊接著定義public native static int xxx_xxx_xxx()方法,這樣就可以直接調用xxx_xxx_xxx()方法了。
第二種方案則更為復雜,它涉及到自己創建SO文件,這個SO文件會調用第三方的SO。為了實現這一點,需要創建一個Java類文件,生成對應的.h文件,編寫C源文件並包含生成的.h文件,實現相應的方法,最後使用Android NDK開發包中的ndk-build腳本生成對應的.so共享庫。
關於網上討論的第二種方案,即自己引用so庫的說法,我們需要考慮幾個因素。首先,這個SO是否符合JNI調用規范,例如是否直接支持特定類型。如果不符合,我們只能選擇第二種方案。如果符合,那麼是否希望這個SO直接暴露給JAVA層也是需要考慮的因素。如果不想,同樣只能選擇第二種方案。
通常情況下,當你只有SO文件,這表明這是一個由他人提供的庫,你可以要求對方提供配套的JAVA調用文件。因此,在實際操作中,我們首先需要檢查SO文件是否符合JNI調用規范,以及根據自身的需求決定是否需要直接暴露給JAVA層。
第二種方案之所以更為靈活,是因為它可以應對各種情況,尤其是當直接調用第三方SO文件存在困難時。而如果SO文件符合JNI規范,且你願意將其直接暴露給JAVA層,那麼直接調用的方法將更為簡便。
在嘗試從JAVA調用時,最簡單的判斷方法是查看SO里的函數名是否遵循Java_XXX_XXX_XXX的格式。如果符合,你可以自己編寫配套的JAVA文件,注意函數名的轉換規則,或者向SO提供方索要。如果不符,則需要採取第二種方案。
總的來說,選擇哪種方案取決於你的具體需求和第三方SO文件的具體情況。在實際應用中,合理選擇方案能夠有效提升開發效率。
⑦ Android so 動態載入詳解
Android SO動態載入詳解:
一、定義與適用場景
- 定義:Android SO動態載入是指在應用運行時,根據需求動態地載入和卸載SO庫文件,而不是在啟動時一次性載入所有SO庫。
- 適用場景:主要用於減少APK體積,尤其適用於那些非必要但在某些特定場景下才需要的SO庫。
二、基本流程與適配
- 基本流程:
- 檢測設備CPU架構:根據設備的CPU架構選擇合適的SO庫文件。
- 載入SO庫:使用System.loadLibrary或System.load方法載入SO庫。
- 調用本地方法:通過JNI調用SO庫中的本地方法。
- 適配要點:
- 需要根據Android版本和CPU架構進行適配,確保SO庫文件與設備兼容。
- 特別注意Android 5.x版本中的設備,盡管可能配置了64位CPU,但系統可能仍為32位,此時只能載入32位SO庫。
三、注意事項與解決方案
- 檢測系統位數:通過JNI指針的位數判斷系統位數,確保載入正確的SO庫文件。
- Android 5.x版本的bug:
- 問題:在Android 5.x版本中,可能存在一個bug,即在試圖載入一個SO庫時,即使另一個依賴的SO庫已載入,系統也可能找不到它。
- 解決方案:
- 修改LD_LIBRARY_PATH環境變數,確保系統能夠找到正確的SO庫路徑。
- 使用自定義ClassLoader來避免hook應用原生庫路徑,保證並發安全和代碼的清晰結構。
四、適用版本與擴展
- 適用版本:Android SO動態載入策略適用於Android 5.0至12.0版本,以及鴻蒙系統。
- 擴展應用:除了減少APK體積外,動態載入還可以用於實現插件化架構、熱更新等功能,提高應用的靈活性和可擴展性。