1. 程式人生 > >開發一流的 Android SDK: Fabric SDK 的建立經驗

開發一流的 Android SDK: Fabric SDK 的建立經驗

APIs & Fabric (0:00)

作為開發者,我們中的大多數人不得不使用 SDK 和 API,但經常地,我們會遇到一些令人沮喪的或設計不好的東西。要使得開發偉大的應用程式更加輕鬆,作為核心的軟體開發工具包還有很長的路要走。在 Fabric 上,我們很關心開發者的經驗,我們花了大量的時間,使我們的 SDK 更容易和更有趣。我的名字是 Ty,在 Twitter 的 Android Fabric 工程師團隊。我想與你們分享一些我們在開發 SDK 過程中學到的經驗。

那麼 Fabric 究竟是什麼呢?它是一套 Twitter 開發的模組化開發工具包,Twitter 共享了一個共同的移動和Web平臺,用於減少佔用空間和提供一致性的解決問題方案,旨在提升第三方移動 App 的質量。我們去年釋出了 Fabric,這是完全免費的。我們相信這是一個偉大的方式來引導你的移動應用程式。就在上個月,我們宣佈了多個外部合作伙伴,現在正在基於Fabric 進行開發,未來將有更多高質量的內容提供給大家。

我們建立 Fabric SDK,我們保持了幾個目標,幫助引導我們進行開發。這些原則決定了我們開發 API 和做決策的選擇。這些想法可以融入你自己的SDK或甚至你的應用。我們很高興能夠看到大家離開這裡後,在未來開發的你們的 SDK 中採納和我們一致的想法。

在我們進入 library 或 SDK 編碼之前,我們有必要考慮幾個方面。

首先要考慮的是要找出你在 library 裡的實際服務的物件是誰,是內部開發人員還是公共開發人員?誰會使用它?它帶來的新價值是什麼?市場上已經有了一個解決辦法嗎?如果是這樣的話,你應該是去對其進行開發和貢獻而不是重新創造一個“輪子”。

考慮開源與閉源是一個大問題。開源通常會讓你更好地通過社群,獲得更穩定的軟體,以及更熱心的內部工程師。然而,需要思考的事,你的 SDK 僅僅是集中於一個工程點呢?還是說它是一個完整的產品,但有一個後臺服務呢?

因此,仔細考慮你將採用哪一種許可證(開源協議)。例如,如果你使用 GPL 許可,那麼將會使得用了你的 SDK 或 library 的人也必須得使用 GPL 開源協議。更靈活的許可證可能是 Apache 2 或 MIT 許可。

特別是對於 Android,打包你的程式碼並不一定是簡單的。你有三個問題需要考慮。首先是對於一個標準的庫專案,開發者將他們包含到他們的程式碼中,並且由 IDE 幫忙連線它們,它是非常靈活的,但是如果他們需要分叉(fork),他們得如何保持更新?

在 Java 的世界 jar 包是另一個好例子——很標準的二進位制包裝。不幸的是,對於 Android,它們不能捆綁打包自己的資原始檔,所以對於一些和檢視相關的 library 一般都不能採用 jar 方式打包。

最後,在 Android 世界還有一種打包方式即 aar,它是谷歌現在支援二進位制打包方式。這是一個壓縮的容器,包含了編譯的原始碼以及資原始檔,它可以通過 Gradle Maven 依賴源從而非常方便快捷地分發給開發者。

Hosting the artifacts (3:10)

最後的考慮是在哪裡託管你的打包結果。Maven Central,是標準的倉庫。然而,他們都需要開源許可,因為他們想保護他們的服務的使用者,他們不希望有人會隱式地拉下來一個二進位制包,並選擇一個他們沒有得到審查的服務條款。如果使用了另外的資源庫(如果你有一個專有的二進位制檔案),則開發人員必須手動添庫到編譯指令碼中。

在創造 Fabric SDK 的工作是一個夢幻般的學習過程。我們的目標就是涵蓋這五大方面:易用、穩定、輕巧、靈活,很好的支援。我們相信偉大的 SDK 要實現這些得走很長的路。

其中的一個關鍵就是可用性。我們認為產品應該是易於使用的。

那麼所謂的易用到底是什麼呢?我們想創造一種最簡單的方式,讓人們在他們的應用中開始使用 Fabric. 如果它是易用的,它應該是不需要侵入太多你的程式碼或者你需要做很多繁瑣的整合工作。只要在你的程式碼中新增一行我們的程式碼,就可以使用它了,類似這樣:

Fabric.with(this, new Crashlytics());

但易用的同時,有時還得能夠定製,許多開發者可能希望更多的定製。要做到這一點,我們使用的 Builder 生成器模式設定一些選項,比如設定一個監聽器好讓程式在應用程式崩潰之前通知你。

