A. android studio鎬庝箞閰嶇疆緙栬瘧so搴
鍦╝pp鐨刡uild鏂囦歡涓錛屾敞鎰忎笉鏄鏁翠釜project鐨刡uild.gradle鏂囦歡涓鐨刟ndroid{}涓鍔犲叆
sourceSets{
main{
jniLibs.srcDirs=['libs']
}
}
灝辮屼簡銆傜劧鍚庢妸so鏂囦歡澶筧rmeabi娣誨姞鍒發ibs涓灝辮屼簡銆備笉鐢ㄦ墦鍖呬簡
B. android studio開發工具編譯C、c++代碼生成so文件
目前android studio 還不支持 ndk開發,如下圖是官網的說明:
C. android studio鎬庝箞鐢熸垚.so鏂囦歡
銆銆1銆佺紪璇戠幆澧冪殑鎼寤
銆銆姝f墍璋擄細鈥滃伐嬈插杽鍏朵簨蹇呭厛鍒╁叾鍣ㄢ濆槢錛屾墍浠ュ厛鎶婃敼鍑嗗囧伐鍏峰噯澶囦竴涓嬶紝鍥犱負鏄鍦╯tudio涓嬬紪璇戠殑錛屾墍浠ュ晩錛屼粈涔坰tudio銆佷粈涔坰dk銆佷粈涔坖dk錛岃繖浜涢兘鑷宸卞幓寮勫惂錛岃繖閲岃翠竴涓媙dk榪欎釜緙栬瘧C鏂囦歡宸ュ叿鎬庝箞涓嬭澆瀹夎;
銆銆涓嬭澆瀹屼簡涔嬪悗鐩存帴鏄涓涓獄ip鐨勫帇緙╁寘錛岃В鍘嬪嵆鍙;
銆銆鐒跺悗浣犱細鍦╨ocal.properties鏂囦歡涓鐪嬪埌錛
銆銆涓嶈佹ワ紝榪樻病鏈夊畬錛宯dk鐜澧冩惌寤鴻繕鏈夋渶鍚庝竴姝ワ紝鍦╣radle.properties鐨勬枃浠舵湯灝懼姞涓奱ndroid.useDeprecatedNdk=true榪欐典唬鐮侊細
銆銆濂戒簡錛屽埌姝ゅ勭幆澧冨氨鎼寤哄畬姣曚簡銆
銆銆2銆乯ava浠g爜鍜孋浠g爜鐨勭紪鍐欐ラゅ強榪囩▼
銆銆棣栧厛鏂板緩涓涓猨ava綾籎NIUtils.java
銆銆public class JNIUtils {
銆銆static {
銆銆System.loadLibrary("huazict");
銆銆}
銆銆//java璋僀涓鐨勬柟娉曢兘闇瑕佺敤native澹版槑涓旀柟娉曞悕蹇呴』鍜宑鐨勬柟娉曞悕涓鏍
銆銆public native String getString();
銆銆}
銆銆鐒跺悗濡備笅鍥炬墍紺洪噸鏂癕ake Project涓涓嬪伐紼嬶細
銆銆浼氬湪宸ョ▼鐩褰旹:\work\MyApplication\stujni\build\intermediates\classes\debug\com\huazi\stujni\jni涓鐪嬪埌鑷宸辯紪璇戝悗鐨刢lass鏂囦歡JNIUtils.class
銆銆鍏舵″氨鏄鐢熸垚.h鏂囦歡浜
銆銆鍦╯tudio鎵撳紑Terminal鍛戒護琛屽伐鍏鳳紝鎵撳紑姝ラゆ槸View->Tool Windows->Terminal
(鎴栫洿鎺ユ寜Alt+F12
銆銆鐒跺悗鍦ㄥ懡浠よ屼腑鍏堣繘鍏ュ埌宸ョ▼鐨刴ain鐩褰曚笅
銆銆杈撳叆鍛戒護錛歫avah -d jni -classpath 鑷宸辯紪璇戝悗鐨刢lass鏂囦歡鐨勭粷瀵硅礬寰
銆銆渚嬪傦細javah -d jni -classpath
E:\work\MyApplication\stujni\build\intermediates\classes\debug
com.huazi.stujni.jni.JNIUtils(娉ㄦ剰debug鍚庣殑絀烘牸)
銆銆鐪嬪埌涓婂浘錛屽浘涓鍛戒護琛屼腑鏄鐩存帴榪涘叆鍒頒簡宸ョ▼鐨刴ain鐩褰曚笅(鍦ㄥ摢涓鐩褰曚笅榪愯屽氨浼氬湪鍝涓鐩褰曚笅鑷鍔ㄧ敓鎴恓ni鏂囦歡澶)錛屾寜鍥炶濺涔嬪悗灝變細鍦╩ain鐩褰曚笅鐢熸垚jni鏂囦歡澶癸紝鍚屾椂鐢熸垚.h鏂囦歡錛
銆銆榪欎釜鏂囦歡.h鏂囦歡涓嶉渶瑕佸仛浠諱綍淇鏀癸紝榛樿ゅ嵆鍙銆
銆銆鐜板湪鎴戜滑鏉ュ啓涓涓猼est鐨凜鏂囦歡huazict.c鍚.h鏂囦歡涓鏍鋒斁鍒癹ni鏂囦歡澶逛笅錛屼唬鐮佸備笅錛
銆銆#include "com_huazi_stujni_jni_JNIUtils.h"
銆銆/**
銆銆* 涓婅竟鐨勫紩鐢ㄦ爣絳句竴瀹氭槸.h鐨勬枃浠跺悕瀹跺悗緙錛屾柟娉曞悕涓瀹氳佸拰.h鏂囦歡涓鐨勬柟娉曞悕縐頒竴鏍
銆銆*/
銆銆JNIEXPORT jstring JNICALL Java_com_huazi_stujni_jni_JNIUtils_getString
銆銆(JNIEnv *env, jobject obj) {
銆銆return (*env)->NewStringUTF(env, "榪欐槸鎴戞祴璇曠殑jni");
銆銆}
銆銆鏈鍚庡湪鏋勫緩鏂囦歡涓鐨勯粯璁ら厤緗涓鍔犱笂錛
銆銆//ndk緙栬瘧鐢熸垚.so鏂囦歡
銆銆ndk {
銆銆moleName "huazict" //鐢熸垚鐨剆o鍚嶅瓧
銆銆abiFilters "armeabi", "armeabi-v7a", "x86" //杈撳嚭鎸囧畾涓夌峚bi浣撶郴緇撴瀯涓嬬殑so搴撱
銆銆}
銆銆鍒拌繖閲岋紝閫氳繃jni璋僀灝卞畬鎴愪簡錛岀幇鍦ㄦ垜浠鏉ユ祴璇曚竴涓嬶紝鍐欎釜TextView鏄劇ず涓涓嬭皟鐢ㄧ殑C錛
銆銆public class MainActivity extends AppCompatActivity {
銆銆@Override
銆銆protected void onCreate(Bundle savedInstanceState) {
銆銆super.onCreate(savedInstanceState);
銆銆setContentView(R.layout.activity_main);
銆銆TextView tv = (TextView)findViewById(R.id.tv);
銆銆tv.setText(new JNIUtils().getString());
銆銆}
銆銆}
銆銆ok錛屾病闂棰橈紝鍙浠ヨ皟鐢錛屽叾瀹炰篃娌℃湁鎯寵薄涓鐨勯偅涔堥毦錛屾槸鍚!
銆銆涓夈佽皟鐢ㄧ紪璇戣繃鐨.so搴
銆銆涓婅竟緙栬瘧瀹屾垚浜嗭紝鏈変漢浼氶棶錛氭垜瑕佺殑鏄緙栬瘧鍚庣殑.so搴擄紝鍒浜虹敤鐨勬椂鍊欑洿鎺ユ嬁鏉ョ敤灝卞彲浠ヤ簡錛岄偅緙栬瘧鍚庣殑.so搴撳湪鍝鍛?
銆銆鏍規嵁榪欎釜璺寰勫氨鍙浠ユ壘鍒版寚瀹氳緭鍑虹殑涓夌嶄綋緋葷粨鏋勪笅鐨.so搴撴枃浠訛紝鐒跺悗鎶.so鏂囦歡澶嶅埗鍑烘潵錛屽備笅鍥炬墍紺虹殑鏀懼埌鐩稿簲鐨勬枃浠跺す涓嬪氨ok浜嗭細
銆銆鍐嶆¤繍琛岋紝緇撴灉榪樻槸涓鏍風殑錛岃窡涓婅竟璐寸殑閭e紶鍥劇殑鏄劇ず鏁堟灉鏄鏄涓鏍風殑錛屽悓鏍瘋兘璋冪敤鍒幫紝浠g爜鎴戝氨涓嶄笂浼犱簡錛岄兘鍦ㄤ笂杈硅創涓婂幓浜嗭紝鑰屼笖涔熶笂浼犱笉浜嗭紝鍏鍙哥殑鎵鏈夋枃浠墮兘鏄鍔犲瘑鐨勶紝鎯充笂浼犻兘涓婁紶涓嶄簡銆
銆銆鍒拌繖閲岋紝鏁翠釜jni鐨勮皟鐢ㄨ繃紼嬪氨緇撴潫浜嗭紝鍖呮嫭璋冪敤jni闇瑕佺殑鐜澧冧互鍙婅皟鐢ㄧ殑榪囩▼錛屾渶鍚.so鏂囦歡鐨勫煎嚭錛岄兘鍦ㄤ笂杈逛簡錛屽傛灉涓婅竟鐨刯ni璋冪敤榪囩▼鏈変粈涔堥棶棰橈紝嬈㈣繋鐣欒█錛岃阿璋銆
D. android 怎麼編譯so文件
android NDK編譯多個so文件
android編譯系統的makefile文件Android.mk寫法如下
(1)Android.mk文件首先需要指定LOCAL_PATH變數,用於查找源文件。由於一般情況下
Android.mk和需要編譯的源文件在同一目錄下,所以定義成如下形式:
LOCAL_PATH:=$(call my-dir)
上面的語句的意思是將LOCAL_PATH變數定義成本文件所在目錄路徑。
(2)Android.mk中可以定義多個編譯模塊,每個編譯模塊都是以include $(CLEAR_VARS)開始
以include $(BUILD_XXX)結束。
include $(CLEAR_VARS)
CLEAR_VARS由編譯系統提供,指定讓GNU MAKEFILE為你清除除LOCAL_PATH以外的所有LOCAL_XXX變數,
如LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_SHARED_LIBRARIES,LOCAL_STATIC_LIBRARIES等。
include $(BUILD_STATIC_LIBRARY)表示編譯成靜態庫
include $(BUILD_SHARED_LIBRARY)表示編譯成動態庫。
include $(BUILD_EXECUTABLE)表示編譯成可執行程序
(3)舉例如下(frameworks/base/libs/audioflinger/Android.mk):
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS) 模塊一
ifeq ($(AUDIO_POLICY_TEST),true)
ENABLE_AUDIO_DUMP := true
endif
LOCAL_SRC_FILES:= \
AudioHardwareGeneric.cpp \
AudioHardwareStub.cpp \
AudioHardwareInterface.cpp
ifeq ($(ENABLE_AUDIO_DUMP),true)
LOCAL_SRC_FILES += AudioDumpInterface.cpp
LOCAL_CFLAGS += -DENABLE_AUDIO_DUMP
endif
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder \
libmedia \
libhardware_legacy
ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
LOCAL_CFLAGS += -DGENERIC_AUDIO
endif
LOCAL_MODULE:= libaudiointerface
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
LOCAL_SRC_FILES += A2dpAudioInterface.cpp
LOCAL_SHARED_LIBRARIES += liba2dp
LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
LOCAL_C_INCLUDES += $(call include-path-for, bluez)
endif
include $(BUILD_STATIC_LIBRARY) 模塊一編譯成靜態庫
include $(CLEAR_VARS) 模塊二
LOCAL_SRC_FILES:= \
AudioPolicyManagerBase.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libmedia
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_LDLIBS += -ldl
else
LOCAL_SHARED_LIBRARIES += libdl
endif
LOCAL_MODULE:= libaudiopolicybase
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
LOCAL_CFLAGS += -DWITH_A2DP
endif
ifeq ($(AUDIO_POLICY_TEST),true)
LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
endif
include $(BUILD_STATIC_LIBRARY) 模塊二編譯成靜態庫
include $(CLEAR_VARS) 模塊三
LOCAL_SRC_FILES:= \
AudioFlinger.cpp \
AudioMixer.cpp.arm \
AudioResampler.cpp.arm \
AudioResamplerSinc.cpp.arm \
AudioResamplerCubic.cpp.arm \
AudioPolicyService.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder \
libmedia \
libhardware_legacy
ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
LOCAL_STATIC_LIBRARIES += libaudiointerface libaudiopolicybase
LOCAL_CFLAGS += -DGENERIC_AUDIO
else
LOCAL_SHARED_LIBRARIES += libaudio libaudiopolicy
endif
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_LDLIBS += -ldl
else
LOCAL_SHARED_LIBRARIES += libdl
endif
LOCAL_MODULE:= libaudioflinger
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
LOCAL_SHARED_LIBRARIES += liba2dp
endif
ifeq ($(AUDIO_POLICY_TEST),true)
LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
endif
ifeq ($(TARGET_SIMULATOR),true)
ifeq ($(HOST_OS),linux)
LOCAL_LDLIBS += -lrt -lpthread
endif
endif
ifeq ($(BOARD_USE_LVMX),true)
LOCAL_CFLAGS += -DLVMX
LOCAL_C_INCLUDES += vendor/nxp
LOCAL_STATIC_LIBRARIES += liblifevibes
LOCAL_SHARED_LIBRARIES += liblvmxservice
# LOCAL_SHARED_LIBRARIES += liblvmxipc
endif
include $(BUILD_SHARED_LIBRARY) 模塊三編譯成動態庫
(4)編譯一個應用程序(APK)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Build all java files in the java subdirectory-->直譯(建立在java子目錄中的所有Java文件)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Name of the APK to build-->直譯(創建APK的名稱)
LOCAL_PACKAGE_NAME := LocalPackage
# Tell it to build an APK-->直譯(告訴它來建立一個APK)
include $(BUILD_PACKAGE)
(5)編譯一個依賴於靜態Java庫(static.jar)的應用程序
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# List of static libraries to include in the package
LOCAL_STATIC_JAVA_LIBRARIES := static-library
# Build all java files in the java subdirectory
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Name of the APK to build
LOCAL_PACKAGE_NAME := LocalPackage
# Tell it to build an APK
include $(BUILD_PACKAGE)
(6)編譯一個需要用平台的key簽名的應用程序
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Build all java files in the java subdirectory
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Name of the APK to build
LOCAL_PACKAGE_NAME := LocalPackage
LOCAL_CERTIFICATE := platform
# Tell it to build an APK
include $(BUILD_PACKAGE)
(7)編譯一個需要用特定key前面的應用程序
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Build all java files in the java subdirectory
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Name of the APK to build
LOCAL_PACKAGE_NAME := LocalPackage
LOCAL_CERTIFICATE := vendor/example/certs/app
# Tell it to build an APK
include $(BUILD_PACKAGE)
(8)添加一個預編譯應用程序
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Mole name should match apk name to be installed.
LOCAL_MODULE := LocalMoleName
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
include $(BUILD_PREBUILT)
(9)添加一個靜態JAVA庫
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Build all java files in the java subdirectory
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Any libraries that this library depends on
LOCAL_JAVA_LIBRARIES := android.test.runner
# The name of the jar file to create
LOCAL_MODULE := sample
# Build a static jar file.
include $(BUILD_STATIC_JAVA_LIBRARY)
(10)Android.mk的編譯模塊中間可以定義相關的編譯內容,也就是指定相關的變數如下:
LOCAL_AAPT_FLAGS
LOCAL_ACP_UNAVAILABLE
LOCAL_ADDITIONAL_JAVA_DIR
LOCAL_AIDL_INCLUDES
LOCAL_ALLOW_UNDEFINED_SYMBOLS
LOCAL_ARM_MODE
LOCAL_ASFLAGS
LOCAL_ASSET_DIR
LOCAL_ASSET_FILES 在Android.mk文件中編譯應用程序(BUILD_PACKAGE)時設置此變數,表示資源文件,
通常會定義成LOCAL_ASSET_FILES += $(call find-subdir-assets)
LOCAL_BUILT_MODULE_STEM
LOCAL_C_INCLUDES 額外的C/C++編譯頭文件路徑,用LOCAL_PATH表示本文件所在目錄
舉例如下:
LOCAL_C_INCLUDES += extlibs/zlib-1.2.3
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
LOCAL_CC 指定C編譯器
LOCAL_CERTIFICATE 簽名認證
LOCAL_CFLAGS 為C/C++編譯器定義額外的標志(如宏定義),舉例:LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1
LOCAL_CLASSPATH
LOCAL_COMPRESS_MODULE_SYMBOLS
LOCAL_COPY_HEADERS install應用程序時需要復制的頭文件,必須同時定義LOCAL_COPY_HEADERS_TO
LOCAL_COPY_HEADERS_TO install應用程序時復制頭文件的目的路徑
LOCAL_CPP_EXTENSION 如果你的C++文件不是以cpp為文件後綴,你可以通過LOCAL_CPP_EXTENSION指定C++文件後綴名
如:LOCAL_CPP_EXTENSION := .cc
注意統一模塊中C++文件後綴必須保持一致。
LOCAL_CPPFLAGS 傳遞額外的標志給C++編譯器,如:LOCAL_CPPFLAGS += -ffriend-injection
LOCAL_CXX 指定C++編譯器
LOCAL_DX_FLAGS
LOCAL_EXPORT_PACKAGE_RESOURCES
LOCAL_FORCE_STATIC_EXECUTABLE 如果編譯的可執行程序要進行靜態鏈接(執行時不依賴於任何動態庫),則設置LOCAL_FORCE_STATIC_EXECUTABLE:=true
目前只有libc有靜態庫形式,這個只有文件系統中/sbin目錄下的應用程序會用到,這個目錄下的應用程序在運行時通常
文件系統的其它部分還沒有載入,所以必須進行靜態鏈接。
LOCAL_GENERATED_SOURCES
LOCAL_INSTRUMENTATION_FOR
LOCAL_INSTRUMENTATION_FOR_PACKAGE_NAME
LOCAL_INTERMEDIATE_SOURCES
LOCAL_INTERMEDIATE_TARGETS
LOCAL_IS_HOST_MODULE
LOCAL_JAR_MANIFEST
LOCAL_JARJAR_RULES
LOCAL_JAVA_LIBRARIES 編譯java應用程序和庫的時候指定包含的java類庫,目前有core和framework兩種
多數情況下定義成:LOCAL_JAVA_LIBRARIES := core framework
注意LOCAL_JAVA_LIBRARIES不是必須的,而且編譯APK時不允許定義(系統會自動添加)
LOCAL_JAVA_RESOURCE_DIRS
LOCAL_JAVA_RESOURCE_FILES
LOCAL_JNI_SHARED_LIBRARIES
LOCAL_LDFLAGS 傳遞額外的參數給連接器(務必注意參數的順序)
LOCAL_LDLIBS 為可執行程序或者庫的編譯指定額外的庫,指定庫以"-lxxx"格式,舉例:
LOCAL_LDLIBS += -lcurses -lpthread
LOCAL_LDLIBS += -Wl,-z,origin
LOCAL_MODULE 生成的模塊的名稱(注意應用程序名稱用LOCAL_PACKAGE_NAME而不是LOCAL_MODULE)
LOCAL_MODULE_PATH 生成模塊的路徑
LOCAL_MODULE_STEM
LOCAL_MODULE_TAGS 生成模塊的標記
LOCAL_NO_DEFAULT_COMPILER_FLAGS
LOCAL_NO_EMMA_COMPILE
LOCAL_NO_EMMA_INSTRUMENT
LOCAL_NO_STANDARD_LIBRARIES
LOCAL_OVERRIDES_PACKAGES
LOCAL_PACKAGE_NAME APK應用程序的名稱
LOCAL_POST_PROCESS_COMMAND
LOCAL_PREBUILT_EXECUTABLES 預編譯including $(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)時所用,指定需要復制的可執行文件
LOCAL_PREBUILT_JAVA_LIBRARIES
LOCAL_PREBUILT_LIBS 預編譯including $(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)時所用, 指定需要復制的庫.
LOCAL_PREBUILT_OBJ_FILES
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES
LOCAL_PRELINK_MODULE 是否需要預連接處理(默認需要,用來做動態庫優化)
LOCAL_REQUIRED_MODULES 指定模塊運行所依賴的模塊(模塊安裝時將會同步安裝它所依賴的模塊)
LOCAL_RESOURCE_DIR
LOCAL_SDK_VERSION
LOCAL_SHARED_LIBRARIES 可鏈接動態庫
LOCAL_SRC_FILES 編譯源文件
LOCAL_STATIC_JAVA_LIBRARIES
LOCAL_STATIC_LIBRARIES 可鏈接靜態庫
LOCAL_UNINSTALLABLE_MODULE
LOCAL_UNSTRIPPED_PATH
LOCAL_WHOLE_STATIC_LIBRARIES 指定模塊所需要載入的完整靜態庫(這些精通庫在鏈接是不允許鏈接器刪除其中無用的代碼)
LOCAL_YACCFLAGS
OVERRIDE_BUILT_MODULE_PATH
E. android中如何編譯出64位so文件
如果是在Linux下編譯Android源碼,有可能是兩個原因:
1. lunch命令有32位和64位的區別,注意選能夠編譯64位so的命令
2. mk文件中有LOCAL_MODULE_PATH的值比如為$(TARGET_OUT_SHARED_LIBRARIES)/hw的改為LOCAL_MODULE_RELATIVE_PATH := hw,後一種可以分別在lib和lib64下分別生成32位和64位的so文件,這個看看編譯後的信息就知道了.
F. android so文件怎麼用
相信很多朋友在使用Androidstudio開發中,遇到過如何引入第三方so文件的問題,然而第三方官方僅僅給出了ADT環境下的集成方式。
Android studio中默認使用的是gradle編譯方式,與ADT編輯方式不一樣,那麼so文件應當如何引入呢?
其實很簡單。這里以集成JPUSH為例,看一下so文件如何引入到編譯環境,最終到JNI直接可以調用該so文件。
首先,在我們的Mole的根目錄中建立libs目錄,將jpush集成SDK中的so文件分別拷入,截圖如下:
然後就是編寫我們的build.gradle文件。
關於so文件引入的配置很簡單,代碼配置如下:
[html]view plainprint?
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)
}
自定義一個任務,在其中指定項目所依賴的so文件的目錄,這里用了**/*.so來寫,為了省事,指定需要拷入的目錄 into "lib",那麼動態運行庫就被拷入到lib目錄中。
完整的build.gradle文件如下:
[html]view plainprint?
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')
}
G. ndk-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/下,這也是系統載入動態庫時搜索的路徑。