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/下,这也是系统加载动态库时搜索的路径。