Crashlytics crashlytics = new Crashlytics.Builder()
      .delay(1)
      .listener(createCrashlyticsListener())
      .pinningInfo(createPinningInfoProvider())
      .build();

Fabric.with(this, crashlytics);

對於 Fabric SDK,我們需要一個 API key 作為連線我們網路伺服器的驗證金鑰。這是我們要開發人員處理的事情,但需要儘量減少所需的工作量或者說繁瑣度。我們的標準方法是:通過我們的構建外掛提供的方式,並將其注入到清單(manifest)檔案中。這裡是一個例子,使用 metadata  在清單檔案中插入資料:

<manifest package="con.example.SDK">
  <application>
    <meta-data android:value="01235813213455"
      android:name="com.fabric.ApiKey" />
  </application>
</manifest>

當 Fabric 在初始化的時候,我們可以通過 package manager 獲取到我們插入在清單檔案中的 API key 並且繼續後續工作。另外,我們可以允許其他的方法來管理這個 API key 的值,對於開源專案這麼做可能會更好(保護 key 的值,因為有時我們對專案進行開源,但 key 不想開源)。例如,您可以建立一個屬性檔案,然後我們將在執行時讀取該目錄檔案內容。

除了我剛才提到的實施細節,我們喜歡在設計 API 時考慮這些特點:第一個是 直覺。如果一個介面呼叫的行為恰好是開發人員預期的方式,而無需參考文件。

我們發現,在你的 SDK API 中使用 一致 的命名,也是有助於使用者理解。使用平常的表達語言來命名你的方法,以及類似的設計模式。並且遵循各個平臺約定俗成的命名規則,比如 iOS 和 Android 平臺,它們各有不同的命名規則。

最後,如果 API 很難被誤用,將可以防止一些錯誤的發生。驗證輸入的引數,和書寫明確的文件,將使得開發者在使用的時候,能夠有信心和避免錯誤。也會帶來一個更愉快的體驗。

讓我們看一個反直覺的例子:

URL url1 = new URL("http://foo.example.com");
URL url2 = new URL("http://example.com");

url1.equals(url2)

這一個感覺,將影響很深,也是 API 中最難的部分。當使用一個偉大的 API 時,我們可以猜測它是如何表現的。在這個例子裡,我們將期望 equals 執行某種標準化的字串比較。

但是實際上反直覺的是,equals 代表如果這兩個 URL 解析到相同的IP地址,在 Java 中的實現,將返回 true,這裡的原因是這個 API 的實現十分有趣:它發射同步的 DNS 請求。誰會想到?阻塞呼叫執行緒是一個意外行為的例子,在 API 中應該是非常明確指出的。

舉一個例子,Fabric 和 Crashlytics 的初始化方式便都是一致的。在初始化 Fabric 或 Crashlytics,兩個不同的二進位制依賴庫檔案,正如我們之前看到的我們允許它們使用同一模式建造。使用者可以使用無引數建構函式,或定義輔助方法來設定預設值,另外,這兩者都提供了一個可用於重定義物件的生成器(builder)。

最後該講到如何防止誤用了。例如,從 Fabric Builder 的建構函式我們可以得知,Context 物件是必須的,而其它一些 setter 是可選的。一旦我們在構建的階段中建立例項,這些可選引數也就一併被初始化。

這樣設計的話,開發人員使用 API 將不能不提供 context,但可以使用其它 setters 在另外的閒暇時間。我們相信這樣就很難被誤用了。

我們如何才能設計出高品質的 API 呢?讓我們來看看我們的設計流程。設計 API 是很難的,它通常不只是一個工程師獨自坐在一個黑暗的房間,決定該是什麼樣子,它需要整個團隊付出大量的工作。

我們在 Fabric 的 API 設計上第一個重點就著眼於我們將支援的幾個平臺。我們建立一個設計文件之前,任何實施工作都是這樣做的,進行討論在這些平臺上,不同的方法的優點和缺點。

有一句話我很喜歡:一個 API 就像一個嬰兒。他們很有趣,但他們需要18年的支援。任何 API 我們都必須要長期地支援,所以我們要讓大家感覺到,我們正走在正確的路上,才能才久堅持支援下去。

最後,即使我們可以讓 iOS 或者 Android 開發中愉快地使用我們的 API 了,我們還需要建立相關的平臺,首要的就是讓開發者們感到最舒服的。

現在我們已經設計了一些很容易使用的東西,讓我們來討論一下我們如何能獲得開發者的信任,相信這是非常重要的。因此,確保軟體開發工具包是可靠的,他們不影響應用程式本身的穩定性。大家都知道,相比開發應用程式,開發一個 SDK 需要更高的穩定性要求。讓我們來看看如果產生了一個錯誤將會有什麼影響。

