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

Becoming an Android Librarian

Becoming an Android Librarian

Becoming an Android Librarian.

Jaewoong

May 14, 2022
Tweet

More Decks by Jaewoong

Other Decks in Programming

Transcript

  1. G E T S T R E A M .

    I O Becoming an Android Librarian
  2. G E T S T R E A M .

    I O skydoves @github_skydoves Android Developer Advocate @ Stream Jaewoong Eum
  3. G E T S T R E A M .

    I O Open-Source Libraries
  4. G E T S T R E A M .

    I O Open-Source Libraries
  5. G E T S T R E A M .

    I O Open-Source Libraries
  6. G E T S T R E A M .

    I O Library & SDK Lifecycles Design Develop Prepare Release
  7. G E T S T R E A M .

    I O Library & SDK Lifecycles Design Develop Prepare Release
  8. G E T S T R E A M .

    I O Library & SDK Lifecycles Design process 1. Define the problem 2. Research overall solutions 3. Verify the feasibility of the solutions 4. Define dependency relationships 5. Draw blueprints of the final usage in real-world projects 6. Design the interfaces
  9. G E T S T R E A M .

    I O Library & SDK Lifecycles Design Develop Prepare Release
  10. G E T S T R E A M .

    I O Development Strategies Minimize API surfaces
  11. G E T S T R E A M .

    I O Development Strategies Minimize API surfaces Client Client Client Client
  12. G E T S T R E A M .

    I O Development Strategies Minimize API surfaces Client Client Client Client
  13. G E T S T R E A M .

    I O Development Strategies Minimize API surfaces Client Client Client Client
  14. G E T S T R E A M .

    I O Development Strategies Minimize API surfaces
  15. G E T S T R E A M .

    I O Development Strategies Minimize API surfaces Client Client Client Client
  16. G E T S T R E A M .

    I O Development Strategies Minimize API surfaces Client Client Client Client
  17. G E T S T R E A M .

    I O Development Strategies Minimize API surfaces Client Client Client Client
  18. G E T S T R E A M .

    I O Development Strategies Minimize API surfaces private internal importance protected public
  19. G E T S T R E A M .

    I O Development Strategies Minimize API surfaces private internal importance protected public Client Client Client
  20. G E T S T R E A M .

    I O Development Strategies Minimize API surfaces class ApiResponseCallAdapter constructor( val resultType: Type ) : CallAdapter<Type, Call<ApiResponse<Type>>> { override fun responseType(): Type { return resultType } override fun adapt(call: Call<Type>): Call<ApiResponse<Type>> { return ApiResponseCallDelegate(call) } }
  21. G E T S T R E A M .

    I O Development Strategies Minimize API surfaces internal class ApiResponseCallAdapter constructor( private val resultType: Type ) : CallAdapter<Type, Call<ApiResponse<Type>>> { override fun responseType(): Type { return resultType } override fun adapt(call: Call<Type>): Call<ApiResponse<Type>> { return ApiResponseCallDelegate(call) } }
  22. G E T S T R E A M .

    I O Development Strategies Minimize API surfaces fun Context.dp2Px(dp: Int): Int { val scale = resources.displayMetrics.density return (dp * scale).toInt() } fun Context.px2Sp(px: Int): Int { val scale = resources.displayMetrics.scaledDensity return (px / scale).toInt() } val px = context.dp2Px(dp = 22) val sp = context.px2Sp(px = 22)
  23. G E T S T R E A M .

    I O Development Strategies Minimize API surfaces internal fun Context.dp2Px(dp: Int): Int { val scale = resources.displayMetrics.density return (dp * scale).toInt() } internal fun Context.px2Sp(px: Int): Int { val scale = resources.displayMetrics.scaledDensity return (px / scale).toInt() } val px = context.dp2Px(dp = 22) // Unresolved reference val sp = context.px2Sp(px = 22) // Unresolved reference
  24. G E T S T R E A M .

    I O Development Strategies Minimize API surfaces internal fun Context.dp2Px(dp: Int): Int { val scale = resources.displayMetrics.density return (dp * scale).toInt() } internal fun Context.px2Sp(px: Int): Int { val scale = resources.displayMetrics.scaledDensity return (px / scale).toInt() } int px = ContextExtensionKt.dp2Px(context, 11); int sp = ContextExtensionKt.px2Sp(context, 11);
  25. G E T S T R E A M .

    I O Development Strategies Minimize API surfaces @JvmSynthetic internal fun Context.dp2Px(dp: Int): Int { val scale = resources.displayMetrics.density return (dp * scale).toInt() } @JvmSynthetic internal fun Context.px2Sp(px: Int): Int { val scale = resources.displayMetrics.scaledDensity return (px / scale).toInt() } int px = ContextExtensionKt.dp2Px(context, 11); // Unresolved reference int sp = ContextExtensionKt.px2Sp(context, 11); // Unresolved reference
  26. G E T S T R E A M .

    I O Development Strategies Explicit API mode
  27. G E T S T R E A M .

    I O Development Strategies Explicit API mode
  28. G E T S T R E A M .

    I O Development Strategies Explicit API mode
  29. G E T S T R E A M .

    I O Development Strategies Explicit API mode
  30. G E T S T R E A M .

    I O Development Strategies Explicit API mode
  31. G E T S T R E A M .

    I O Development Strategies Binary Compatibility Validator
  32. G E T S T R E A M .

    I O Development Strategies Binary Compatibility Validator build.gradle module.gradle On terminal
  33. G E T S T R E A M .

    I O Development Strategies Binary Compatibility Validator module.api
  34. G E T S T R E A M .

    I O Development Strategies Binary Compatibility Validator
  35. G E T S T R E A M .

    I O Development Strategies Metalava
  36. G E T S T R E A M .

    I O Development Strategies Exposing resources /classes.jar /res/ /R.txt /public.txt /assets/ /libs/name.jar /jni/abi_name/name.so /proguard.txt /lint.jar /api.jar AAR file
  37. G E T S T R E A M .

    I O Development Strategies Exposing resources /classes.jar /res/ /R.txt /public.txt /assets/ /libs/name.jar /jni/abi_name/name.so /proguard.txt /lint.jar /api.jar AAR file res/drawable res/layout res/menu res/values res/xml res/raw res/anim res/animator res/mipmap res/font string.xml colors.xml styles.xml dimens.xml arrays.xml … /res/ /res/values/
  38. G E T S T R E A M .

    I O Development Strategies Exposing resources <resources> <color name="white">#FFFFFF</color> <color name="black">#000000</color> <color name="blue">#57A8D8</color> <color name="yellow">#FBC02D</color> </resources> Library (colors.xml) Project val whiteColor = ContextCompat.getColor(this, R.color.white) binding.myView.setBackgroundColor(whiteColor) <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="skydoves" android:textColor="@color/yellow" />
  39. G E T S T R E A M .

    I O Development Strategies Exposing resources <resources> <color name="white">#FFFFFF</color> <color name="black">#000000</color> <color name="blue">#57A8D8</color> <color name="yellow">#FBC02D</color> </resources> Library (colors.xml) val whiteColor = ContextCompat.getColor(this, R.color.white) binding.myView.setBackgroundColor(whiteColor) <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="skydoves" android:textColor="@color/yellow" /> Project compile error!
  40. G E T S T R E A M .

    I O Development Strategies Exposing resources public.xml
  41. G E T S T R E A M .

    I O Development Strategies Exposing resources <?xml version="1.0" encoding="utf-8"?> <resources xmlns:tools="http://schemas.android.com/tools"> <!-- Definitions of layouts to be exposed as public ⟶ <public name="balloon_layout_body" type="layout" /> <public name="balloon_layout_overlay" type="layout" /> <!-- Definitions of attributes to be exposed as public ⟶ <public name="balloon_drawableStart" type="attr" /> <public name="balloon_drawableEnd" type="attr" /> <public name="balloon_drawableTop" type="attr" /> <public name="balloon_drawableBottom" type="attr" /> <public name="balloon_drawablePadding" type="attr" /> <public name="balloon_drawableTintColor" type="attr" /> <public name="balloon_drawableWidth" type="attr" /> <public name="balloon_drawableHeight" type="attr" /> <public name="balloon_drawableSquareSize" type="attr" /> Library (/res/values/public.xml)
  42. G E T S T R E A M .

    I O Development Strategies Exposing resources <?xml version="1.0" encoding="utf-8"?> <resources xmlns:tools="http://schemas.android.com/tools"> <!-- Definitions of layouts to be exposed as public ⟶ <public name="balloon_layout_body" type="layout" /> <public name="balloon_layout_overlay" type="layout" /> <!-- Definitions of attributes to be exposed as public ⟶ <public name="balloon_drawableStart" type="attr" /> <public name="balloon_drawableEnd" type="attr" /> <public name="balloon_drawableTop" type="attr" /> <public name="balloon_drawableBottom" type="attr" /> <public name="balloon_drawablePadding" type="attr" /> <public name="balloon_drawableTintColor" type="attr" /> <public name="balloon_drawableWidth" type="attr" /> <public name="balloon_drawableHeight" type="attr" /> <public name="balloon_drawableSquareSize" type="attr" /> Library (/res/values/public.xml) res/drawable res/layout res/menu res/values res/xml res/raw res/anim res/animator res/mipmap res/font String.xml attrs.xml colors.xml styles.xml dimens.xml arrays.xml /res/ /res/values/
  43. G E T S T R E A M .

    I O Development Strategies Exposing resources Project (XML) Project (code)
  44. G E T S T R E A M .

    I O Development Strategies Exposing resources Project (XML) Project (code)
  45. G E T S T R E A M .

    I O Development Strategies Exposing resources
  46. G E T S T R E A M .

    I O Development Strategies Exposing resources
  47. G E T S T R E A M .

    I O Development Strategies Exposing resources
  48. G E T S T R E A M .

    I O Development Strategies Exposing resources Library (layout_balloon.xml) Library (Balloon.Builder.kt)
  49. G E T S T R E A M .

    I O Development Strategies Exposing resources • Some issues have been reported in Crashlytics. • But the reports were not helpful at all. • Occasionally the library behaves very weirdly. • Also it’s really difficult to reproduce.
  50. G E T S T R E A M .

    I O Development Strategies Exposing resources Perhaps..?
  51. G E T S T R E A M .

    I O Development Strategies Exposing resources <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:clipChildren="false" android:clipToPadding="false" android:padding="10dp"> <com.skydoves.balloon.vectortext.VectorTextView android:id="@+id/text" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_vertical" android:textColor="@android:color/white" /> … Library (layout_balloon.xml) Project (layout_balloon.xml) <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:clipChildren="false" android:clipToPadding="false" android:padding="10dp"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:text="skydoves" android:textSize="16sp" android:textStyle="bold" /> ...
  52. G E T S T R E A M .

    I O Development Strategies Exposing resources <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:clipChildren="false" android:clipToPadding="false" android:padding="10dp"> <com.skydoves.balloon.vectortext.VectorTextView android:id="@+id/text" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_vertical" android:textColor="@android:color/white" /> … Library (layout_balloon.xml) // wrong behaviors Project (layout_balloon.xml) // runtime error! <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:clipChildren="false" android:clipToPadding="false" android:padding="10dp"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:text="skydoves" android:textSize="16sp" android:textStyle="bold" /> ...
  53. G E T S T R E A M .

    I O Development Strategies Resource prefix resourcePrefix
  54. G E T S T R E A M .

    I O Development Strategies Resource prefix build.gradle
  55. G E T S T R E A M .

    I O Development Strategies Resource prefix layout_balloon.xml attrs.xml
  56. G E T S T R E A M .

    I O Development Strategies Resource prefix
  57. G E T S T R E A M .

    I O Development Strategies R class Non transitive R class
  58. G E T S T R E A M .

    I O Development Strategies Non transitive R class
  59. G E T S T R E A M .

    I O Development Strategies Non transitive R class
  60. G E T S T R E A M .

    I O Development Strategies Non transitive R class :app :library :material (MDC) implementation implementation
  61. G E T S T R E A M .

    I O Development Strategies Non transitive R class :app :library :material (MDC) implementation implementation com.google.android.material.R (:material)
  62. G E T S T R E A M .

    I O Development Strategies Non transitive R class :app :library :material (MDC) implementation implementation com.my.library.R (:material) (:library) com.google.android.material.R (:material)
  63. G E T S T R E A M .

    I O Development Strategies Non transitive R class :app :library :material (MDC) implementation implementation com.my.library.R (:material) (:library) com.google.android.material.R (:material) com.my.app.R (:material) (:library) (:app)
  64. G E T S T R E A M .

    I O Development Strategies Non transitive R class :app :library :material (MDC) implementation implementation Transitive dependency com.my.library.R (:material) (:library) com.google.android.material.R (:material) com.my.app.R (:material) (:library) (:app)
  65. G E T S T R E A M .

    I O Development Strategies Non transitive R class com.my.library.R (:material) (:library)
  66. G E T S T R E A M .

    I O Development Strategies Non transitive R class
  67. G E T S T R E A M .

    I O Development Strategies Non transitive R class :app :library :material (MDC) implementation implementation com.my.library.R (:material) (:library) com.google.android.material.R (:material) com.my.app.R (:material) (:library) (:app) Wow, a million of LoC in R classes in a minute!
  68. G E T S T R E A M .

    I O Development Strategies Non transitive R class Dex format has 64K limit for methods and fields references! 64K (65,536 = 64 x 1024 (2^10))
  69. G E T S T R E A M .

    I O Development Strategies Non transitive R class
  70. G E T S T R E A M .

    I O Development Strategies Non transitive R class android.nonTransitiveRClass=true gradle.properties
  71. G E T S T R E A M .

    I O Development Strategies Non transitive R class :app :library :material (MDC) implementation implementation com.my.library.R (:library) com.google.android.material.R (:material) com.my.app.R (:app) Refer to its own resources without pulling resources from dependencies.
  72. G E T S T R E A M .

    I O Development Strategies Non transitive R class Before After
  73. G E T S T R E A M .

    I O Development Strategies Non transitive R class aar size diff 226054 bytes -> 214538 bytes (11516 bytes reduced) 10,000 projects 2260540000 bytes -> 2145380000 bytes (≈115 MB reduced) 100,000 projects 22605400000 bytes -> 21453800000 bytes (≈1.1 GB reduced) 1,000,000 projects 226054000000 bytes -> 214538000000 bytes (≈10 GB reduced) 100,000,000 end-users 22605400000000 bytes -> 21453800000000 bytes (≈1 TB reduced)
  74. G E T S T R E A M .

    I O Development Strategies Non transitive R class :app :feature1 :feature2 :feature3 com.my.app.R (:feature1) (:feature2) (:feature3) (:app) Unresolved reference
  75. G E T S T R E A M .

    I O Development Strategies Non transitive R class :app :feature1 :feature2 :feature3 com.my.app.R (:feature1) (:feature2) (:feature3) (:app) full name package import with namespacing
  76. G E T S T R E A M .

    I O Library & SDK Lifecycles Design Develop Prepare Release
  77. G E T S T R E A M .

    I O Preparation Documentation (KDoc)
  78. G E T S T R E A M .

    I O Preparation Documentation (Dokka) ./gradlew dokkaHtml ./gradlew dokkaHtmlMultiModule ./gradlew dokkaJavadoc
  79. G E T S T R E A M .

    I O Preparation Documentation (README)
  80. G E T S T R E A M .

    I O Library & SDK Lifecycles Design Develop Prepare Release
  81. G E T S T R E A M .

    I O Release Maven
  82. G E T S T R E A M .

    I O Release Maven repositories mavenCentral() google() jcenter()
  83. G E T S T R E A M .

    I O Release Maven central repository mavenCentral()
  84. G E T S T R E A M .

    I O Release Maven central repository 1. Registering a Sonatype account 2. Generating a GPG key pair 3. Setting up publication in your project a. Maven publishing setup with Gradle b. Signing artifacts with GPG key c. Configure pom files d. Per-module Gradle setup 4. Publish to sonatype repository 5. Evaluate and close the ticket on staging repositories
  85. G E T S T R E A M .

    I O Release Maven central repository 🔗 https://bit.ly/386yJt1 🔗 https://bit.ly/3KU3Xk4
  86. G E T S T R E A M .

    I O Release Jitpack maven { url 'https://jitpack.io' }
  87. G E T S T R E A M .

    I O Library & SDK Lifecycles Design Develop Prepare Release Management
  88. G E T S T R E A M .

    I O Management Code formatting
  89. G E T S T R E A M .

    I O Management Code formatting
  90. G E T S T R E A M .

    I O Verifying and Marketing Community
  91. G E T S T R E A M .

    I O Verifying and Marketing Technical contents
  92. G E T S T R E A M .

    I O Verifying and Marketing Example projects Codes speak louder than words!
  93. G E T S T R E A M .

    I O https://github.com/skydoves [email protected] https://twitter.com/github_skydoves https://medium.com/@skydoves Contact
  94. G E T S T R E A M .

    I O Thank you.