安卓預編譯動態庫
㈠ 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
㈡ Android NDK 如何使用自己的共享庫
Import MoleNDK r5 支持預編譯的共享庫所謂預編譯的共享庫,就是說你自己從其他地方找來的源碼,編譯出來的共享庫。這個共享庫自己有,android 系統中沒有。使用方法如下:1、聲明一個共享庫模塊:把這個共享庫聲明為 「一個」 獨立的模塊。假如libfoo.so 與 Android.mk 位於同一個目錄。則 Android.mk 應該這樣寫: LOCAL_PATH := $(call my-dir)LOCAL_STATIC_LIBRARIES include $(CLEAR_VARS) LOCAL_MODULE := foo-prebuilt # 模塊名 LOCAL_SRC_FILES := libfoo.so # 模塊的文件路徑(相對於 LOCAL_PATH) include $(PREBUILT_SHARED_LIBRARY) # 注意這里不是 BUILD_SHARED_LIBRARY這個共享庫將被拷貝到 $PROJECT/obj/local 和 $PROJECT/libs/<abi> (stripped)2、在其他模塊中引用這個共享庫 在Android.mk 中,將這個共享庫的模塊名加入 LOCAL_STATIC_LIBRARIES (靜態庫) 或者LOCAL_SHARED_LIBRARIES (動態庫)例如, 使用 libfoo.so 的方法: include $(CLEAR_VARS) LOCAL_MODULE := foo-user LOCAL_SRC_FILES := foo-user.c LOCAL_SHARED_LIBRARY := foo-prebuilt include $(BUILD_SHARED_LIBRARY)3、為該共享庫導出頭文件 這個共享庫一般會有對應的頭文件,比如 libfoo.so 就有 foo.h 一個簡單的方法: include $(CLEAR_VARS) LOCAL_MODULE := foo-prebuilt LOCAL_SRC_FILES := libfoo.so LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include include $(PREBUILT_SHARED_LIBRARY) 這樣,使用該共享庫的模塊就會在其 LOCAL_C_INCLUDES 變數中,加入這個包含路徑 4、調試共享庫 建議你的共享庫包含調試信息。 $PROJECT/libs/<abi> 目錄下的共享庫都是 strip 之後的 有調試信息的版本,要被 ndk-gdb 使用5、共享庫的 ABI 你的共享庫與目標系統的ABI的兼容性很重要。 請檢查 TARGET_ARCH_ABI,有以下值: armeabi => ARMv5TE 以上 armeabi-v7a => ARMv7 以上 x86 => x86 建議: armeabi ABI 可以運行在所有 ARM CPU 上面。
㈢ 安卓平台屬於動態庫操作嗎
屬於
靜態庫全稱靜態鏈接庫,動態庫全稱動態鏈接庫,看到全稱就知道什麼意思了吧?也就是說在鏈接的時候才會用到的庫,只有C/C++、OC語言才會有鏈接過程,Java沒有。
在Android中說到靜態庫和動態庫,一般說的都是C/C++代碼,我們知道在android中是通過jni技術訪問到C代碼的,我們會把C/C++打包成so文件,這個就是動態庫(共享庫)。如果我們想要使用的C庫是.a形式的靜態庫時,我們要把.a包裝成so庫,具體網上有方法。
個人感覺在java語言中討論靜態庫和動態庫就是個偽概念,java是的編譯結果是位元組碼文件,不是二進制文件,而且沒有鏈接的過程,jvm在解釋執行java代碼的時候調用C++代碼只能是動態的。
在C++和object C開發中,用編譯鏈接的過程,靜態庫在鏈接過程中,會和自己寫的源代碼打到一塊,多個程序多個靜態庫。動態庫不會打到一塊,如果有共享情況的話,系統只會載入一次。
OC的代碼處理過程是很復雜的,有預處理、編譯、鏈接過程,預處理就是處理宏什麼的,編譯這個過程就很復雜了,有編譯前端和編譯後端,編譯稱機器碼(中間還會有匯編的過程),鏈接就是鏈接動態庫或者靜態庫。
Android(java)代碼處理過程就很簡單啦,畢竟是運行在虛擬機上的。沒有所謂的預處理,直接編譯,這里的編譯也就是把java代碼轉化成位元組碼,這個編譯和OC中的編譯可不是一個概念,只不過也這么叫而已。後續Aandroid還會用dex工具把.class打包成.dex,不同的VM模式(5.0以後都是ART)會對.dex進行不同的優化,具體看Android 編譯到運行APK過程總結。需要提一下的是,ART採用AOT和JIT技術,在安裝或者運行的時候,會把位元組碼轉化成機器碼,這個機器碼也會受VM控制的,具體看Android之Dalvik 、ART
C/C++、Object C屬於編譯型語言,這是毋庸置疑的,因為它們都會在生成安裝包之前編譯成機器碼。
㈣ Android 怎麼自定義共享庫
LOCAL_PATH := $(call my-dir)//標准mk語句,指編譯路徑,所有mk文件第一句都是這個 /**這個模塊表示引用了一個本地的靜態庫 include $(CLEAR_VARS) //清除各種變數,因為這些變數是靜態全局的,如果清除,下次編譯時又會用到這些變數造成出錯 LOCAL_MODULE := libopencore-amrnb //本地靜態庫模塊的名字,這個名字在下面編譯jni時需要引用 LOCAL_SRC_FILES := lib/libopencore-amrnb/smfwuxiao/article/details/6591927 NDK r5 開始支持預編譯共享庫。預編譯共享庫就是從其他地方獲得源碼編譯出的共享庫,而不是Android系統自帶的。方法如下: 1、聲明共享庫模塊 把共享庫聲明為一個獨立模塊。假如 libfoo.so 與 Android.mk 位於同一目錄。則 Android.mk 應該這樣寫: LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := foo-prebuilt # 模塊名 LOCAL_SRC_FILES := libfoo.so # 模塊的文件路徑(相對於 LOCAL_PATH) include $(PREBUILT_SHARED_LIBRARY) # 注意這里不是 BUILD_SHARED_LIBRARY 這個共享庫將被拷貝到 $PROJECT/obj/local 和 $PROJECT/libs/<abi> (strip過的) 2、在其他模塊中引用這個共享庫 在 Android.mk 中,將這個共享庫的模塊名加入 LOCAL_STATIC_LIBRARIES (靜態庫)或 LOCAL_SHARED_LIBRARIES (動態庫) 例如, 使用 libfoo.so 的方法: include $(CLEAR_VARS) LOCAL_MODULE := foo-user LOCAL_SRC_FILES := foo-user.c LOCAL_SHARED_LIBRARY := foo-prebuilt include $(BUILD_SHARED_LIBRARY) 3、為共享庫導出頭文件 這個共享庫一般有相應的頭文件,比如 libfoo.so 就有 foo.h。 一個簡單方法(在Android.mk中寫): include $(CLEAR_VARS) LOCAL_MODULE := foo-prebuilt LOCAL_SRC_FILES := libfoo.so LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include include $(PREBUILT_SHARED_LIBRARY) 這樣,使用該共享庫的模塊就會在它的 LOCAL_C_INCLUDES 變數加入該頭文件搜索路徑。 4、調試共享庫 建議你的共享庫保留調試信息。 $PROJECT/libs/<abi> 目錄下的共享庫都是 strip 之後的(沒有調試信息)。有調試信息的版本可被ndk-gdb使用。 5、共享庫 ABI 你的共享庫與目標系統ABI的兼容性很重要。 請檢查 TARGET_ARCH_ABI,有以下值: armeabi => ARMv5TE 以上 armeabi-v7a => ARMv7 以上 x86 => x86 建議: armeabi ABI 可以運行在所有 ARM CPU 上。
㈤ Android Studio手動配置Makefile、CMake
在Ubutu上編譯出來的.so文件,怎麼添加到Android項目中去使用呢?目前:可以通過
Makefile方式和CMake方式引入預編譯靜動態庫(靜態庫.a 動態庫.so)到項目中去使用。就目前而言CMake是Goole推薦使用方式,但是加入接手一個老的NDK項目是MakeFile方式,看不懂就GePi了,所以這里我們還是介紹一下MakeFile方式將靜動態庫加入到AS中,完成NDK項目的開發。廢話不多說,直接擼步驟了:
1、在src/main目錄下創建一個ndkBuild文件夾
2、在此文件中創建一個Android.mk文件
3、在此文件中創建一個test.c的源文件
4、將編譯好的的.so庫復制到src/main目錄下
如圖所示目錄結構:
1、編輯Android.mk文件
2、編輯grade(app)文件
3、編輯test.c文件
4、使用編譯好的.so庫裡面的函數
本結果運行在Android 5.1 系統上
再次運行在Android 8.0系統上
看以清楚知道,其實我們的APK包裡面就沒有libMainTest.so庫,所以APP在8.0上會出現奔潰的現象。so...
1、在src/main目錄下創建一個cmake文件夾
include:裡麵包含需要一些頭文件
cmakeTest.c:需要編譯的源文件
2、在app目錄下創建一個文件:CmakeLists.txt
3、編輯grade(app)
4、編輯cmakeTest.c文件
4、引用編譯好的libcmakeTest.so
Android 8.0.0系統:
Android 5.1.1系統:
㈥ 怎麼用Qt Creator編寫JNI的so動態庫供安卓java開發者使用
這種情況可以通過代碼目的JNI去調用,在JNI中導入頭文件,通過NDK編譯成功後即可。學習java推薦千鋒教育,該機構坐擁國內頂級的教師團隊,每年培養眾多學子,值得託付和信賴。
Java語言基礎數據類型有兩種:對象和基本類型(Primitives)。Java通過強制使用靜態類型來確保類型安全,要求每個變數在使用之前必須先聲明。這種機制和非靜態類型的語言有很大差別,非靜態語言不要求對變數進行聲明。雖然顯式類型聲明看起來較繁瑣,但其有助於編譯器對很多編程錯誤的預防,例如,由於變數名拼寫錯誤導致創建了沒有用的變數,調用了不存在的方法等。顯式聲明可以徹底防止這些錯誤被生成到運行代碼中。
想要了解更多有關java開發的相關信息,推薦咨詢千鋒教育。千鋒企業合作部於2013年成立,主要針對企業用人需求和學員職業規劃進行服務。經過8年發展,企業合作部已經成為千鋒連接企業和學員的重要紐帶。服務面對企業建立全方位、立體化、遍布全國的企業合作網路,覆蓋全國一線二線城市大中小型公司,成功幫助20000餘名人才實現就業,合作企業達20000餘家,每年簽訂1000餘份人才培養訂單,讓廣大學員沒有後顧之憂。
㈦ 第二章:Android.bp語法
注意 :關於Android.bp的權威解釋可以參見 android.bp權威文檔
Google官方語法文檔 https://android.googlesource.com/platform/build/soong
從前面的列子可以看出定義一個模塊從模塊的類型開始,模塊有不同的類型,如前面例子中的cc_library_shared,當然類型還有很多種,譬如 cc_binary、android_app 、cc_library_static 等等。模塊包含一些屬性格式為「property-name:property-value」,其中name屬性必須指定,其屬性值必須是全局唯一的。
其中默認模塊可用於在多個模塊中重復相同的屬性
srcs 屬性以字元串列表的形式指定用於編譯模塊的源文件。您可以使用模塊引用語法 「:」 來引用生成源文件的其他模塊的輸出,如 genrule 或 filegroup。
實例說明:
我們知道Android.mk中可以定義變數,當然作為新編譯系統中替代Android.mk的Android.bp也是一定存在,更加何況Android.mk還可以一定條件的轉換成Android.bp。
變數范圍限定為聲明它們的文件的其餘部分,可以使用 「=」 號賦值, 但是不能使用 「:=」 賦值。變數是不可變的,但有一個例外它們可以附上+= 賦值,但僅在變數被引用之前。
下面我們看一下正確使用變數的列子:
我們知道Android.mk中可以進行注釋,當然Android.bp裡面也可以,Android.mk中使用 # 然後添加註釋,Android.bp使用單行注釋 // 和多行注釋 /* */ 兩種方式。
具體支持以下幾種類型:
String類型、字元串列表類型和Map類型支持操作符 + 。
Android.bp可以支持android_app、cc_binary、cc_binary_host等多種類型,具體定義在Android源碼的 build/soong/androidmk/cmd/androidmk/android.go 可以查看,具體如下:
Android.bp可以支持多種預編譯類型,具體定義在Android源碼的 build/soong/androidmk/cmd/androidmk/android.go 可以查看,如下圖所示:
例如: system/core/libusbhost/Android.bp aosp9.0開始
Android.bp是一門實戰性的東西,光說不練沒有啥用,說再多不如直接開練來得舒服。那就直接開始手撕實例了,讓我們開戰嗎!
下面幾種庫編譯類型:
2.1 動態庫類型
最終編譯為so包
**2.2 java庫類型: **
最終編譯為jar包
2.3 Andorid應用類型
最終編譯為apk包
轉自: https://blog.csdn.net/tkwxty/article/details/104395820
㈧ android 怎麼引用一個靜態庫
由於工作需要,需要在framework中增加自己的動態庫,並且動態庫需要使用合作方提供的第三方靜態庫。但是在引入靜態庫編譯動態庫時總是提示失敗。具體如下:
1. 文件列表
可以看出這個配置文件的內容主要分為兩部分,第一部分預編譯靜態庫,這一過程不觸發構建過程,僅僅是重起了個名字,並且將該庫拷貝到某個路徑下(具體可以參看另一篇文章,NDK使用二進制庫的方法);第二部分是用於編譯動態本地庫,可以看出它通過LOCAL_STATIC_LIBRARIES關鍵字引入了之前預編譯的靜態庫。
㈨ 如何導入Android的AAR動態庫so文件到底怎麼樣放
1、 .so動態庫的生成 可使用gcc或者g++編譯器生成動態庫文件(此處以g++編譯器為例) g++ -shared -fPIC -c XXX.cpp g++ -shared -fPIC -o XXX.so XXX.o 2、 .so動態庫的動態調用介面函數說明 動態庫的調用關系可以在需要調用動態庫的程序編譯時,。可以看看安卓巴士教程:http://www.apkbus.com/thread-464057-1-1.html
㈩ Android 怎麼自定義共享庫
在源碼根目錄下有個 vendor (供應商) 目錄,專門用於存放各個供應商的會有代碼。其中有一個個 sample 目錄,這是 Google 用於示範如何編寫自定義共享庫的示例,它展示了自定義共享庫、JNI 調用、對庫的使用方法及皮膚定製等功能。下面我們通過對該示例進行分析,讓大家熟悉這個輕量級的框架。
1、首先看一下 sample 目錄的結構:
sample
├── Android.mk
├── apps
│ ├── Android.mk
│ ├── client
│ └── upgrade
├── frameworks
│ ├── Android.mk
│ └── PlatformLibrary
├── MODULE_LICENSE_APACHE2
├── procts
│ ├── AndroidProcts.mk
│ └── sample_addon.mk
├── README.txt
├── sdk_addon
│ ├── hardware.ini
│ └── manifest.ini
└── skins
└── WVGAMedDpi
Android.mk: 該文件用於編寫構建規則,默認繼承 Android 的 make 框架。
frameworks: 該目錄在這里的意義等同於 Android 源碼中的 frameworks 。
PlatformLibrary: 該目錄就自定義共享庫。
apps: 該目錄用於編寫依賴該庫的應用程序。經過測試也可以用來編寫不依賴該庫的程序,這有個好處,讓開發商可以把自己特有的應用集成到框架中。
client 與 upgrade: 這是兩個依賴該庫的應用程序示例。
procts: 該目錄中的文件對包含該庫與 Android 框架集成的信息,如模塊名稱等。
AndroidProcts.mk: 指明該模塊的 make 配置文件的在哪裡。
sample_addon.mk :模塊的配置信息。
sdk_addon: 該目錄對該庫的硬體需求進行定義。
hardware.ini: 定義模塊對硬體的需求。
manifest.ini: 模塊的說明文件。名稱、供應商等。
skins: 該目錄用於存放自定義皮膚。
WVGAMedDpi: 已經定義好的一套皮膚。
2.如何封裝 Java 共享庫?
PlatformLibrary 為我們展示了封裝 Java 共享庫的方法。其目錄結構如下: frameworks/PlatformLibrary
├── Android.mk
├── com.example.android.platform_library.xml
├── java
│ └── com
│ └── example
│ └── android
│ └── platform_library
│ └── PlatformLibrary.java
└── README.txt
Android.mk: 該文件說明如何構建該模塊。
com.example.android.platform_library.xml: 該文件是模塊注冊時需要的文件。該文件需要被放置到 /system/etc/permissions 目錄下。
Java /*: Java 源碼所在目錄。具體步驟:
a、編寫 Java 庫,並將源碼放到 java 目錄下。這一步和編寫普通 Java 程序沒有差別。
b、編寫 Android.mk,內容如下:
# 獲得當前目錄,清空環境變數
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS) # 源碼所在目錄,all-subdir-java-files 表示所有了目錄中的 Java 文件。
LOCAL_SRC_FILES := \
$(call all-subdir-java-files) # 該模塊是可選的。
LOCAL_MODULE_TAGS := optional # Java 模塊名稱
LOCAL_MODULE:= com.example.android.platform_library # 編譯為 Java 庫。最近以 jar 的形式而不是 apk 的形式存在。
include $(BUILD_JAVA_LIBRARY) # 構建該庫的 API 文檔
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files) $(call all-subdir-html-files)
LOCAL_MODULE:= platform_library
# 文檔對應的庫
LOCAL_DROIDDOC_OPTIONS := com.example.android.platform_library
# 庫的類型
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_DROIDDOC_USE_STANDARD_DOCLET := true # 編譯為 Java API。
include $(BUILD_DROIDDOC)
c、編寫 com.example.android.platform_library.xml,內容如下:
< xml version="1.0" encoding="utf-8" >
<permissions>
<!-- 庫的名稱及對應的 Jar 文件位置 -->
<library name="com.example.android.platform_library"
file="/system/framework/com.example.android.platform_library.jar"/>
</permissions> 現在基本的庫我們已經編寫完成,現在需要對框架中的其它文件進行配置。
d、編寫 sample/frameworks/Android.mk, 內容如下:
# 包含子目錄中的所有 make 文件 include $(call all-subdir-makefiles) 該文件與 sample/Android.mk 文件相同。
e、編寫 sample/sdk_addon/manifest.ini,內容如下: # 該模塊的名稱、供應商及描述
name=Sample Add-On
vendor=Android Open Source Project
description=sample add-on # 構建該模塊的 Android 平台代號
api=3 # 模塊的版本號。必須為整數。
revision=1 # 該模塊中包括的共享庫列表
libraries=com.example.android.platform_library # 對每個庫的詳細定義,格式如下:
# <library.name>=<name>.jar;<desc> # <library.name>: 通過前面 libraies 定義的庫的名稱。
# <name>.jar: 包含庫 API 的 jar 文件。該文件放在 libs/add-on 下面。
com.example.android.platform_library=platform_library.jar;Sample optional plaform library 該文件還可包括該模塊的其它定義,如皮膚等,為了保持該文檔清晰易懂的初衷,這里不做介紹,需要了解可以給我郵件。
f、編寫 sample/procts/sample_addom.mk,內容如下:
# 要植入系統鏡像的應用及可選類庫。可以包括 Java 庫和本地庫。這里我們只有 Java 庫。
PRODUCT_PACKAGES := \ com.example.android.platform_library # 把 xml 文件復制到系統鏡像中相應的位置去。
PRODUCT_COPY_FILES := \ vendor/
sample/frameworks/PlatformLibrary/com.example.android.platform_library.xml:system/etc/permissions/
com.example.android.platform_library.xml # 這個擴展的名稱
PRODUCT_SDK_ADDON_NAME := platform_library # 把模塊的 manifest 和硬體配置文件復制到系統鏡像中相應的位置。 PRODUCT_SDK_ADDON_COPY_FILES := \
vendor/sample/sdk_addon/manifest.ini:manifest.ini \
vendor/sample/sdk_addon/hardware.ini:hardware.in # 把庫的 Jar 包復制到相應的位置。 PRODUCT_SDK_ADDON_COPY_MODULES := \
com.example.android.platform_library:libs/platform_library.jar # 文檔的名稱。必須與。
# LOCAL_MODULE:= platform_library
PRODUCT_SDK_ADDON_DOC_MODULE := platform_library # 這個擴展繼承系統擴展。 $(call inherit-proct, $(SRC_TARGET_DIR)/proct/sdk.mk) # 這個擴展的真實名字。這個名字會用於編譯。
# 用 'make PRODUCT-<PRODUCT_NAME>-sdk_addon' 的形式來編譯此擴展。
PRODUCT_NAME := sample_addon
g、編寫 sample/procts/AndroidProcts.mk,內容如下:
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/sample_addon.mk h、最後運行make -j8 PRODUCT-sample_addon-sdk_addon,編譯擴展。
至此,我們就完成了 Java 庫的封裝。
3、接下來我們再來看如何通過 JNI 的方式對 C 代碼進行封裝。
a、在 sample/frameworks/PlatformLibrary 目錄下添加一個文件夾,用於放置 JNI 本地代碼,目錄結構如下:
frameworks/PlatformLibrary/jni
├── Android.mk
└── PlatformLibrary.cpp
b、把 frameworks/PlatformLibrary/java/com/example/android/platform_library/PlatformLibrary.java
文件改寫為 JIN 調用介面,代碼如下 : package com.example.android.platform_library; import android.util.Config;
import android.util.Log; public final class PlatformLibrary {
static { / Load the library. If it's already loaded, this does nothing. System.loadLibrary("platform_library_jni");
private int mJniInt = -1; public PlatformLibrary() {} / Test native methods. public int getInt(boolean bad) {
// this alters mJniInt //
int result = getJniInt(bad); // reverse a string, for no very good reason //
String reverse = reverseString("Android!"); Log.i("PlatformLibrary", "getInt: " + result + ", '" + reverse + "'"); return mJniInt; //
/ Simple method, called from native code. private static void yodel(String msg) {
Log.d("PlatformLibrary", "yodel: " + msg); //
/ Trivial native method call. If "bad" is true, this will throw an
/ exception. native private int getJniInt(boolean bad); / Native method that returns a new string that is the reverse of
/ the original. This also calls yodel(). native private static String reverseString(String str);
}
c、在 frameworks/PlatformLibrary/jni/PlatformLibrary.cpp 中編寫 PlatformLibrary.java 中規定本地調用的具體實現。
d、編寫 frameworks/PlatformLibrary/jni/Android.mk,內容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional # JNI 模塊的名稱
LOCAL_MODULE:= libplatform_library_jni # 依賴的源代碼文件
LOCAL_SRC_FILES:= \
PlatformLibrary.cpp # 編譯時需要的庫
LOCAL_SHARED_LIBRARIES := \
libandroid_runtime \
libnativehelper \
libcutils \
libutils # 沒有靜態庫
LOCAL_STATIC_LIBRARIES := # 包含必須的 JNI 頭文件
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) # 編譯器選項
LOCAL_CFLAGS += # 對該模塊不進行預編譯。使用預編譯可以提高模塊的性能。
LOCAL_PRELINK_MODULE := false # 把它編譯成動態共享庫
include $(BUILD_SHARED_LIBRARY) 該文件主要定義了本地庫的名字、依賴、編譯選項及編譯方式。
e、修改 frameworks/PlatformLibrary/Android.mk,在末尾添加如下兩行:
include $(CLEAR_VARS) # 調用子目錄中的 make 文件。
include $(call all-makefiles-under,$(LOCAL_PATH))
f、修改 sdk_addon/sample_addon.mk,在PRODUCT_PACKAGES 中添加該 JNI 本地庫。
PRODUCT_PACKAGES := \
com.example.android.platform_library \
libplatform_library_jni
g、編譯即可。至此,添加 JNI 庫完畢。
4、添加接下來我們再看看如何添加原生應用程序
添加原生應用程序就很簡單了,只需要把按照 Android 應用開發的基本方法,寫好一個應用,該應用可以依賴這個擴展,也可以不依賴。如 sample 中的 client 應用,目錄結構如下: apps/client/
├── AndroidManifest.xml
├── Android.mk
└── src
└── com
└── example
└── android
└── platform_library
└── client
└── Client.java
a、在應用根目錄中添加一個 Android.mk 文件,內容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS) LOCAL_MODULE_TAGS := user # 目標名稱
LOCAL_PACKAGE_NAME := PlatformLibraryClient # 只編譯這個apk包中的java文件
LOCAL_SRC_FILES := $(call all-java-files-under, src) # 使用當前版本的 SDK
LOCAL_SDK_VERSION := current # 依賴使用剛才編寫的擴展
LOCAL_JAVA_LIBRARIES := com.example.android.platform_library include $(BUILD_PACKAGE)
b、在 AndroidManifest.xml 中添加一句:
<uses-library android:name="com.example.android.platform_library" />
c、修改 sdk_addon/sample_addon.mk,在PRODUCT_PACKAGES 中添加該 JNI 本地庫。
PRODUCT_PACKAGES := \
com.example.android.platform_library \
libplatform_library_jni \
PlatformLibraryClient
d、編譯即可。至此,添加 JNI 庫完畢。
5、其他功能如添加皮膚等,這里就不一一示範了,請參考<sdk-src>/vendor/sample。