如果一個應用程式有一個關鍵的錯誤,阻礙了它的使用者使用,它可能僅僅需要傳送一個新版應用程式給顧客進行更新即可。而如果是我們 SDK 發現了一個漏洞,我們很快修復它,它可能還需要一個月才能到達你的使用者,在此期間,你的使用者就會有很不好的體驗了。

顯然,如果一個 SDK 有一個嚴重的 bug,它的修復更新到達時間要長得多。這可能需要幾個月,用你的SDK應用程式的使用者才能得到錯誤修正。應用程式開發人員可能需要數週才能注意或升級您的 SDK 版本,並進行修復、測試 bug。所以說確保一個 SDK 的穩定性是我們的最高優先事項之一。

作為開發人員我們可以做什麼,以確保儘可能高的穩定性?有一些事情是我們開發過程中的關鍵。首先,程式碼審查是非常重要的,必須得認真對待它們。然後,通過不斷地問自己“這個程式碼有什麼問題嗎?”我們可以這樣試著去問自己,以達到儘可能的防守。

如果能夠自動獲得一些基本的正確性保證,也可以在早期幫助捕捉錯誤,所以單元測試是非常有用的。

另一方面,人們經常忽略的是:在使用者使用初次使用進行測試時候,使它能夠執行你的一些 SDK 程式碼,這樣做他們可以在你的 SDK 整合時進行捕捉 bug。

最後,持續整合(譯者注:維基百科詞條 - 持續整合 )和”吃你自家的狗糧”(譯者注:維基百科詞條 - Eating your own dog food )也都可以作為你的保護層,可能有助於早期快速識別問題。

使 SDK 具備可測試性和可模擬性 (10:16)

有一些技巧可以讓你的 SDK 具備更好的可測試性。其中,為了測試,有時我們需要進行模擬,模擬(mock)類作為真實類的仿製類,它沒有真實操作,並且允許被重寫呼叫和驗證方式。

通過避免靜態方法,您可以允許在模擬例項上進行操作任何方法的呼叫。如果您將使用靜態方法,需要確保它可以被隔離,並且您將提供所有的依賴關係,並且沒有基於任何狀態。

許多 mocking libraries 對於 final 的類也會產生許多問題,所以要考慮你的類擴充套件。在你的模擬類中不應該存在 public 屬性,所以需要被訪問的一切都應該通過一個訪問的方法來執行。

在你的 API 中使用介面。如果您的輸入點使用介面,設定類來測試將更容易。該介面允許開發人員進行重寫的行為,比如契合模擬伺服器或在記憶體中儲存,來替代真實場景真實儲存的開銷。

最後,需要考慮到測試人員不需要構造多個層次深度的模擬。這個鼓勵測試的原則應該被寫入你的指引文件,並提供更穩定的測試框架。

有一些 class 很難被模擬,比如 final 型別的,它將建立它自己的依賴關係,並且是一個基於狀態的單例。這在 Java 中是很常見的,雖然它通常是一個反模式。這使得它在隔離測試中非常具有挑戰性。那麼,我們能做什麼來解決它?其實只要有一些小修改,我們可以使這些難解的點變得更容易測試一些。

public class Tweeter {
  private Network network;

  private public Tweeter(Network network) {
    this.network = network;
  }
  public List<Tweet> getTweets() {
    return getNetwork.getTweets();
  }
}

與其把它作為一個單例,為什麼不把它做為一個例項?開發者可以自己去重用它,快取,或者做其它的事情。刪除在 class 中的 final Mockito 或其他框架就可以模擬它了,同時也能讓 SDK 在初始化、構造時候管理它的依賴。依賴注入不僅僅是一個框架,它還是一個幫助組織程式碼的設計模式,使得程式碼更具有模組性和可測試性。

開發者經常是容易不耐煩的,所以有一些錯誤越儘早丟擲就越好。如果你一直在使用 Gradle 你應該會明白我的意思,一些錯誤如果在 build 期間不能通過總是好於 build 完成之後5分鐘才出現錯誤。你應該 把一些可以預期的異常丟擲,以便於開發者能夠儘快知道這些異常,比如在這種情況下,開發者試圖設定一個 null 的 logger 到我們的 builder 裡,我們得馬上丟擲一個異常,這樣他們就可以很快知道並解決他們的錯誤。

然而,你得保證你的 SDK 在生產環境中絕不會出錯,讓你的程式碼持續執行在他們的應用中,是你保證開發者們信心的唯一方法。他們的應用程式往往是他們生計的依賴,所以他們不會喜歡去賭著使用一個經常崩潰的庫。所以當他們在除錯過程中出現問題的時候,你可以提供額外的資訊,寫清楚這個 Exception,但要隱藏在生產過程中可能出現的問題,這樣允許他們的應用程式的其餘部分繼續執行。你的 SDK 的出現問題可能對你來說是一個大問題,但並不是世界末日。

