Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How to Build Awesome Android Libraries (360 AnDev 2021)

How to Build Awesome Android Libraries (360 AnDev 2021)

This talk is a collection of advice about building Android libraries or SDKs, highlighting some of the less obvious things you can do to make your library great.

Many of the recommendations will also make your life easier in any multi-module project, even if you're not publishing libraries anywhere.

All of this is based on my own open-source library development work - which I do both in my free time and at my day job working on the Stream Chat Android SDK.

More info and resources: https://zsmb.co/appearances/360-andev-2021/

Marton Braun

July 22, 2021
Tweet

More Decks by Marton Braun

Other Decks in Programming

Transcript

  1. zsmb.co
    zsmb13
    How to Build Awesome
    Android Libraries
    Márton Braun

    View Slide

  2. Introduction

    View Slide

  3. Introduction
    RainbowCake
    rainbowcake/rainbowcake
    Krate
    AutSoft/Krate
    MaterialDrawerKt
    zsmb13/MaterialDrawerKt
    requireKTX
    zsmb13/requireKTX

    View Slide

  4. GetStream/stream-chat-android
    › Open source chat SDK

    View Slide

  5. GetStream/stream-chat-android
    › Open source chat SDK
    › Low-level client with
    real-time events

    View Slide

  6. GetStream/stream-chat-android
    › Open source chat SDK
    › Low-level client with
    real-time events

    View Slide

  7. GetStream/stream-chat-android
    › Open source chat SDK
    › Low-level client with
    real-time events
    › Offline support
    › Pre-built UI components

    View Slide

  8. GetStream/stream-chat-android
    › Open source chat SDK
    › Low-level client with
    real-time events
    › Offline support
    › Pre-built UI components

    View Slide

  9. GetStream/stream-chat-android
    › Open source chat SDK
    › Low-level client with
    real-time events
    › Offline support
    › Pre-built UI components
    › Kotlin-first APIs

    View Slide

  10. GetStream/stream-chat-android
    › Open source chat SDK
    › Low-level client with
    real-time events
    › Offline support
    › Pre-built UI components
    › Kotlin-first APIs
    › Free for makers!

    View Slide

  11. GetStream/stream-chat-android

    View Slide

  12. TL;DW Minimize ALL the things!

    View Slide

  13. TL;DW Minimize ALL the things!
    › Features of the library

    View Slide

  14. TL;DW Minimize ALL the things!
    › Features of the library
    › Public API

    View Slide

  15. TL;DW Minimize ALL the things!
    › Features of the library
    › Public API
    › Dependencies

    View Slide

  16. TL;DW Minimize ALL the things!
    › Features of the library
    › Public API
    › Dependencies
    › Performance impact

    View Slide

  17. TL;DW Minimize ALL the things!
    › Features of the library
    › Public API
    › Dependencies
    › Performance impact
    › Enabled features by default

    View Slide

  18. TL;DW Minimize ALL the things!
    › Features of the library
    › Public API
    › Dependencies
    › Performance impact
    › Enabled features by default
    › Requirements

    View Slide

  19. Public API

    View Slide

  20. Public API
    › Minimal API

    View Slide

  21. Public API
    › Minimal API Item 15: Minimize the accessibility of classes and members

    View Slide

  22. Public API
    › Minimal API
    › Deprecations

    View Slide

  23. Public API
    › Minimal API
    › Deprecations

    View Slide

  24. Public API
    › Minimal API
    › Deprecations
    › Easy to use

    View Slide

  25. Public API
    › Minimal API
    › Deprecations
    › Easy to use
    › Hard to misuse

    View Slide

  26. Public API
    zsmb.co/talks/mastering-api-visibility/
    › Minimal API
    › Deprecations
    › Easy to use
    › Hard to misuse
    › Controlling visibility

    View Slide

  27. Public API
    › Minimal API
    › Deprecations
    › Easy to use
    › Hard to misuse
    › Controlling visibility
    › Validating

    View Slide

  28. Public API
    › Minimal API
    › Deprecations
    › Easy to use
    › Hard to misuse
    › Controlling visibility
    › Validating

    View Slide

  29. Public API
    › Minimal API
    › Deprecations
    › Easy to use
    › Hard to misuse
    › Controlling visibility
    › Validating
    › Dependencies
    interface ChatClient {
    suspend fun sendMessage(message: Message): Message
    }

    View Slide

  30. Public API
    › Minimal API
    › Deprecations
    › Easy to use
    › Hard to misuse
    › Controlling visibility
    › Validating
    › Dependencies
    public interface Call {
    public fun execute(): Result
    public fun enqueue(callback: Callback)
    }
    public suspend fun Call.await(): Result

    View Slide

  31. Dependencies

    View Slide

  32. Dependencies
    › Minimal dependencies

    View Slide

  33. Dependencies
    › Minimal dependencies
    › Size

    View Slide

  34. Dependencies
    › Minimal dependencies
    › Size
    › Many libraries per app

    View Slide

  35. Dependencies
    › Minimal dependencies
    › Size
    › Many libraries per app
    › Library present in
    multiple apps

    View Slide

  36. Dependencies
    › Minimal dependencies
    › Size
    › Many libraries per app
    › Library present in
    multiple apps
    › Complexity

    View Slide

  37. Dependencies
    › Minimal dependencies
    › Size
    › Many libraries per app
    › Library present in
    multiple apps
    › Complexity
    › Version conflicts

    View Slide

  38. Dependencies
    Library 2
    Library 1
    Appcompat 1.4
    alpha
    Appcompat 1.2
    App
    › Minimal dependencies
    › Size
    › Many libraries per app
    › Library present in
    multiple apps
    › Complexity
    › Version conflicts

    View Slide

  39. Version updates

    View Slide

  40. Version updates

    View Slide

  41. implementation vs api
    Library 1
    App

    View Slide

  42. implementation vs api
    Library 1
    Library 2
    App
    implementation

    View Slide

  43. implementation vs api
    Library 1
    Library 2
    App
    implementation

    View Slide

  44. implementation vs api
    Library 1
    Library 2
    App
    api
    Library 1
    Library 2
    App
    implementation

    View Slide

  45. library.aar

    View Slide

  46. library.aar
    resources
    layout.xml
    values.xml

    View Slide

  47. library.aar
    resources
    layout.xml
    values.xml
    AndroidManifest.xml

    View Slide

  48. library.aar
    resources
    layout.xml
    values.xml
    AndroidManifest.xml
    classes.jar

    View Slide

  49. library.aar
    resources
    layout.xml
    values.xml
    AndroidManifest.xml
    classes.jar R.txt

    View Slide

  50. library.aar
    resources
    layout.xml
    values.xml
    AndroidManifest.xml
    classes.jar R.txt
    library-
    sources.jar
    library-
    javadoc.jar
    *.kt *.html

    View Slide

  51. The POM file
    library.pom


    io.getstream
    stream-chat-android-client
    4.12.0
    aar
    stream-chat-android-client


    org.jetbrains.kotlin
    kotlin-stdlib
    1.5.10
    runtime

    ...


    library.aar
    resources
    layout.xml
    values.xml
    AndroidManifest.xml
    classes.jar R.txt
    library-
    sources.jar
    library-
    javadoc.jar
    *.kt *.html

    View Slide

  52. The POM file
    library.pom


    io.getstream
    stream-chat-android-client
    4.12.0
    aar
    stream-chat-android-client


    org.jetbrains.kotlin
    kotlin-stdlib
    1.5.10
    runtime

    ...


    View Slide

  53. The POM file
    library.pom


    io.getstream
    stream-chat-android-client
    4.12.0
    aar
    stream-chat-android-client


    org.jetbrains.kotlin
    kotlin-stdlib
    1.5.10
    runtime

    ...


    View Slide

  54. The POM file
    library.pom


    io.getstream
    stream-chat-android-client
    4.12.0
    aar
    stream-chat-android-client


    org.jetbrains.kotlin
    kotlin-stdlib
    1.5.10
    runtime

    ...


    View Slide

  55. Repositories
    MavenCentral
    Library 1

    View Slide

  56. Repositories
    MavenCentral
    Jitpack
    Jcenter
    Library 3
    Library 2
    Library 1

    View Slide

  57. Repositories
    MavenCentral
    Jitpack
    Jcenter
    Library 3
    Library 2
    Library 1

    View Slide

  58. Repositories
    App
    MavenCentral
    Jitpack
    Jcenter
    Library 3
    Library 2
    Library 1

    View Slide

  59. Repositories
    App
    MavenCentral
    Jitpack
    Jcenter
    Library 3
    Library 2
    Library 1

    View Slide

  60. Repositories
    App
    MavenCentral
    Jitpack
    Jcenter
    Library 3
    Library 2
    Library 1

    View Slide

  61. Repositories
    App
    MavenCentral
    Jitpack
    Jcenter
    Library 3
    Library 2
    Library 1

    View Slide

  62. Multi-module libraries
    my-awesome-lib

    View Slide

  63. Multi-module libraries
    my-awesome-lib

    View Slide

  64. Multi-module libraries
    my-awesome-lib
    my-awesome-lib-plus
    my-awesome-lib-core

    View Slide

  65. Multi-module libraries
    my-awesome-lib-plus
    my-awesome-lib-core
    my-awesome-lib

    View Slide

  66. rx
    Multi-module libraries
    my-awesome-lib-plus
    my-awesome-lib-core

    View Slide

  67. Multi-module libraries
    plus rxjava
    my-awesome-lib-rx
    my-awesome-lib-core

    View Slide

  68. Fat AARs
    ui-components
    core
    offline
    client

    View Slide

  69. Fat AARs
    ui-components
    core
    offline
    client
    App

    View Slide

  70. Fat AARs
    ui-components
    core
    offline
    client
    App

    View Slide

  71. Fat AARs
    ui-components
    core
    offline
    client
    App

    View Slide

  72. Fat AARs

    View Slide

  73. Fat AARs

    View Slide

  74. Fat AARs

    View Slide

  75. Fat AARs
    "At the moment we are talking with Gradle about being able
    to merge dependencies from multiple projects (that are
    being bundled), as that part is a problem in the JVM
    ecosystem as well. Once that is in, we can focus on the
    Android-specific features (Android resources, manifest etc.)."
    2020-12-02

    View Slide

  76. Fat AARs
    fat-aar-plugin
    vigidroid/fat-aar-plugin
    fataar-gradle-plugin
    Mobbeel/fataar-gradle-plugin
    fat-aar-android
    kezong/fat-aar-android
    android-fat-aar
    adwiv/android-fat-aar

    View Slide

  77. Startup impact

    View Slide

  78. Startup impact
    › Don’t hog startup
    › Competing with other libraries

    View Slide

  79. Startup impact
    › Don’t hog startup
    › Competing with other libraries
    › Initialize on-demand

    View Slide

  80. Startup impact
    › Don’t hog startup
    › Competing with other libraries
    › Initialize on-demand
    › App Startup

    View Slide

  81. Logging

    View Slide

  82. Logging
    › Don’t log by default

    View Slide

  83. Logging
    › Don’t log by default
    val client = ChatClient.Builder("apiKey", context)
    .logLevel(ChatLogLevel.ALL)
    .build()

    View Slide

  84. Logging
    › Don’t log by default
    › Don’t enable any feature by default
    val client = ChatClient.Builder("apiKey", context)
    .logLevel(ChatLogLevel.ALL)
    .build()

    View Slide

  85. Requirements
    › Minimal requirements
    › Make integrating your library easy
    › Don’t force things on your clients

    View Slide

  86. API level
    App
    Library 1 Library 2 Library 3
    API 21
    API 21 API 19
    API 15

    View Slide

  87. API level
    App
    Library 1 Library 2 Library 3
    API 21
    API 21 API 19
    API 15

    View Slide

  88. API level
    App
    Library 1 Library 2 Library 3
    API 21
    API 21 API 23
    API 15

    View Slide

  89. API level
    App
    Library 1 Library 2 Library 3
    API 23
    API 21 API 23
    API 15

    View Slide

  90. Permissions & features
    library.aar
    resources
    layout.xml
    values.xml
    AndroidManifest.xml
    classes.jar R.txt

    View Slide

  91. Permissions & features


    android:minSdkVersion="21"
    android:targetSdkVersion="29" />









    library.aar
    resources
    layout.xml
    values.xml
    AndroidManifest.xml
    classes.jar R.txt

    View Slide

  92. Permissions & features


    android:minSdkVersion="21"
    android:targetSdkVersion="29" />









    AndroidManifest.xml

    View Slide



  93. android:minSdkVersion="21"
    android:targetSdkVersion="29" />









    Permissions & features
    AndroidManifest.xml

    View Slide



  94. android:minSdkVersion="21"
    android:targetSdkVersion="29" />









    Permissions & features
    AndroidManifest.xml

    View Slide



  95. android:minSdkVersion="21"
    android:targetSdkVersion="29" />









    Permissions & features
    AndroidManifest.xml

    View Slide

  96. Resource prefixes
    android {
    resourcePrefix 'stream_ui_'
    }

    View Slide

  97. Resource prefixes


    #005FFF
    #FF3742
    #20E070

    accent_green
    android {
    resourcePrefix 'stream_ui_'
    }

    View Slide

  98. Resource prefixes
    android {
    resourcePrefix 'stream_ui_'
    }


    #005FFF
    #FF3742
    #20E070

    accent_green

    View Slide

  99. Resource prefixes
    android {
    resourcePrefix 'stream_ui_'
    }


    #005FFF
    #FF3742
    #20E070

    accent_green
    Resource named 'accent_green' does not start
    with the project's resource prefix 'stream_ui_';
    rename to 'stream_ui_accent_green' ?

    View Slide

  100. Resource prefixes
    android {
    resourcePrefix 'stream_ui_'
    }










    View Slide

  101. Resource prefixes
    android {
    resourcePrefix 'stream_ui_'
    }

    View Slide

  102. Private resources

    View Slide

  103. Private resources





    View Slide

  104. Explicitly public resources





    View Slide

  105. Proguard
    library.aar
    resources
    layout.xml
    values.xml
    AndroidManifest.xml
    classes.jar R.txt

    View Slide

  106. Proguard
    ## Stream Chat Android Client Proguard Rules
    -keep class io.getstream.chat.android.client.api.* { *; }
    -keep class io.getstream.chat.android.client.api.models.* { *; }
    -keep class io.getstream.chat.android.client.api2.model.** { *; }
    -keep class io.getstream.chat.android.client.errors.* { *; }
    -keep class io.getstream.chat.android.client.events.* { *; }
    -keep class io.getstream.chat.android.client.models.* { *; }
    -keep class io.getstream.chat.android.client.parser.* { *; }
    -keep class io.getstream.chat.android.client.socket.* { *; }
    -keep class io.getstream.chat.android.client.utils.Result { *; }
    -keep class io.getstream.chat.android.client.utils.SyncStatus { *; }
    library.aar
    resources
    layout.xml
    values.xml
    AndroidManifest.xml
    classes.jar R.txt
    proguard.txt

    View Slide

  107. Proguard
    ## Stream Chat Android Client Proguard Rules
    -keep class io.getstream.chat.android.client.api.* { *; }
    -keep class io.getstream.chat.android.client.api.models.* { *; }
    -keep class io.getstream.chat.android.client.api2.model.** { *; }
    -keep class io.getstream.chat.android.client.errors.* { *; }
    -keep class io.getstream.chat.android.client.events.* { *; }
    -keep class io.getstream.chat.android.client.models.* { *; }
    -keep class io.getstream.chat.android.client.parser.* { *; }
    -keep class io.getstream.chat.android.client.socket.* { *; }
    -keep class io.getstream.chat.android.client.utils.Result { *; }
    -keep class io.getstream.chat.android.client.utils.SyncStatus { *; }
    proguard.txt

    View Slide

  108. Proguard
    ## Stream Chat Android Client Proguard Rules
    -keep class io.getstream.chat.android.client.api.* { *; }
    -keep class io.getstream.chat.android.client.api.models.* { *; }
    -keep class io.getstream.chat.android.client.api2.model.** { *; }
    -keep class io.getstream.chat.android.client.errors.* { *; }
    -keep class io.getstream.chat.android.client.events.* { *; }
    -keep class io.getstream.chat.android.client.models.* { *; }
    -keep class io.getstream.chat.android.client.parser.* { *; }
    -keep class io.getstream.chat.android.client.socket.* { *; }
    -keep class io.getstream.chat.android.client.utils.Result { *; }
    -keep class io.getstream.chat.android.client.utils.SyncStatus { *; }
    -dontoptimize
    -dontshrink
    proguard.txt

    View Slide

  109. Proguard
    android {
    buildTypes {
    release {
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt’),
    'proguard-rules.pro'
    consumerProguardFiles 'consumer-proguard-rules.pro'
    }
    debug {
    consumerProguardFiles 'consumer-proguard-rules.pro'
    }
    }
    }

    View Slide

  110. Proguard
    android {
    buildTypes {
    release {
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt’),
    'proguard-rules.pro'
    consumerProguardFiles 'consumer-proguard-rules.pro'
    }
    debug {
    consumerProguardFiles 'consumer-proguard-rules.pro'
    }
    }
    }

    View Slide

  111. Proguard
    android {
    buildTypes {
    release {
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt’),
    'proguard-rules.pro'
    consumerProguardFiles 'consumer-proguard-rules.pro'
    }
    debug {
    consumerProguardFiles 'consumer-proguard-rules.pro'
    }
    }
    }

    View Slide

  112. Testing

    View Slide

  113. Testing
    › Lots of responsibility

    View Slide

  114. Testing
    › Lots of responsibility
    › Diverse environments

    View Slide

  115. Testing
    › Lots of responsibility
    › Diverse environments
    › Can’t assume anything

    View Slide

  116. Testing
    › Lots of responsibility
    › Diverse environments
    › Can’t assume anything
    › Devices, architectures, OS versions, stores

    View Slide

  117. Testing
    › Lots of responsibility
    › Diverse environments
    › Can’t assume anything
    › Devices, architectures, OS versions, stores
    › Other frameworks and libraries

    View Slide

  118. Testing
    › Lots of responsibility
    › Diverse environments
    › Can’t assume anything
    › Devices, architectures, OS versions, stores
    › Other frameworks and libraries
    › Your code is not final

    View Slide

  119. Documentation

    View Slide

  120. Documentation
    › Have documentation

    View Slide

  121. Documentation
    › Have documentation
    › README

    View Slide

  122. Documentation
    › Have documentation
    › README
    › What it does

    View Slide

  123. Documentation
    › Have documentation
    › README
    › What it does
    › Setup instructions

    View Slide

  124. Documentation
    › Have documentation
    › README
    › What it does
    › Setup instructions
    › Screenshots

    View Slide

  125. Documentation
    › Have documentation
    › README
    › Code comments

    View Slide

  126. Documentation
    › Have documentation
    › README
    › Code comments

    View Slide

  127. Documentation
    › Have documentation
    › README
    › Code comments

    View Slide

  128. Documentation
    › Have documentation
    › README
    › Code comments
    › Sample app

    View Slide

  129. Documentation
    › Have documentation
    › README
    › Code comments
    › Sample app
    › Update strategy

    View Slide

  130. Publishing

    View Slide

  131. Publishing
    › Maven repositories

    View Slide

  132. Publishing
    › Maven repositories
    › Main options

    View Slide

  133. Publishing
    › Maven repositories
    › Main options
    › Jcenter

    View Slide

  134. Publishing
    › Maven repositories
    › Main options
    › Jcenter

    View Slide

  135. Publishing
    › Maven repositories
    › Main options
    › Jcenter

    View Slide

  136. Publishing
    › Maven repositories
    › Main options
    › Jcenter

    View Slide

  137. Publishing
    › Maven repositories
    › Main options
    › Jcenter
    › Jitpack

    View Slide

  138. Publishing
    › Maven repositories
    › Main options
    › Jcenter
    › Jitpack

    View Slide

  139. Publishing
    › Maven repositories
    › Main options
    › Jcenter
    › Jitpack
    › Maven Central

    View Slide

  140. Publishing
    › Maven repositories
    › Main options
    › Jcenter
    › Jitpack
    › Maven Central

    View Slide

  141. Publishing
    › Coordinates

    View Slide

  142. Publishing
    › Coordinates
    io.getstream:stream-chat-android-client:4.12.0

    View Slide

  143. Publishing
    › Coordinates
    io.getstream : stream-chat-android-client : 4.12.0
    Group ID Version
    Artifact ID

    View Slide

  144. Publishing
    Group ID
    io.getstream : stream-chat-android-client : 4.12.0
    Version
    Artifact ID
    › Coordinates

    View Slide

  145. Publishing
    › Coordinates
    io.getstream : stream-chat-android-client : 4.12.0
    Group ID Version
    Artifact ID

    View Slide

  146. Publishing
    › Coordinates
    › Versioning
    io.getstream : stream-chat-android-client : 4.12.0
    Group ID Version
    Artifact ID

    View Slide

  147. Publishing
    › Coordinates
    › Versioning
    semver.org
    io.getstream : stream-chat-android-client : 4.12.0
    Group ID Version
    Artifact ID

    View Slide

  148. Publishing
    › Coordinates
    › Versioning
    › License

    View Slide

  149. Publishing
    › Coordinates
    › Versioning
    › License
    tldrlegal.com

    View Slide

  150. Release checklist

    View Slide

  151. Community

    View Slide

  152. Community
    › Open source vs source available

    View Slide

  153. Community
    › Open source vs source available
    › Address issues and discussions

    View Slide

  154. Community
    › Open source vs source available
    › Address issues and discussions
    › Take PR contributions

    View Slide

  155. Community
    › Open source vs source available
    › Address issues and discussions
    › Take PR contributions
    › Be open for feedback*

    View Slide

  156. Community
    › Open source vs source available
    › Address issues and discussions
    › Take PR contributions
    › Be open for feedback*
    “You're supposed to side with the community, but you
    should also have a say in what you're building”
    – Filip Babić

    View Slide

  157. Resources
    • Nishant Srivastava’s excellent talks
     Things I wish I knew when I started building Android SDK/Libraries
     https://www.youtube.com/watch?v=G-x9wRWwICo
     Things I wish I knew when I started building Android Libraries Vol 2
     https://www.youtube.com/watch?v=jQyt3HSmx2I
    • Mastering API Visibility in Kotlin
     https://zsmb.co/talks/mastering-api-visibility/
     Kotlin/binary-compatibility-validator
     https://github.com/Kotlin/binary-compatibility-validator
    • Publishing Android libraries to MavenCentral in 2021
     https://proandroiddev.com/publishing-android-libraries-to-mavencentral-in-2021-8ac9975c3e52

    View Slide

  158. Resources
    • Jeroen Mols’ library development articles
     https://jeroenmols.com/blog/2020/10/28/library-gettingstarted/
     What is a library and how is it deployed
     https://jeroenmols.com/blog/2020/11/04/library-modularization/
     Publishing submodules, fat AARs, controlling access
     https://jeroenmols.com/blog/2020/11/11/library-dependencies/
     Dependency conflicts and version incompatibilities
    • More on fat AARs
     Sam Edwards’ article
     https://handstandsam.com/2018/07/13/why-we-need-fat-aars-for-android-libraries/
     Open issue on Google’s issue tracker
     https://issuetracker.google.com/issues/62121508

    View Slide

  159. zsmb13
    zsmb.co/talks

    View Slide

  160. How to Build Awesome
    Android Libraries
    zsmb.co/talks
    zsmb13
    Márton Braun
    › Minimize all the things!
    › Public API
    › Dependencies
    › Size and impact
    › Publishing and releases
    › Don’t forget the docs!

    View Slide