App 的開發(fā)更偏向于用戶層面璧瞬,從 UI 展示到業(yè)務(wù)邏輯處理户辫,全程處理用戶的行為。而 SDK 面向的是開發(fā)者嗤锉,開發(fā)更偏向于功能方面渔欢,注重功能的開發(fā)實(shí)現(xiàn)。不妨來看看 FinClip 移動端工程師整理的如何編寫一個(gè) SDK瘟忱,還是很有參考價(jià)值奥额。
一、什么是 SDK?
SDK 全稱 Software Development Kit访诱,廣義上的 SDK 是為特定的軟件包垫挨、軟件框架、硬件平臺触菜、操作系統(tǒng)等建立應(yīng)用程序時(shí)所使用的開發(fā)工具的集合(在 iOS 項(xiàng)目中九榔,SDK 也被稱為庫)。
在 iOS 開發(fā)或 Android 開發(fā)中,不可避免會需要使用第三方工具提升產(chǎn)品的開發(fā)效率帚屉,比如用于消息推送的極光谜诫,用于第三方支付與登錄的支付寶,微信等等攻旦。但大多數(shù)商用產(chǎn)品都不會直接給出源碼(可能只有為愛發(fā)電的開源項(xiàng)目才會無私提供源碼)喻旷,而我們在開發(fā) App 時(shí)就需要將這些第三方 SDK 集成在我們的項(xiàng)目之中。
SDK 的全稱是 Software Development Kit牢屋,翻譯過來是軟件開發(fā)工具包且预,這是一種被用來輔助開發(fā)某類軟件而編寫的特定軟件包。
二烙无、SDK 設(shè)計(jì)的基本原則
一款好用且設(shè)計(jì)充分的 SDK 必須要遵循以下 4 條基本原則锋谐,即:
- SDK 安全,穩(wěn)定
- 統(tǒng)一的開發(fā)規(guī)范
- Library 小而精
- 不依賴第三方 SDK
- 安全截酷,穩(wěn)定:考慮到 SDK 是需要嵌入到 App 里面去的涮拗,所以 SDK 最重要的特性就是安全性,不會因?yàn)閬y開放接口而導(dǎo)致 App 數(shù)據(jù)泄露迂苛;其次重要的是 SDK 的穩(wěn)定性三热, SDK 的 Crash 如果沒有被捕獲進(jìn)行處理,則會導(dǎo)致應(yīng)用徹底崩潰(這樣就會導(dǎo)致第三方接入的 App 體驗(yàn)性非常差)三幻,甚至?xí)苯訉?dǎo)致接入方的用戶流失就漾;
- 統(tǒng)一的開發(fā)規(guī)范:對于 SDK 開發(fā)規(guī)范來說,統(tǒng)一的命名規(guī)范很重要念搬,最好的狀態(tài)是“接入方看到接口命名就能知道是哪家廠商的 SDK”抑堡,換句話說就是 SDK 的命名規(guī)范統(tǒng)一,形成自己公司的品牌效應(yīng)朗徊,此外也方便開發(fā)者進(jìn)行接入使用首妖。此外也需要具有自己的編碼規(guī)范,你可以在網(wǎng)上找到大廠的規(guī)范模板荣倾,并通過借鑒整理出屬于自己的規(guī)范悯搔,從而盡早統(tǒng)一代碼風(fēng)格;
- Library 小而精:小是指要避免造成接入方的App增加很大舌仍,不然會引起接入方的不滿妒貌,甚至下架。精是指功能要專注铸豁,比如極光推送灌曙,就是專注推送相關(guān)的功能;
- 不依賴第三方 SDK:這個(gè)也很好理解节芥,SDK 中如果又依賴其他第三方 SDK在刺, 不僅會導(dǎo)致 SDK 的體積變大逆害,也會影響接入方集成 SDK 的相關(guān)成本。
三蚣驼、在 iOS 環(huán)境下開發(fā) SDK
1. iOS 環(huán)境下的 SDK
如同上文所說魄幕,在 iOS 開發(fā)中,我們將 SDK 稱為“庫”颖杏,我們是這樣對其定義的:
- 一般是給應(yīng)用提供通用服務(wù)的纯陨,非獨(dú)立運(yùn)行的程序集合;
- 一般都是編譯過的留储,方便使用翼抠。
我們會根據(jù)庫的調(diào)用方法分為“靜態(tài)庫”和“動態(tài)庫”兩種:
- 靜態(tài)連接:一般是指在創(chuàng)建應(yīng)用程序的時(shí)候,將庫集成進(jìn)去获讳,這樣做的好處就是應(yīng)用程序包自身可以獨(dú)立運(yùn)行阴颖,而不好的地方就是包會略顯臃腫,庫不能共享(靜態(tài)庫經(jīng)常以 .a 結(jié)尾)丐膝;
- 動態(tài)連接:創(chuàng)建應(yīng)用的時(shí)候只約定好與庫之間的調(diào)用關(guān)系量愧,而不徹底將庫包集成進(jìn)應(yīng)用。這樣在應(yīng)用運(yùn)行時(shí)帅矗,需要運(yùn)行環(huán)境中提供庫侠畔,并且連接裝載。優(yōu)劣與靜態(tài)庫相反损晤,動態(tài)鏈接庫需要庫環(huán)境,但由于本身不集成庫內(nèi)容红竭,會比較小尤勋,同時(shí)也為和其他應(yīng)用共享庫的使用提供了可能(常見的動態(tài)庫是 Windows 下的 .dll,Linux 下的 .so茵宪,Mac 下的 .dylib/.tbd)最冰。
特別注意:平時(shí)我們經(jīng)常說的 Framework (in Apple) 是 Cocoa/Cocoa Touch 程序中使用的一種資源打包方式,可以將代碼文件稀火、頭文件暖哨、資源文件、說明文檔等集中在一起凰狞,方便開發(fā)者使用篇裁。也就是說我們的 Framework 其實(shí)是資源打包的方式,和靜態(tài)庫動態(tài)庫的本質(zhì)是沒有什么關(guān)系赡若。
2. 靜態(tài)庫和動態(tài)庫的區(qū)別
如果說要找出靜態(tài)庫與動態(tài)庫的區(qū)別达布,那可以從文件鏈接(每個(gè)源代碼模塊獨(dú)立編譯,然后按照需要將他們組裝起來逾冬,這個(gè)組裝模塊的過程黍聂,就是鏈接)的角度進(jìn)行解釋:
- 靜態(tài)庫:鏈接時(shí)會被完整的復(fù)制到可執(zhí)行文件中躺苦,所以如果兩個(gè)程序都用了某個(gè)靜態(tài)庫,那么每個(gè)二進(jìn)制可執(zhí)行文件里面产还,都會含有這份靜態(tài)庫的代碼匹厘;
- 動態(tài)庫:鏈接時(shí)不復(fù)制,而是在程序啟動后動態(tài)加載脐区,然后再進(jìn)行符號決議(符號綁定) 愈诚。理論上動態(tài)庫只存在一份就可以了。其他的程序都可以動態(tài)鏈接到這個(gè)動態(tài)庫上面坡椒,從而節(jié)省內(nèi)存(內(nèi)存中只有一份動態(tài)庫)扰路。另外一個(gè)好處是,由于動態(tài)庫并不綁定到可執(zhí)行程序上倔叼,所以我們想升級這個(gè)動態(tài)庫就很容易汗唱,windows和linux上面一般插件和模塊機(jī)制都是這樣實(shí)現(xiàn)的。
具體的優(yōu)劣勢可以看這張表:
庫類型 | 優(yōu)點(diǎn) | 缺點(diǎn) |
---|---|---|
靜態(tài)庫 | 1. 目標(biāo)程序沒有外部依賴丈攒,直接就可以運(yùn)行哩罪。 2. 效率較動態(tài)庫高。 | 1. 會使用目標(biāo)程序的體積增大巡验。 |
動態(tài)庫 | 1. 不需要拷貝到目標(biāo)程序中际插,不會影響目標(biāo)程序的體積。 2. 同一份庫可以被多個(gè)程序使用(因?yàn)檫@個(gè)原因显设,動態(tài)庫也被稱作共享庫)框弛。 3. 編譯時(shí)才載入的特性,也可以讓我們隨時(shí)對庫進(jìn)行替換捕捂,而不需要重新編譯代碼瑟枫。實(shí)現(xiàn)動態(tài)更新 | 1. 動態(tài)載入會帶來一部分性能損失(可以忽略不計(jì)) 2. 動態(tài)庫也會使得程序依賴于外部環(huán)境。如果環(huán)境缺少動態(tài)庫或者庫的版本不正確指攒,就會導(dǎo)致程序無法運(yùn)行(Linux lib not found 錯誤)慷妙。 |
靜態(tài)庫可以簡單理解為一堆目標(biāo)文件(.o/.obj)的打包體(并非二進(jìn)制文件),而動態(tài)庫可以簡單理解為 一個(gè)沒有 main 函數(shù)的可執(zhí)行文件允悦。
3. 了解 iOS 的動態(tài)庫(即被閹割的動態(tài)庫)
有一個(gè)背景知識需要注意膝擂,iOS 官方規(guī)定不允許存在動態(tài)庫,并且所有的 IPA 都需要經(jīng)過 Apple 的私鑰加密后才能用隙弛,即使你用了動態(tài)庫也會因?yàn)楹灻e誤而無法加載(越獄和非 App Store 除外)架馋。于是這就把開發(fā)者自己開發(fā)動態(tài)庫這件事變成為了天方夜譚。
iOS8 之前的 iOS 應(yīng)用都是運(yùn)行在沙盒當(dāng)中的全闷,不同程序之間不能共享代碼绩蜻,并且 iOS 又是單進(jìn)程運(yùn)行的(也就是某一時(shí)刻只有一個(gè)進(jìn)程在運(yùn)行),那么即使你寫個(gè)共享庫也無法共享給他人室埋。
而動態(tài)下載代碼又是被蘋果官方明令禁止的办绝,也就是說動態(tài)庫的優(yōu)勢完全無法發(fā)揮伊约,所以動態(tài)庫也就沒有存在的必要了。
但是這一切問題都隨著 iOS8 發(fā)布之后的 App Extesion 特性孕蝉, Swift 的誕生發(fā)生了奇妙的改變屡律。
由于 iOS 主 App 需要和 Extension 共享代碼,Swift 語言機(jī)制也需要動態(tài)庫降淮,于是蘋果后來提出了 Embedded Framework超埋,這種動態(tài)庫允許 APP 和 App Extension 共享代碼(動態(tài)庫的生命被限定在一個(gè)APP進(jìn)程內(nèi))。
更簡單的解釋:雖然提供了動態(tài)庫佳鳖,但這是被閹割的動態(tài)庫霍殴。
盡管如此,這種動態(tài)庫(Embedded Framework) 和系統(tǒng)的 UIKit.Framework 還是有很大區(qū)別的系吩。傳統(tǒng)的動態(tài)庫是給多個(gè)進(jìn)程使用的来庭,而這里的動態(tài)庫(Embedded Framework)是給單個(gè)進(jìn)程里面多個(gè)可執(zhí)行文件用的。
系統(tǒng)的 Framework 不再需要拷貝到目標(biāo)程序中穿挨,我們自己做出來的動態(tài)庫(Embedded Framework) 哪怕是動態(tài)的月弛,最后也還是要拷貝到 App 中(App 和 Extension 的 Bundle 是共享的)。所以蘋果沒有直接把這種 Embedded Framework稱作動態(tài)庫而是叫 Embedded Framework科盛。
上面提到的 Swift 也有原因帽衙,在 Swift 的項(xiàng)目中如果要在項(xiàng)目中使用外部代碼,可選的方式只有兩種贞绵,一種是把代碼拷貝到工程中厉萝,另一種是用動態(tài) Framework。使用靜態(tài)庫是不支持的榨崩。
這個(gè)問題的根本原因是冀泻, Swift 的運(yùn)行庫沒有被包含在 iOS 系統(tǒng)中,反而會被打包進(jìn) App 中(這也是造成 Swift App 體積大的原因)蜡饵,靜態(tài)庫會導(dǎo)致最終的目標(biāo)程序中包含重復(fù)的運(yùn)行庫。
4. 以動態(tài)庫為例胳施,開始制作SDK
第一步:創(chuàng)建 App 工程溯祸,命名為 RealDemo
如果不清楚怎么創(chuàng)建,可以點(diǎn)擊 這里
第二步:關(guān)閉 RealDemo 工程舞肆,然后在 RealDemo 目錄下創(chuàng)建 Framework 工程焦辅,命名為 RealSDK
選擇下方的 Framework 進(jìn)行創(chuàng)建
切記目錄不要選擇錯誤
第三步:設(shè)置 Framework 工程的 Build Settings
創(chuàng)建動態(tài)庫需要選擇 Dynamic Library,如果要制作靜態(tài)庫則要選擇 Static Library
第四步:關(guān)閉RealSDK工程椿胯,創(chuàng)建 WorkSpace筷登,命名為 RealDemo
逐次點(diǎn)擊 File - New - Workspace
創(chuàng)建后會出現(xiàn)對應(yīng)的 workspace 文件
第五步:連接 Framework 工程和 App 工程
我們需要先打開 RealDemo.xcworkspace,打開后你會發(fā)現(xiàn)這里空空如也哩盲。
然后我們直接把需要連接的 Framework 工程(RealSDK.xcodeproj)和 App 工程(RealDemo.xcodeproj)拖進(jìn)來就可以了前方!
直接拖拽進(jìn) Xcode 即可
拖拽后你會發(fā)現(xiàn)兩者的層級關(guān)系相同
第六步:把 Framework 添加到 App 工程中
逐次點(diǎn)擊狈醉,不要點(diǎn)錯了
選擇前面創(chuàng)建的 framework
有過 SDK 開發(fā)經(jīng)驗(yàn)的同學(xué)到這里應(yīng)該已經(jīng)看明白了,所謂實(shí)時(shí)聯(lián)調(diào)說白了就是用 WorkSpace 把兩個(gè)工程連接起來而已惠险,跟 Pod 的原理有幾分相似苗傅。
第七步:給 Framework 加點(diǎn)功能
我們需要增加一個(gè) RealDog 類,定義一個(gè) eat 方法班巩,實(shí)現(xiàn)里面打印一句話“吃骨頭”。然后修改 RealDog.h 的 Target Membership 為 Public,意思為公開頭文件追逮。
在這里我定義了 eat 方法
RealDog的實(shí)現(xiàn)如下:
@implementation RealDog
+ (void)eat {
NSLog(@"吃骨頭");
}
@end
第八步:在 App 的 ViewController 調(diào)用一下 SDK 的方法
#import "ViewController.h"
#import <RealSDK/RealDog.h>
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[RealDog eat];
}
@end
第九步:運(yùn)行一下泣栈,可以發(fā)現(xiàn)App工程成功調(diào)用了SDK的方法
OK,實(shí)時(shí)聯(lián)調(diào)到此結(jié)束
5. 使用腳本合并真機(jī)抑进、模擬器等多種架構(gòu)的 Framework
第一步:添加一個(gè) Aggregate Target
RealSDK Project -> TARGETS -> "+"(左下角) -> Cross-platform - Other -> Aggregate
第二步:將 Aggregate Target 命名為“RealSDK-Script”
命名后點(diǎn)擊 Finish 即可
第三步:依賴 RealSDK
在 Dependencies 中配置依賴關(guān)系
第四步:添加腳本
點(diǎn)擊這里的 New Run Script Phase
復(fù)制下方腳本即可
這個(gè)腳本是通用的强经,各位同學(xué)直接復(fù)制粘貼即可:
# Type a script or drag a script file from your workspace to insert its path.
UNIVERSAL_OUTPUTFOLDER=../Framework/
# 創(chuàng)建輸出目錄,并刪除之前的framework文件
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
rm -rf "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework"
# 分別編譯模擬器和真機(jī)的Framework
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
# 定義真機(jī)单匣、模擬器Build文件夾路徑變量
IPHONE_BUILD=${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework
SIMULATOR_BUILD=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework
# 拷貝framework到univer目錄
cp -R "${IPHONE_BUILD}" "${UNIVERSAL_OUTPUTFOLDER}/"
#cp -R "${SIMULATOR_BUILD}" "${UNIVERSAL_OUTPUTFOLDER}/"
# 定義輸出路徑變量
OUTPUT_PATH=${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework
# 合并framework夕凝,輸出最終的framework到build目錄
lipo -create "${IPHONE_BUILD}/${PROJECT_NAME}" "${SIMULATOR_BUILD}/${PROJECT_NAME}" -output "${OUTPUT_PATH}/${PROJECT_NAME}"
第五步:運(yùn)行腳本
依然是點(diǎn)擊左側(cè)的播放按鈕
第六步:查看結(jié)果
能看到這個(gè)文件夾就代表編譯成功啦!
如果你的 Mac 是最新的 M1芯片户秤,那么可能會出現(xiàn)以下報(bào)錯:
fatal error: lipo: /Users/hujianhui/Library/Developer/Xcode/DerivedData/RealDemo-ckvcidkkuvgpadeiqrvgjdyikcdc/Build/Products/Debug-iphoneos/RealSDK.framework/RealSDK and /Users/hujianhui/Library/Developer/Xcode/DerivedData/RealDemo-ckvcidkkuvgpadeiqrvgjdyikcdc/Build/Products/Debug-iphonesimulator/RealSDK.framework/RealSDK have the same architectures (arm64) and can't be in the same fat output file
你只需要去除 iOS 模擬器的 arm64 架構(gòu)即可码秉,方法如下:
點(diǎn)擊 arm64 前面的減號即可
6. 小貼士
- Framework 中使用 Category
在 Framework 工程的 Build Setting 中添加 -ObjC。另外鸡号,使用我們 SDK 的 App 的 Build Setting 中也要添加 -ObjC转砖。
- Framework 支持 bitcode
四、在 Android 環(huán)境中開發(fā) SDK
1. Android SDK 介紹
Android App 集成第三方 SDK 的文件類型鲸伴,主要有三種府蔗,一種是 JAR 包文件,和 SO 文件 汞窗,另外一種是 AAR 文件姓赤, JAR 包是 Java 提供的 SDK 文件類型,里面包含的是純 Java 編譯過后的代碼仲吏。SO 一般是 C 和 C++ 打包成庫的文件不铆。
AAR 名字來源于 Android Archive,見名知義裹唆,是一個(gè) Android 庫項(xiàng)目的二進(jìn)制歸檔文件誓斥,使用 Android Studio ,非常簡單可以生成一個(gè) AAR 文件许帐。AAR 庫文件里面劳坑,包含了 JAR 和 SO,還有資源 Res 等文件成畦,結(jié)構(gòu)等同一個(gè) App距芬。
它可以提供構(gòu)建應(yīng)用所需的一切內(nèi)容涝开,包括源代碼、資源文件和 Android 清單蔑穴。不過忠寻,Android 庫將編譯為您可以用作 Android 應(yīng)用模塊依賴項(xiàng)的 Android ARchive (AAR) 文件,而不是編譯為在設(shè)備上運(yùn)行的 APK存和。
與 JAR 文件不同奕剃,AAR 文件會為 Android 應(yīng)用提供以下功能:
- AAR 文件可以包含多項(xiàng) Android 資源和一個(gè)清單文件,讓您除了能夠在 Java 類和方法中進(jìn)行捆綁以外捐腿,還能夠在布局和可繪制對象等共享資源中進(jìn)行捆綁纵朋;
- AAR 文件可以包含 C/C++ 庫,供應(yīng)用模塊的 C/C++ 代碼使用茄袖。
2. 創(chuàng)建 SDK 工程
打開上個(gè)章節(jié)我們創(chuàng)建的示例工程操软,在工程上創(chuàng)建一個(gè) library module,命名為GPush宪祥,讓我們模擬實(shí)現(xiàn)一個(gè)推送簡短新聞的接口聂薪。
如果你忘記怎么做的話,可以點(diǎn) 這里
選擇 Android Library蝗羊,并在名稱中輸入 GPush
添加成功后我們會在左側(cè)看到對應(yīng)的 Libray 文件
3. 添加依賴項(xiàng)
如需在同一項(xiàng)目中的另一個(gè)應(yīng)用或庫模塊中使用新的 Android 庫代碼藏澳,就需要這樣添加一個(gè)項(xiàng)目級依賴項(xiàng):
- 依次轉(zhuǎn)到 File > Project Structure > Dependencies;
- 選擇要在其中使用庫的模塊耀找;
- 在 Declared Dependencies 標(biāo)簽頁中翔悠,點(diǎn)擊 +,然后在下拉菜單中選擇 Module Dependency野芒。
先點(diǎn)擊加號蓄愁,再選中對應(yīng)的 Module Dependency
將其加入依賴中
4. 接口設(shè)計(jì)
既然是做一個(gè)推送新聞的接口,那就必須要分為客戶端和推送端狞悲,即 Client#onReceiveMessage 和 GPush#pushMessage撮抓。
從下面給出 UML 圖可以看出,只需要一個(gè)方法就可以監(jiān)聽到新聞推送了摇锋,GPushImpl#start(Client client)丹拯。
可以看我畫的 UML 圖,幫助你更進(jìn)一步理解 GPush 類
package com.myname.library;
interface GPush {
void pushMessage(String msg);
}
GPushImpl 類
package com.myname.library;
import android.os.Handler;
import android.os.HandlerThread;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
public class GPushImpl implements GPush {
private List<Client> mClients;
private HandlerThread mHandlerThread;
private Handler mHandler;
private Random mRandom = new Random();
private List<String> msgs = new ArrayList<String>() {
{
add("1乱投、文旅部:嚴(yán)查以中老年為目標(biāo)的包價(jià)游產(chǎn)品");
add("2、加快推進(jìn)沿長江戶籍改革顷编,服務(wù)長江經(jīng)濟(jì)帶高質(zhì)量發(fā)展戚炫。");
add("3、今年首批10家非法社會組織網(wǎng)站被關(guān)停媳纬,含中國文藝名人協(xié)會等双肤。");
add("4施掏、上海:5月1日起,電動自行車騎乘人員必須戴頭盔茅糜。");
add("5七芭、廣州:清明祭掃實(shí)行實(shí)名預(yù)約,倡導(dǎo)網(wǎng)上祭掃蔑赘、錯峰延后祭掃狸驳。");
add("6、河北武安鐵礦致6死事故涉嫌瞞報(bào)缩赛,企業(yè)相關(guān)人員被控制耙箍。");
add("7、黃崢辭任拼多多董事長:將放棄超級表決權(quán)酥馍,投入科學(xué)研究辩昆。");
add("8、打破國外20年壟斷旨袒,國產(chǎn)人工心臟研發(fā)成功汁针,但商用落地時(shí)間暫不確定。");
add("9砚尽、調(diào)查:六成青年入睡時(shí)間晚于23點(diǎn)施无,夢多睡眠淺成年輕人睡眠主要問題。");
}
};
GPushImpl() {
mClients = new ArrayList<>();
mHandlerThread = new HandlerThread("Push-Thread");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
}
@Override
public void pushMessage(String msg) {
Iterator<Client> iterator = mClients.iterator();
while (iterator.hasNext()) {
iterator.next().onReceiveMessage(msg);
}
}
public static void start(Client client) {
GPushImpl gPush = new GPushImpl();
gPush.mClients.add(client);
gPush.mHandler.post(gPush.mRunnable);
}
private Runnable mRunnable = new Runnable() {
@Override
public void run() {
mHandler.postDelayed(mRunnable, mRandom.nextInt(10000));
pushMessage(msgs.get(mRandom.nextInt(msgs.size())));
}
};
}
Client 類
public interface Client {
void onReceiveMessage(String msg);
}
開始監(jiān)聽新聞推送
GPushImpl.start {
Toast.makeText(MainActivity@this,it,Toast.LENGTH_LONG).show()
}
SDK 打包
./gradlew :GPush:assembleRelease
打包完成后就行生成一個(gè) aar 文件尉辑, 這個(gè)文件就是我們打包的結(jié)果了
5. 最后注意事項(xiàng) — 混淆
基于代碼保護(hù)的目的帆精,Gradle 打包默認(rèn)會根據(jù) build.gradle 和 proguard-rules.pro 配置的混淆規(guī)則,來對代碼進(jìn)行一個(gè)混淆隧魄, 如果 library 里面使用了如 GSON 或者反射等技術(shù)則需要對部分類進(jìn)行 keep 操作卓练。
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
-keep class com.myname.library.** {*;}
如果正確按照教程,那相信你已經(jīng)成功的做出了屬于自己的第一個(gè) iOS 與 Android SDK购啄,本期教程依然基于 mac 電腦進(jìn)行實(shí)現(xiàn)襟企,如果你的電腦是 Windows 或者其他操作系統(tǒng),還需要進(jìn)行一些其他的靈活配置狮含。
文末
您的點(diǎn)贊收藏就是對我最大的鼓勵顽悼! 歡迎關(guān)注我,分享Android干貨几迄,交流Android技術(shù)蔚龙。 對文章有何見解,或者有何技術(shù)問題映胁,歡迎在評論區(qū)一起留言討論木羹!最后給大家分享一些Android相關(guān)的視頻教程,感興趣的朋友可以去看看。
【2021 最新版】Android studio全套教程+Android(安卓)開發(fā)入門到精通(項(xiàng)目實(shí)戰(zhàn)篇)_嗶哩嗶哩_bilibili
Android開發(fā)進(jìn)階學(xué)習(xí)—設(shè)計(jì)思想解讀開源框架 · 已更新至104集(持續(xù)更新中~)_嗶哩嗶哩_bilibili
【實(shí)戰(zhàn)教學(xué)】Android開發(fā)—jetpack入門到精通_嗶哩嗶哩_bilibili
Android音視頻開發(fā):音視頻基礎(chǔ)知識到直播推流實(shí)戰(zhàn)系列教程_嗶哩嗶哩_bilibili
Android項(xiàng)目實(shí)戰(zhàn)-從0開始手把手實(shí)現(xiàn)組件化路由SDK項(xiàng)目實(shí)戰(zhàn)_嗶哩嗶哩_bilibili