作為一個開發者,你使用 SDK,你的應用程式應該增加價值,而最糟糕的事情就是你引進了某物反而使得原本多價值降低了甚至完全破壞使用者體驗。開發者們,包括我自己,不需要任何人來幫助我們寫一個糟糕的 App。


除了穩定,使用者不太可能下載大的應用程式,這意味著安裝包的大小是一個關鍵內容。下載軟體產生的流量需要使用者去付錢,所以即使你的應用是完全免費的,使用者也得為下載它付出流量。在許多新興市場,因為下載速度太慢,所以很多使用者不愛下載大型應用程式;在某些市場,使用者主動選擇更新的應用僅僅基於更新日誌和新增新的特性是否值得,因為他們需要支付每千位元組流量費用。

讓我們來討論一些 Fabric 用於保持輕量的技術吧。有一些偉大的第三方庫,可以真正給予貢獻於你的應用程式,但當涉及到 size 規模和影響時,他們會他們顯得不自由。例如,影象載入方面有各種不同體積大小的圖片載入庫。其中 Fresco,是比其他任何一個第三方庫都還大量級的一個庫。然而,它對於舊裝置有更好的支援,載入速度快而且記憶體友好,並支援漸進式JPEG。

作為一個 SDK 你應該努力平衡你的尺寸與功能。因此,要注意引入第三方庫,以確保它們只滿足所需的內容。

使用開源庫有很大的優勢,因為這些庫往往經過很多的測試了,大家都使用得很好,並且他們有定期向他們提供更新的社群。這通常提供了一個更好的方案。在我們的 Twitter SDK,我們利用 Square 的 RetroFit 這個庫作為一個依賴來簡化我們的 API,而且也能使我們提供更好的可擴充套件性,這是值得的。

報告二進位制檔案(binary)的大小 (15:22)

task reportSdkFootprint << {
  def sdkProject = project(':clients:SdkProject')
  def nonSdkProject = project(':clients:NonSdkProject')
  def footprint = getSizeDifferent(
    new File("$sdkProject.buildDir}.../Sdk.apk"),
    new File("${nonSdkProject.buildDir}.../onSdk.apk"))
  println footprint
}

這裡有一個很好的減少你的庫大小的方法,就是如果你每天都稱量自己的體重,你就能夠減肥。我們採取這種方法來關注和減小我們的 SDK 大小。我們積極地監控每個 build,使我們能夠衡量的真實影響開發者的 APK 大小情況。沒有硬性和快速的規則來解決大小增加,但一直關注它顯然是有幫助的。

Dalvik 方法數量限制 (15:52)

很多人應該都會遇到過 Dalvik 65K 的限制吧?不過你們可能不熟悉這個錯誤的具體原因,對於方法的呼叫,可以通過在 Android 一個 DEX 檔案,而它的引用的數量有限。問題的關鍵是,DEX 的工具,在編譯時,試圖把所有的方法引用到一定的空間中,但引用數目大於空間所能容納的數目,導致分配失敗。

現在你可以使用 multidex 來解決這個問題,但這增加了在較舊的裝置上應用程式的載入時間,它的初始化時間顯著增加,它並不適合一些較新的裝置使用者以外的人。它甚至某些流行的三星裝置上會導致出錯,並導致應用程式崩潰。這些特定的裝置有數以百萬計的裝置,在歐洲和亞洲都是很流行的,所以說這個解決方案真是迫不得已,能不觸及儘量不要觸及。

但如果開發者遇到這個問題,在他們去使用 multidex 或類似的東西之前,他們經常決定稽核他們的第三方庫,選擇是否可以減少應用程式方法數量的庫。所以我們的目標和建議是儘可能地使你的庫模組化和精益。

我們用一個偉大的庫被稱為 dex-method-counts 在 Gradle 中,它包裝了一些Android 構建工具對每個第三方庫的方法數量並給出了詳細的資料分析。這讓我們快速洞察到我們的庫大小和我們的依賴的大小。

我們想要模組化開發人員需要的特定功能。我們這樣做是通過指定一個樹的傳遞依賴關係。所以,我們有兩個例子展示如何初始化 Fabric:

容易整合的:

Fabric.with(this, new Twitter());

更多控制的:

Fabric.with(this, new TweetUi(), new TweetComposer());

第一個例子讓你馬上開始,其次是一個擁有更多定製的版本,在這裡你可以選擇需要的特定元件,然後它們才生效。

