SDK全稱 Software Development Kit,廣義上的 SDK 是為特定的軟件包、軟件框架、硬件平台、操作系統等建立應用程序時所使用的開發工具的集合,狹義上的 SDK 則是基於系統 SDK 進行開發包裝的、新的、獨立的、能夠完成特定功能並返回相關數據的一組工具的集合。
插件(Plug-in,又稱addin、add-in、addon或add-on,又譯外掛)是一種遵循一定規范的應用程序接口編寫出來的程序。其只能運行在程序規定的系統平台下(可能同時支持多個平台),而不能脫離指定的平台單獨運行。因為插件需要調用原純凈系統提供的函數庫或者數據。很多軟件都有插件,插件有無數種。
sdk可以看做插件的集合;
推薦一個BLE藍牙研究的庫,正在做該方面的或者有興趣的可以看下。
Android BLE藍牙框架,包括掃描、連接、設置通知、發送數據、讀取和接收數據以及各種直觀的回調,近乎一行代碼植入項目,可擴展配置藍牙相關操作。
https://github.com/Alex-Jerry/BleDemo
http://www.jianshu.com/p/d70e22ce61bc
本文作者
作者:brucevanfdm
鏈接:
http://www.jianshu.com/p/8f39919cd4e5
本文由作者授權發布。
1
前言
最近由於工作需要,將應用里的部分功能獨立了出來,封裝成 SDK 提供給合作伙伴使用。由於經驗不足,網上也沒多少寫這方面內容的文章,遇到了不少的坑,決定記錄下來。
其實,剛說到要寫SDK也有點慌,印象中SDK一直是個復雜的東西,腦海中浮現的是Java SDK ,Android SDK這類龐然大物。
SDK全稱 Software Development Kit,廣義上的 SDK 是為特定的軟件包、軟件框架、硬件平台、操作系統等建立應用程序時所使用的開發工具的集合,狹義上的 SDK 則是基於系統 SDK 進行開發包裝的、新的、獨立的、能夠完成特定功能並返回相關數據的一組工具的集合。
聽起來一愣一愣的,其實,將一些業務邏輯獨立出來,打包成jar、so、aar,暴露一些APIs給外部調用,也可以稱為SDK。如推送SDK,支付SDK,地圖SDK...既然是所謂的集合,那么自然有大有小。
下面說說我在封裝SDK與使用的時候遇到的那些事,希望對大家有些幫助吧!
2
二次打包aar
大多時候,我們的業務依賴於第三方庫,載體可能為jar、so、aar,如果是jar包那好辦,直接丟進libs目錄下就可以了;so庫就不簡單了,不少開發商只提供少數abi的so庫,這時就需要根據需求選擇了,要么全部一份,要么只保留一個目錄,否則就會報錯;aar則是包含了代碼、資源(圖片、布局等)、so庫等的集合。
那么需求來了,如何將第三方aar包二次封裝,加入自己的業務邏輯再打包成一個aar呢?其實這個問題我也沒有找到直接的解決方案,如果你有,請聯系我,感激不盡!但是這個問題又是可以曲線解決的,aar其實就是個壓縮包而已,如下圖所示:
Android Studio導入aar時也是將其視為一個module(library),使用其中的classes以及其他資源文件,那我們可不可以直接將其解壓,直接導入?
這樣就避免了在aar的基礎上封裝成aar!跳過這個坑?實踐證明確實是可以的。如果你要封裝的aar只包含了jar包和so庫,那就簡單了,解壓出來分別導入項目相關目錄即可!不然可能就要手動合並某些資源了...更新:詳情請看 二次打包(封裝)AAR實用指南
http://www.jianshu.com/p/3bad128bd106
還是期待谷歌能給出一個傻瓜式的一鍵合並方案吧!
3
SDK中Application對象的初始化
有次SDK接入方反饋說某個地方崩潰了,一看Log,是調用Application對象中的方法空指針了。我一想,混淆?不是。導入姿勢不對?不是。文檔沒認真看?也不是?Demo可以正常運行啊......隨即想到是接入方自定義Application對象的問題。
如果aar中定義了Application,theme,icon,那么編譯時就要拋出如下異常:
-編譯錯誤AndroidManifest合並異常-
由於項目與aar都定義了自己的Application,編譯器不知道用誰的,這就產生了上圖的異常,按照提示,在Application標簽下添加如下代碼:
tools:replace="android:name"
合並方案可以參考官方文檔:合並多個清單文件| Android Studio - Android Developers
https://developer.android.com/studio/build/manifest-merge.html?hl=zh-cn
理雖如此,但是你很大概率就掉坑了,這個方案直接將SDK中的Application對象替換為你的,換句話說就是SDK中的Application對象根本沒有初始化,這就是上文說的空指針的罪魁禍首了!
確實之前在寫文檔的時候沒有考慮到自定義Application的情況,還是經驗不足啊!甚至一度將Application里初始化的方法全部移出來,后來轉念一想,讓接入方繼承我的Application不就OK了嗎!!測試一波,趕緊更新下文檔,不然又被吐槽了...這下理解為什么接入某些第三方SDK時,有的會要求繼承SDK里定義的Application對象。
4
Application多繼承
作為一個SDK提供方,假如你的SDK需要用戶繼承你的Application,我覺得應當提供一個Application多繼承的解決方案,畢竟用戶可能不僅僅只用你一個SDK,當有多個SDK有這個需求時就尷尬了。
java 多繼承,這里的需求是繼承兩個類,並不是通過實現接口的方式“繼承”多個接口上的方法聲明。語言原生不支持,這樣就比較麻煩了。
解決辦法如下:
通過接口實現 + 反射 的方式來創建代理Application對象,曲線實現Application的多繼承,由於代碼較多,這里就不貼源碼了,解決方案:ApplicationProxyDemo 源碼配合注釋食用,風味更佳!
https://github.com/brucevanfdm/ApplicationProxyDemo
5
導入aar的兩種方法
解決一:采用Android Studio新建module的方法,選擇jar/aar即可。
導入.AAR
解決二:使用gradle腳本直接導入:
1. 在項目build.gradle文件內android{}標簽中加入如下代碼申明本地倉庫:
repositories{
flatDir{
dirs'libs'
}
}
}
2. 然后將aar包放入libs目錄(沒有就在app目錄下創建一個),隨后加入dependencies :
dependencies{
compilefileTree(dir: 'libs', include: [ '*.jar'])
...
compile(name: 'xxxxxx-xxxx', ext: 'aar') //name為aar文件全名
}
6
SDK中不可忽視的混淆問題
1. 常規的避免混淆,比如一些第三方類庫中的要求
2. 避免混淆對外提供方法與數據實體的類,並且添加到接入方的proguard-rules.pro中。
最后
其實在最近的SDK開發與對接中遇到了不少問題,但是也學到了不少東西,由於缺少相關經驗,也在不斷的摸索之中。正所謂實戰出真知,紙上談兵容易,真刀真槍時就會暴露出一些問題,還是要多動手。當然了,技術都是業務驅動的。
開發SDK注意事項
1. 修改類別文件名及類別方法。
開發SDK時通常會用到比較多的第三方的類別方法, 這樣的話, 開發者在使用你的SDK時, 因為他可能也會加一些第三方的開源庫, 比如都使用了NSString的md5類別文件。 由於這兩個文件都是從網上下載來下的, 所以文件名是一樣的。 這樣在編譯時就會報錯。 然后就想到要去修改這個類別文件名, 等修改類別文件名后。 發現類別中的方法名是一樣的, 而ios在調用兩個相同方法的類別方法時, 不能確定其調用的哪個方法, 但可以肯定地是只會調用一個類別方法, 如果恰好開發者自己又修改了這個類別方法, 那就有問題了。
所以在SDK開發過程中, 需要修改引入進來的類名, 及方法名, 建議添加項目前綴, 最好是三個字母的, 如NAB, (兩個字母為蘋果自己保留使用)
2. 在開發SDK時, 如果發現某個方法命名時比較困難, 那么幾乎可以肯定的是, 這個方法藕合度太高,需要再次進行分解。
3. 開發SDK時, 需要考慮到升級的問題, 並且可以指定某些版本必須強制升級。 (以防某些版本到后期發現有明顯問題, 需要及時替換)
4. 開發SDK時, 需要留出一個接口, 能通過后台服務器強制關閉掉某個接入應用的調用。 (這可能會發生在惡意地攻擊行為, 以及非惡意地使用行為,如某應用頻繁自動重啟事故,每次重啟都會調用咱們的SDK,然后就會使得咱們的SDK服務器壓力陡增), 這個時候, 如果后台能根據這個應用的APP ID啥的, 強制關閉它發的請求,或者屏掉他的請求, 你會發現世界如此美好。
5. 統計方面, SDK存儲每個接口調用的次數,以在一定的情況下發送給服務器, 便於后期分析某些接口是否有問題,或者是根本就沒有用戶使用的情況。
6. 有些SDK使用的前提條件,最好是在編譯期就提示給用戶,而不是在運行期, 可以使用類似下面代碼來進行提示
#warning - Release scheme, this is not work.
#if !__has_feature(objc_arc)
#error iBeaconSDK requires automatic reference counting
#endif