讓我們的 SDK 儘可能小,我們著眼於模組化來設計我們的架構。就像我們討論過的,在 Android 上二進位制檔案的大小和方法計數是非常重要的,所以這使我們能夠儘可能高效。因為如果我們利用 AAR(標準的通過 Maven 提供標準的庫),我們可以使用分解依賴來滿足我們的需求。

在架構 Twitter SDK 堆疊,所有的一切都建立在 Fabric 上,它提供共享的 common 程式碼給所有我們的 SDKs. 我們建立了 TwitterCore 層,它提供了登入和 API 客戶端和其他一些核心功能。

然後,我們才有基於特徵的 SDKs,像我們的 Tweets,我們的 composer,我們的簡訊登入基礎設施;這些特點都可能是你使用我們 SDK 的理由。最後,我們提供了一個介面,通過傳遞依賴關係將其包裝起來。這允許應用程式開發人員根據他們需要的層次結構選擇元件。

除了注意 SDK 本身的大小之外,我們建議你在“壓線”之前進行壓縮。我們可以明顯看到,不同格式之間有壓縮大小差異,如 XML 和 JSON,一起使用jzip壓縮格式,或二進位制格式 Protobuf。有些人可能不熟悉 Protobuf,它是一個二進位制的壓縮格式,在伺服器和客戶端介面使用一致的預期協議,使得不需要將所有欄位都進行傳輸。它可以非常高效地進行序列化和反序列化。

有效地發射是避免消耗過多電源功率的關鍵。Android 有三種典型的能量狀態:全功率、低功耗、空閒狀態或稱待機狀態。

在高功耗的時候進行統一的網路傳輸,比在空閒的時候斷斷續續進行多次傳輸來得節約時間和節約電源。

對於在典型的3G裝置上每一個數據連線,網路接收模組會產生約20秒的活躍時間。這意味著如果你每分鐘有三個網路連線,我們將會保持這個網路接收模組不斷地處於啟用。通過批處理這三個連線,我們可以在這裡減少20秒的啟用速率,以及至少40秒的待機或空閒時間。

不過對於這個方面,有一個例子,說的是天真統計分析 SDK,它們有時會不停地 ping 你的伺服器,大約20秒一次,僅僅是為了告知伺服器你的應用當前處於前臺。這麼做的後果就是會造成網路接收模組一直處於啟用狀態,並且把電源耗盡又沒有傳輸什麼實質上的資料內容。

保持 Fabric 的輕量部分方式是,我們應該清楚地知道何時在主執行緒做的工作何時在後臺執行緒工作,我們建議在你的應用程式啟動時候初始 Fabric,因此它的初始化將在主執行緒,我們從我們周圍很多顧客那裡聽到大家都是比較關注啟動時間的。

為了緩解這一點,我們做了非常有限的一些同步工作,然後立馬返回到開發者的 application,同時在後臺繼續做一些畢竟耗時的執行工作,以保持您的應用程式下次能夠快速啟動。

有些事情需要用同步做的一個例子:如果你使用在使用我們的 Crashlytics ,你得立即使用它的 crash handler,因為一旦崩潰異常發生在非同步初始化 crash handler 完成之前,就會捕捉不到這個異常。

一個 SDK 的開發者沒有像應用開發者那麼多的選擇權。你不能選擇你的裝置,API level,或客戶。你需要支援更大範圍的裝置,應用程式開發者並不侷限在選擇你的SDK,所以提供最大程度的靈活性是很重要的。

靈活性的一個體現是,可以讓開發者選擇不同的依賴管理器或者構件工具來引入或整合你的庫。

我們提供一些主要的開發工具外掛支援,包括 Gradle, Maven, 和 Ant. 我們還為通常的 IDE 提供 GUI 外掛,以及一個幫助開發 Mac 和 iOS app 的應用。儘管我們這是主要在講 Android 方面開發 SDK 的內容,但我還是忍不住想告訴大家一個好訊息就是我們最近完成了令人興奮的 CocoaPods 支援,這將非常方便於 iOS 開發者使用我們的 SDK.

儘量選擇相容最低的系統版本 (23:26)

靈活性的關鍵是瞭解您的 SDK 使用者的需求。然後做出需要支援的最低系統版本的決定。我們很希望我們的 SDK 能夠儘可能支援更多的系統裝置。對於這一點,降低支援最低作業系統版本是很有必要盡力去做的。

但另一方面,相容低版本也是要付出代價的。並沒有什麼直接的法則能夠告訴我們如何才能在繁瑣度和更好的相容性上確定平衡。支援舊的作業系統版本,通常意味著不利用更加好用的新介面,同時還要面對一些舊版本存在的問題。初次之後,你還要花費更多精力去測試你的程式碼之正確性。

一般來說,SDK 會比應用軟體在支援的最低系統版本的選擇上,更近保守。例如,Crashlytics 提供了 Android 2.2 的支援,因為這是一個還基本實用的 Android 應用程式。而不是像一些應用程式,它們僅支援某一作業系統的版本,它們關注使用者數量而去選擇最佳系統版本。

另一個重要的部分是能夠檢測出你正在執行的 Android 版本,所以你才能知道,哪些是可以呼叫的方法。通常,SDK 支援更老版本的 Android SDK。這對我們來說是非常重要的,因為我們想提供最大限度的裝置支援。

Android Manifests (24:57)

在 Android 系統上,執行時相容性是靈活性的重要組成部分。Android 開發者都知道,一個應用程式的元資料(metadata)在 manifest 檔案中宣告,一個 apk 一個 manifest 檔案。

此外,每一個你包含進來的 aar 都會帶一個 Manifest 檔案,只是在 build 的過程中,Android 工具會自動幫它們合併到一個 Manifest 裡面。這意味著,如果一個 AAR 的 Manifest 會影響最終 Manifest 的生成,比如新增一個許可權宣告,這對於開發者來說是很難注意到的。

許可權是任何 Android 應用程式的關鍵。在 Crashlytics 我們利用 wifi state permission 可以更好地管理上傳崩潰日誌。在 Android 的棉花糖系統上,這是屬於正常水平的許可權,這意味著它還需要在 manifest 檔案中宣告並同意。然而,我們沒有在我們的清單中宣告這個許可權,所以,如果使用了我們 SDK 的開發者想要上傳崩潰日誌,就必須得在他的清單檔案中宣告上這條許可權。如果開發者聲明瞭那條許可權,我們在下面的程式碼中就能夠知道擁有這個許可權了。

protected boolean canCheckNetworkState(Context context) {
  String permission = Manifest.permission.ACCESS_NETWORK_STATE;
  int result = context.checkCallingOrSelfPermission(permission);

  return (result == PackageManager.PERMISSION_GRANTED);
}

我們只需要檢查上下文物件中的許可權,以判斷是否已授予該許可權。如果沒有獲得該許可權也沒辦法了,我們不能為了許可權而可能影響到安全異常。一個 SDK 可以在執行時檢查是否被允許使用某許可權,如果可用再呼叫相應的 API.

很多時候我們都需要回退機制,但是在這種情況下,如果我們不知道WiFi或網際網路的狀態,我們必須假定它總是連線嘗試,讓超時發生。

有很多 Android 裝置的存在,同時有很多各式各樣的特性或者功能可能其它機器裝置並沒有,比如有的有 Kindle Fire 而有的沒有,有的裝置甚至還沒有攝像頭。

如果你正在構建一個基於相機的 SDK,你會在清單檔案中宣告使用相機。這就要求商店不要將應用程式展現給一個沒有攝像頭的裝置。我鼓勵你,把這個功能列為可選的,並允許你的庫在執行時檢測和修改它的行為。

在執行時檢測硬體功能非常簡單。您只需要查詢 package manager 該特定功能是否存在即可。這樣以後你的應用程式可以確定哪些功能可以使用了。以我們的相機庫示例,您可能還允許使用者瀏覽照片和上傳照片,只是他們不能夠在沒有相機的裝置上拍照就是了。

Classpath 檢測 (27:41)

有很多很好的第三方庫可以節約你的開發時間以及幫助你開發更好的 SDK. 當我們提供 SDK 給使用者,可能需要檢測使用者是否有引入這些可選的第三方庫,比如 RxJava 或者 Square 公司的OkHttp,如果有,我們就可以利用它們提供相應的支援。但你沒必要把這些包括到你的 SDK 當中,因為我們前面說了,保持輕量是最好的。

private boolean hasOkHttpOnClasspath() {
  try {
    Class.forName("com.squareup.okhttp.OkHttpClient");
    return true;
  } catch (ClassNotFoundException e) { }
  return false;
}

在這個例子中,你可以通過 class path 來檢測 OkHttp 是否存在。你可以告訴使用者可以引入這個第三方庫進行更好的支援,但沒有必要主動把它們包括到你的 SDK 當中。如果有,你可以利用,如果沒有,你也可以有你的另外選擇。

除了執行時檢測,我們不能滿足每個開發者的需求。我們的 Twitter SDK 提供了易於使用和流行的一些特性讓使用者去發現。我們預先就會準備好,幫你簡化簽名操作,我們使用持續的 token,簽署了所有的輸出請求。

但是,如果你想使用一個我們 SDK 目前沒有提供的 Twitter API 功能怎麼辦呢?如果是這樣,你可以繼承 Twitter API client,並且提供你的 retroift 介面,我們可以接受它並幫你進行簽名。

正如我們所知道的,開發人員有很多工具,有很多的選擇,他們需要在他們的程式碼中保持靈活性。這是很現實的。我們提供可擴充套件的介面,使用 Fabric,使開發人員可以利用擴充套件他們想要的功能介面。

這裡還有一個例子是日誌記錄。有許多不同的庫來使用,我們提供了日誌介面,以便它可以在 Fabric 開始前提供實現,然後我們將尊重並使用開發人員的日誌記錄需求。

但如果開發者選擇不配置他個性的日誌內容,我們提供一個健全的預設日誌,便是標準的 Android Logger.

另外,對於 Java 之外的方面,我們也支援讓使用者自定義他們想要的介面風格,比如開發者可以修改 color 的值,這些值將被應用於 TwitterUI SDK.

這裡有一個需要注意的點,因為 dex 合併點時候不支援在 name 中使用空格符號,所以不要使用類似”background color”這樣的 name.

制定靈活程式碼的一部分,就是允許開發人員選擇監聽一些事件發生並獲得通知。在我們的 builder,我們可以設定同步或非同步任務結束的時候進行回撥,也可以設定如果出錯了可以得到回撥通知。它允許開發者根據自己的狀態和所獲取的資訊進行定製決策。

當你完成了你的 SDK 開發的時候,並不代表著你的 SDK 真正完成了,你還需要有很多開發之外的內容要做,要建立開發者交流的社群,還要有 Apple 文件、Java 文件,以及 README 文件,另外還有很重要的就是要有使用你的庫的示例教程。

添加註釋 給你的所有 public 的內容,以及順帶說明一些使用案例。

釋出簡明的 示例(sample)程式碼,讓使用的人可以遵循著你的程式碼進行初次嘗試。但切記不要把你的示例程式碼寫得太複雜或者在無關緊要的內容上糾結太多,不然會導致使用者花費更多時間去學習你的示例程式碼,並且使用到他們的專案中時候,產生了很多疑問或者 bug.

相關推薦

開發一流Android SDK Fabric SDK建立經驗

APIs & Fabric (0:00) 作為開發者,我們中的大多數人不得不使用 SDK 和 API,但經常地,我們會遇到一些令人沮喪的或設計不好的東西。要使得開發偉大的應用程式更加輕鬆,作為核心的軟體開發工具包還有很長的路要走。在 Fabric 上,我們很關心開發者的經驗,我們花了大量的時間

如何在安卓原生專案中加入mui相關檔案進行開發(使用新版本5+SDK建立最簡Android原生工程(Android studio))

緣起 最近在搭一個android開發的demo,專案使用androidstudio作為開發工具,使用混合式開發,途中需要整合mui.但是網上找了很多教程都是老版本的,以至於MUI官網提供的demo已經不符合教程了。後來進過多方努力終於找到了新版的教程,特此記錄。 新版教程連結點這

android開發(0)android studio的下載安裝與簡單使用 | sdk的安裝與編譯

ger 準備 開發環境 view 選擇 集成開發環境 alt 尋找 control android studio,簡稱AS,是集成開發環境,所謂集成,就是集編輯、編譯、調試、打包等於一體。簡單來說,通過AS,就可以開發出在android系統上運行的APP。 我使用的是mac

ArcGIS Runtime SDK for Android 入門(9)通過PictureMarkerSymbol建立點符號

    本文主要簡單講解如何通過本地或線上資源的方式使用SimpleMarkerSymbol建立簡單的圖片點符號。 實現步驟: 1.建立Android專案    2.新增Runtime SDK依賴 3.新增許可權及OpenGL ES支援 在AndroidMani

android-使用環信SDK開發即時通信功能及源代碼下載

聊天功能 實時 成就 soft cat xtend 技術 easy www. 近期項目中集成即時聊天功能。挑來揀去,終於選擇環信SDK來進行開發,選擇環信的主要原因是接口方便、簡潔。說明文檔清楚易懂。文檔有android、ios、和後臺server端。還

HyperLeger Fabric SDK開發(一)——Fabric SDK開發簡介

HyperLeger Fabric SDK開發(一)——Fabric SDK開發簡介 一、Fabric SDK簡介 1、Fabric SDK簡介 Farbric的Peer節點和Orderer節點都提供了基於gRPC協議的介面,用於和Peer節點與Orderer節點進行命令/資料互動。為了簡化開發,為開發

HyperLeger Fabric SDK開發(二)——Fabric SDK配置

HyperLeger Fabric SDK開發(二)——Fabric SDK配置 一、Fabric SDK配置 Fabric區塊鏈網路應用程式需要大量的引數,用於連線Fabric區塊鏈網路。通常將Fabric區塊鏈網路應用程式所需的引數放到一個配置檔案進行管理,配置檔案定義Fabric SDK Go的配置

HyperLeger Fabric SDK開發(三)——fabsdk

HyperLeger Fabric SDK開發(三)——fabsdk 一、fabsdk簡介 1、fabsdk簡介 fabsdk是Fabric SDK的主要包,fabsdk支援客戶端使用Hyperledger Fabric區塊鏈網路。fabsdk基於配置建立上下文環境,上下文環境會在client包使用。官

HyperLeger Fabric SDK開發(四)——channel

HyperLeger Fabric SDK開發(四)——channel 一、channel簡介 1、channel 簡介 pkg/client/channel支援訪問Fabric網路上的通道。channel客戶端例項提供與指定通道上的Peer節點進行互動的處理函式。channel客戶端可以在指

PI Square中文論壇 PI SDK 開發中級篇| PI Square

注: 為了更好的利用站內資源營造一個更好的中文開發資源空間,本文為轉發修正帖,原作者為OSIsoft技術工程師王曦(Xi Wang),原帖地址:PI SDK 中級篇  來源:https://d.gg363.site/url?sa=t&rct=j&q=&a

HyperLeger Fabric SDK開發(五)——event

HyperLeger Fabric SDK開發(五)——event 一、event簡介 1、event簡介 event包支援訪問Fabric網路上的通道事件。事件客戶端可以接收區塊事件,過濾區塊事件,鏈碼事件和交易狀態事件。官方文件:https://godoc.org/github.com/hyperl

HyperLeger Fabric SDK開發(八)——msp

HyperLeger Fabric SDK開發(八)——msp 一、msp簡介 1、msp簡介 msp支援在Fabric網路上建立和更新使用者。MSP客戶端支援以下操作:Enroll,Reenroll,Register,Revoke和GetSigningIdentity。官方文件:https://god

HyperLeger Fabric SDK開發(七)——ledger

HyperLeger Fabric SDK開發(七)——ledger 一、ledger簡介 1、ledger簡介 ledger包支援在Fabric網路上的指定通道上啟用賬本查詢。如果應用程式需要對多個通道進行賬本查詢,需要為每個通道的賬本客戶端建立一個單獨例項。賬本客戶端支援以下查詢:QueryInfo

HyperLeger Fabric SDK開發(六)——resmgmt

HyperLeger Fabric SDK開發(六)——resmgmt 一、resmgmt簡介 1、resmgmt簡介 resmgmt支援在Fabric網路上建立和更新資源。resmgmt允許管理員建立、更新通道,並允許Peer節點加入通道。管理員還可以在Peer節點上執行與鏈碼相關的操作,例如安裝,例

Fabric-sdk-java更改背書策略,由OR變為AND

1、修改chaincodeendorsementpolicy.yaml  identities: # list roles to be used in the policy user1: {"role": {"name": "member", "mspId": "

Android開發-在Android應用裡整合友盟訊息推送SDK的實現(相容小米、華為、魅族機型離線推送)

前 言 最近由於專案的功能需求的需要,需要在Android應用整合訊息推送的功能,而目前市面上的第三方訊息推送除了友盟推送外,還有極光推送、小米推送、個推以及信鴿(騰訊)推送等。當時本人對比各大第三方的訊息推送進行了測試,覺得友盟訊息推送整合簡單,推送訊息的

ChainDesk:從零到壹構建基於 fabric-sdk-node 的專案開發實戰

 ChainDesk:從零到壹構建基於 fabric-sdk-node 的專案開發實戰 第一章:搭建環境 http://www.chaindesk.cn/witbook/14/200?20190102meiti 第二章:鏈碼實現 http://www.chaindesk.cn/wi

android-使用環信SDK開發即時通訊功能及原始碼下載

最近專案中整合即時聊天功能,挑來揀去,最終選擇環信SDK來進行開發,選擇環信的主要原因是介面方便、簡潔,說明文件清晰易懂。文件有android、ios、和後臺伺服器端,還是非常全的。 環信官網:http://www.easemob.com/ 本篇文章目的主要

Android基於環信SDK開發IM即時聊天(一)

目前市面上我瞭解的做第三方即時聊天SDK的有兩家:環信、融雲,這裡我使用環信SDK來完成即時聊天的初步開發工作。 下面先奉上1張效果圖: 1、開發準備 首先要到環信官網註冊開發者賬號,目前只有企業賬號註冊,不過反正也不會去稽核企業資訊的正確與否,所

Android開發-在Android專案裡整合友盟統計SDK進行對移動APP統計的實現

前 言 友盟(Umeng),2010年4月在北京成立,是中國最專業、最有資料凝聚力的移動開發者服務平臺。友盟以移動應用統計分析為產品起點,發展成為提供從基礎設定搭建-開發-運營服務的整合服務平臺,致力於為移動開發者提供專業的資料統計分析、開發和運營元件