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

[AppdevCon '19] Demystifying Android Libraries

[AppdevCon '19] Demystifying Android Libraries

Building an Android library in the current times is way different than what it used to be earlier. Things have changed considerably and keeping up to date with them is now a necessity rather than just some acquirable knowledge.

In this session, you will dive deeper into best practices and ways of architecting Android libraries. You will get to learn about the common pitfalls and how to overcome them by using the right approach such as leveraging architecture components and making your Android libraries lifecycle-aware. You will also understand how one can leverage Kotlin language when developing Android libraries as well as information around API design and exploring the path to becoming a better Android Library Developer.

By the end of this session, you will be all set to build Android libraries that scale and have API which contributes to the developer's happiness.

Event Link: https://web.archive.org/web/20190315154423/https://appdevcon.nl/session/demystifying-android-libraries/

Nishant Srivastava

March 15, 2019
Tweet

More Decks by Nishant Srivastava

Other Decks in Programming

Transcript

  1. 1

    View Slide

  2. OSS Android libraries developed
    2

    View Slide

  3. How does Gradle process
    Android Libraries
    @nisrulz 3

    View Slide

  4. How does Gradle process
    Android Libraries
    repositories {
    jCenter()
    }
    dependencies {
    implementation 'com.github.nisrulz:awesomelib:1.0'
    ...
    }
    4
    @nisrulz

    View Slide

  5. How does Gradle process
    Android Libraries
    repositories {
    jCenter()
    }
    dependencies {
    implementation 'com.github.nisrulz:awesomelib:1.0'
    ...
    }
    5
    @nisrulz
    // Dependency Notation

    View Slide

  6. How does Gradle process
    Android Libraries
    repositories {
    jCenter()
    }
    dependencies {
    implementation 'com/github/nisrulz/awesomelib/1.0'
    ...
    }
    6
    @nisrulz

    View Slide

  7. How does Gradle process
    Android Libraries
    implementation 'com.github.nisrulz:awesomelib:1.0'
    7
    @nisrulz

    View Slide

  8. How does Gradle process
    Android Libraries
    implementation 'com/github/nisrulz/awesomelib/1.0'
    8
    @nisrulz

    View Slide

  9. How does Gradle process
    Android Libraries
    implementation 'com/github/nisrulz/awesomelib/1.0'
    9
    @nisrulz

    View Slide

  10. How does Gradle process
    Android Libraries
    implementation 'com/github/nisrulz/awesomelib/1.0'
    10
    @nisrulz

    View Slide

  11. How does Gradle process
    Android Libraries
    implementation 'com.github.nisrulz:awesomelib:1.0'
    11
    @nisrulz

    View Slide

  12. Android ARchive(AAR)
    @nisrulz 12

    View Slide

  13. 13
    @nisrulz

    View Slide

  14. 14
    @nisrulz

    View Slide

  15. AAR = Java ARchive(JAR) + Resources
    15
    @nisrulz

    View Slide

  16. AAR = Java ARchive(JAR) + Resources
    Sensey: https://github.com/nisrulz/sensey
    16
    @nisrulz

    View Slide

  17. AAR = Java ARchive(JAR) + Resources
    @nisrulz 17

    View Slide

  18. Sensey’s build.gradle
    dependencies {
    ...
    // Other testing dependencies
    // Transitive dependency: Support Compat library
    implementation "com.android.support:support-compat:27.0.2"
    }
    18
    @nisrulz

    View Slide

  19. Using AAR as dependency
    @nisrulz 19

    View Slide

  20. Using an AAR as dependency
    repositories{
    flatDir{
    dirs 'libs'
    }
    }
    dependencies {
    implementation(name:'nameOfYourAARFileWithoutExtension', ext:'aar')
    }
    @nisrulz 20

    View Slide

  21. Using an AAR as dependency
    repositories{
    flatDir{
    dirs 'libs'
    }
    }
    dependencies {
    implementation(name:'nameOfYourAARFileWithoutExtension', ext:'aar')
    }
    // No transitive dependencies of the library are downloaded
    21
    @nisrulz

    View Slide

  22. Why doesn’t my AAR
    download transitive
    dependencies?
    @nisrulz 22

    View Slide

  23. Sensey’s AAR
    23
    @nisrulz

    View Slide

  24. Sensey’s AAR
    No build.gradle file
    24
    @nisrulz

    View Slide

  25. Maven Artifact
    25
    @nisrulz

    View Slide

  26. Maven Artifact
    26
    @nisrulz

    View Slide

  27. POM?
    27
    @nisrulz

    View Slide

  28. POM
    ● Project Object Model
    ● XML file
    ● Configuration details used by Maven to build the project
    28
    @nisrulz

    View Slide

  29. POM
    POM of Sensey Android Library


    4.0.0
    com.github.nisrulzsensey1.8.0
    aarsensey
    Android library which makes playing with sensor events & detecting gestures a breeze.
    https://github.com/nisrulz/sensey


    The Apache Software License, Version 2.0http://www.apache.org/licenses/LICENSE-2.0.txt



    nisrulzNishant [email protected]


    https://github.com/nisrulz/sensey.git
    https://github.com/nisrulz/sensey.git
    https://github.com/nisrulz/sensey



    com.android.support
    support-compat27.0.2
    runtime


    ...



    29
    @nisrulz

    View Slide

  30. POM
    POM of Sensey Android Library


    4.0.0
    com.github.nisrulzsensey1.8.0
    aarsensey
    Android library which makes playing with sensor events & detecting gestures a breeze.
    https://github.com/nisrulz/sensey


    The Apache Software License, Version 2.0http://www.apache.org/licenses/LICENSE-2.0.txt



    nisrulzNishant [email protected]


    https://github.com/nisrulz/sensey.git
    https://github.com/nisrulz/sensey.git
    https://github.com/nisrulz/sensey



    com.android.support
    support-compat27.0.2
    runtime


    ...



    30
    @nisrulz

    View Slide

  31. POM
    POM of Sensey Android Library


    ...


    com.android.support
    support-compat27.0.2
    runtime


    ...



    31
    @nisrulz

    View Slide

  32. Bundled Proguard Configs
    32
    @nisrulz

    View Slide

  33. Bundled Proguard Configs
    android {
    release {
    minifyEnabled true
    // Rules to be used during the AAR generation
    proguardFiles 'proguard-rules-for-building-library.pro'
    }
    ...
    }
    33
    @nisrulz

    View Slide

  34. Bundled Proguard Configs
    android {
    release {
    minifyEnabled true
    // Rules to be used during the AAR generation
    proguardFiles 'proguard-rules-for-building-library.pro'
    // Rules appended to the integrating app
    consumerProguardFiles 'proguard-rules-for-using-library.pro'
    }
    ...
    }
    34
    @nisrulz

    View Slide

  35. Bundled Proguard Configs
    35
    @nisrulz

    View Slide

  36. Bundled Proguard Configs
    36
    @nisrulz

    View Slide

  37. Bundled Proguard Configs
    # Fuel’s bundled Proguard file
    # Without specifically keeping this class,
    # callbacks on android don't function properly.
    -keep class com.github.kittinunf.fuel.android.util.AndroidEnvironment
    37
    @nisrulz

    View Slide

  38. Bundled Proguard Configs
    # DON'T DO THIS
    # Do not obfuscate the input class files
    -dontobfuscate
    # Optimizes variable allocation on the local variable frame.
    -optimizations !code/allocation/variable
    # Preserved as entry points
    -keep public class * {
    public protected *;
    }
    38
    @nisrulz

    View Slide

  39. Bundled Proguard Configs
    # DON'T DO THIS
    # Adding the below in library proguard rules disables
    # the optimizations in the Android app
    -dontoptimize
    39
    @nisrulz

    View Slide

  40. Bundled Proguard Configs
    # To check the merged configuration
    # Add the below to your app’s current proguard rules
    -printconfiguration proguard-merged-config.txt
    40
    @nisrulz

    View Slide

  41. Bundled Proguard Configs
    41
    @nisrulz

    View Slide

  42. Modularization
    42
    @nisrulz

    View Slide

  43. Modularization
    43
    @nisrulz

    View Slide

  44. Modularization
    EasyDeviceInfo: https://github.com/nisrulz/easydeviceinfo
    44
    @nisrulz

    View Slide

  45. Modularization
    dependencies {
    def libVer = {latest_version}
    // Base + Ads Bundled Library
    implementation "com.github.nisrulz:easydeviceinfo:$libVer"
    // Base Library
    implementation "com.github.nisrulz:easydeviceinfo-base:$libVer"
    // Ads Library
    implementation "com.github.nisrulz:easydeviceinfo-ads:$libVer"
    }
    45
    @nisrulz

    View Slide

  46. Modularization


    ...


    com.github.nisrulz
    easydeviceinfo-ads 2.5.0
    compile


    com.github.nisrulz
    easydeviceinfo-base 2.5.0
    compile

    ...


    46
    @nisrulz

    View Slide

  47. Modularization


    ...


    com.github.nisrulz
    easydeviceinfo-ads 2.5.0
    compile


    com.github.nisrulz
    easydeviceinfo-base 2.5.0
    compile

    ...


    47
    @nisrulz

    View Slide

  48. Modularization


    ...


    com.github.nisrulz
    easydeviceinfo-ads 2.5.0
    compile


    com.github.nisrulz
    easydeviceinfo-base 2.5.0
    compile

    ...


    48
    @nisrulz

    View Slide

  49. Modularization


    ...


    com.github.nisrulz
    easydeviceinfo-common2.5.0
    compile


    com.google.android.gms
    play-services-ads-identifier16.0.0
    runtime

    ...


    49
    @nisrulz

    View Slide

  50. Modularization


    ...


    com.github.nisrulz
    easydeviceinfo-common2.5.0
    compile


    com.google.android.gms
    play-services-ads-identifier16.0.0
    runtime

    ...


    50
    @nisrulz

    View Slide

  51. Avoiding Resource Name
    Conflicts
    51
    @nisrulz

    View Slide

  52. Conflict occurs between a library & app resource
    > Project will not compile
    What happens when...
    52
    @nisrulz

    View Slide

  53. Conflict occurs between 2 libraries integrated in the app
    > Resources from library defined first in build.gradle gets
    included
    What happens when...
    53
    @nisrulz

    View Slide

  54. Solution?
    54
    @nisrulz

    View Slide

  55. Add a prefix to all your resources.
    Solution?
    55
    @nisrulz

    View Slide

  56. Add a prefix to all your resources.
    How?
    Solution?
    56
    @nisrulz

    View Slide

  57. Add a prefix to all your resources.
    How?
    ● Enforce this in Android Studio
    Solution?
    57
    @nisrulz

    View Slide

  58. Add a prefix to all your resources.
    How?
    ● Enforce this in Android Studio
    ● Declare in build.gradle of library
    android {
    resourcePrefix 'YOUR_PREFIX_' // i.e 'sensey_'
    }
    Solution?
    58
    @nisrulz

    View Slide

  59. Solution?
    Resource named ‘app_name’ does not start with the project’s
    resource prefix ‘sensey_’;
    Rename to `sensey_app_name`?
    59
    @nisrulz

    View Slide

  60. minSdkVersion Restriction
    60
    @nisrulz

    View Slide

  61. minSdkVersion of app >= minSdkVersion of library
    minSdk Restriction
    61
    @nisrulz

    View Slide

  62. minSdk Restriction
    62
    @nisrulz

    View Slide

  63. Manifest merger failed : uses-sdk:minSdkVersion 14 cannot be smaller
    than version 21 declared in library [:sensey]
    Suggestion:
    + Use a compatible library with a minSdk of at most 14
    + Increase this project's minSdk version to at least 21
    + Use tools:overrideLibrary="com.github.nisrulz.sensey" to force
    usage (may lead to runtime failures)
    minSdk Restriction
    63
    @nisrulz

    View Slide

  64. Manifest merger failed : uses-sdk:minSdkVersion 14 cannot be smaller
    than version 21 declared in library [:sensey]
    Suggestion:
    + Use a compatible library with a minSdk of at most 14
    + Increase this project's minSdk version to at least 21
    + Use tools:overrideLibrary="com.github.nisrulz.sensey" to force
    usage (may lead to runtime failures)
    minSdk Restriction
    64
    @nisrulz

    View Slide

  65. Manifest merger failed : uses-sdk:minSdkVersion 14 cannot be smaller
    than version 21 declared in library [:sensey]
    Suggestion:
    + Use a compatible library with a minSdk of at most 14
    + Increase this project's minSdk version to at least 21
    + Use tools:overrideLibrary="com.github.nisrulz.sensey" to force
    usage (may lead to runtime failures)
    minSdk Restriction
    65
    @nisrulz

    View Slide

  66. xmlns:tools="http://schemas.android.com/tools"
    package="com.github.nisrulz.senseysample">


    ...


    minSdk Restriction
    66
    @nisrulz

    View Slide

  67. xmlns:tools="http://schemas.android.com/tools"
    package="com.github.nisrulz.senseysample">


    ...


    minSdk Restriction
    67
    @nisrulz

    View Slide

  68. Access Visibility
    vs
    Code Organization
    68
    @nisrulz

    View Slide

  69. Visibility vs Organization
    69
    @nisrulz

    View Slide

  70. Visibility vs Organization
    ● Code organized in individual packages; everything is
    public
    70
    @nisrulz

    View Slide

  71. Visibility vs Organization
    ● Code organized inside one package; Classes and methods
    are package private and only public on demand
    71
    @nisrulz

    View Slide

  72. Visibility vs Organization
    ● Code organized inside the module i.e individual packages
    Classes and methods are internal and only public on
    demand (in Kotlin land)
    72
    @nisrulz

    View Slide

  73. Visibility vs Organization
    ● internal and only public on demand (in Kotlin land)
    73
    @nisrulz

    View Slide

  74. Visibility vs Organization
    ● Code organized inside the module i.e individual packages
    Classes and methods are internal and only public on
    demand (in Kotlin land)
    ● Drawback
    ○ Need dependency on kotlin std library
    74
    @nisrulz

    View Slide

  75. Lifecycle-Aware
    Android Library
    75
    @nisrulz

    View Slide

  76. Lifecycle Components
    Classes designed to help deal with Android
    lifecycle
    ● Lifecycle
    ● LifecycleOwner
    ● LifecycleObserver
    76
    @nisrulz

    View Slide

  77. Lifecycle Owner
    77
    @nisrulz

    View Slide

  78. Lifecycle Owner + Lifecycle
    78
    @nisrulz

    View Slide

  79. Lifecycle Owner + Lifecycle




    79
    @nisrulz

    View Slide

  80. Lifecycle Owner + Lifecycle
    class MainActivity extends AppCompatActivity() {...}
    80
    @nisrulz

    View Slide

  81. Lifecycle Owner + Lifecycle
    class MainActivity extends AppCompatActivity() {...}
    public class AppCompatActivity extends FragmentActivity{...}
    81
    @nisrulz

    View Slide

  82. Lifecycle Owner + Lifecycle
    class MainActivity extends AppCompatActivity() {...}
    public class AppCompatActivity extends FragmentActivity{...}
    public class FragmentActivity extends SupportActivity {...}
    82
    @nisrulz

    View Slide

  83. Lifecycle Owner + Lifecycle
    class MainActivity extends AppCompatActivity() {...}
    public class AppCompatActivity extends FragmentActivity{...}
    public class FragmentActivity extends SupportActivity {...}
    public class SupportActivity extends Activity implements LifecycleOwner,
    Component {
    ...
    public Lifecycle getLifecycle() {return this.mLifecycleRegistry();}
    ...
    }
    83
    @nisrulz

    View Slide

  84. Lifecycle Owner + Lifecycle
    class MainActivity extends AppCompatActivity() {...}
    public class AppCompatActivity extends FragmentActivity{...}
    public class FragmentActivity extends SupportActivity {...}
    public class SupportActivity extends Activity implements LifecycleOwner,
    Component {
    ...
    public Lifecycle getLifecycle() {return this.mLifecycleRegistry();}
    ...
    }
    84
    @nisrulz

    View Slide

  85. Lifecycle Observer
    85
    @nisrulz

    View Slide

  86. Lifecycle Observer
    86
    @nisrulz

    View Slide

  87. LifecycleObserver
    dependencies {
    def lifecycleVer = "2.0.0"
    // Runtime
    implementation "androidx.lifecycle:lifecycle-runtime:$lifecycleVer"
    // Annotation Support
    annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycleVer"
    ...
    }
    87
    @nisrulz

    View Slide

  88. LifecycleObserver
    public class AwesomeLib implements LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    public void init() { ... }
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public void libOnStart() { ... }
    ...
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    public void cleanup() { ... }
    }
    88
    @nisrulz

    View Slide

  89. LifecycleOwner
    class MainActivity : AppCompatActivity() {
    val awesomeLib = AwesomeLib()
    override fun onStart() {
    ...
    // Add lifecycle observer
    lifecycle.addObserver(awesomeLib)
    }
    override fun onStop() {
    ...
    // Remove lifecycle observer
    lifecycle.removeObserver(awesomeLib)
    }
    }
    89
    @nisrulz

    View Slide

  90. LifecycleAware Library
    90
    @nisrulz

    View Slide

  91. ProcessLifecycleOwner
    Class that tracks the lifecycle of
    whole application process
    91
    @nisrulz

    View Slide

  92. ProcessLifecycleOwner
    dependencies {
    // For ProcessLifecycleOwner
    implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
    ...
    }
    92
    @nisrulz

    View Slide

  93. ProcessLifecycleOwner
    Does something weird…
    93
    @nisrulz

    View Slide

  94. ProcessLifecycleOwner
    Does something weird…
    Adding lifecycle-extensions artifact
    > automatically adds element to the merged
    manifest
    94
    @nisrulz

    View Slide

  95. ProcessLifecycleOwner
    95
    @nisrulz

    View Slide

  96. ProcessLifecycleOwner


    ...
    android:name="androidx.lifecycle.ProcessLifecycleOwnerInitializer"
    android:authorities="com.example.app.lifecycle-process"
    android:exported="false"
    android:multiprocess="true" />


    96
    @nisrulz

    View Slide

  97. ProcessLifecycleOwner


    ...
    android:name="androidx.lifecycle.ProcessLifecycleOwnerInitializer"
    android:authorities="com.example.app.lifecycle-process"
    android:exported="false"
    android:multiprocess="true" />


    97
    @nisrulz

    View Slide

  98. ProcessLifecycleOwner


    ...
    android:name="android.arch.lifecycle.ProcessLifecycleOwnerInitializer"
    android:authorities="com.example.app.lifecycle-trojan"
    android:exported="false"
    android:multiprocess="true" />


    98
    @nisrulz
    Pre-AndroidX

    View Slide

  99. ProcessLifecycleOwner


    ...
    android:name="android.arch.lifecycle.ProcessLifecycleOwnerInitializer"
    android:authorities="com.example.app.lifecycle-trojan"
    android:exported="false"
    android:multiprocess="true" />


    99
    @nisrulz
    Pre-AndroidX

    View Slide

  100. ProcessLifecycleOwner
    100
    @nisrulz
    Pre-AndroidX

    View Slide

  101. ProcessLifecycleOwner


    ...
    android:name="androidx.lifecycle.ProcessLifecycleOwnerInitializer"
    android:authorities="com.example.app.lifecycle-process"
    android:exported="false"
    android:multiprocess="true" />


    101
    @nisrulz
    AndroidX

    View Slide

  102. ProcessLifecycleOwner


    ...
    android:name="androidx.lifecycle.ProcessLifecycleOwnerInitializer"
    android:authorities="com.example.app.lifecycle-process"
    android:exported="false"
    android:multiprocess="true" />


    102
    @nisrulz
    AndroidX

    View Slide

  103. ProcessLifecycleOwner
    // Internal class to initialize Lifecycles.
    public class ProcessLifecycleOwnerInitializer extends ContentProvider {
    @Override
    public boolean onCreate() {
    ...
    ProcessLifecycleOwner.init(getContext());
    return true;
    }
    ...
    }
    103
    @nisrulz

    View Slide

  104. ProcessLifecycleOwner
    Why?
    To invoke ProcessLifecycleOwner as soon as process
    starts
    104
    @nisrulz

    View Slide

  105. ProcessLifecycleOwner
    Why?
    To invoke ProcessLifecycleOwner as soon as process
    starts
    Drawback?
    Initializes ProcessLifecycleOwner even if your app
    does not use it!
    105
    @nisrulz

    View Slide

  106. ProcessLifecycleOwner
    How to get rid of it in app?
    106
    @nisrulz

    View Slide

  107. ProcessLifecycleOwner
    How to get rid of it in app?
    Use Merge rule marker in app’s AndroidManifest.xml:
    // Remove marked element from the merged manifest
    tools:node="remove"
    107
    @nisrulz

    View Slide

  108. ProcessLifecycleOwner

    ...
    android:name="androidx.lifecycle.ProcessLifecycleOwnerInitializer"
    android:authorities="${applicationId}.lifecycle-process"
    xmlns:tools="http://schemas.android.com/tools"
    tools:node="remove"
    />

    108
    @nisrulz
    App’s AndroidManifest.xml

    View Slide

  109. ProcessLifecycleOwner

    ...
    android:name="androidx.lifecycle.ProcessLifecycleOwnerInitializer"
    android:authorities="${applicationId}.lifecycle-process"
    xmlns:tools="http://schemas.android.com/tools"
    tools:node="remove"
    />

    109
    @nisrulz
    App’s AndroidManifest.xml

    View Slide

  110. ProcessLifecycleOwner

    ...
    android:name="androidx.lifecycle.ProcessLifecycleOwnerInitializer"
    android:authorities="${applicationId}.lifecycle-process"
    xmlns:tools="http://schemas.android.com/tools"
    tools:node="remove"
    />

    110
    @nisrulz
    App’s AndroidManifest.xml

    View Slide

  111. ProcessLifecycleOwner

    ...
    android:name="androidx.lifecycle.ProcessLifecycleOwnerInitializer"
    android:authorities="${applicationId}.lifecycle-process"
    xmlns:tools="http://schemas.android.com/tools"
    tools:node="remove"
    />

    111
    @nisrulz
    App’s AndroidManifest.xml

    View Slide

  112. Auto Initialize
    Android Library
    112
    @nisrulz

    View Slide

  113. AutoInit Android Library
    Android Libraries need Android context to handle simple tasks such as
    ● Hook into Android Runtime
    ● Access app resources
    ● Use System Services
    ● Register BroadcastReceiver
    113
    @nisrulz

    View Slide

  114. AutoInit Android Library
    public class MyApplication extends Application {
    @Override
    public void onCreate() {
    super.onCreate();
    // Init android library
    AwesomeLib.getInstance().init(this);
    }
    }
    114
    @nisrulz

    View Slide

  115. AutoInit Android Library
    public class MyApplication extends Application {
    @Override
    public void onCreate() {
    super.onCreate();
    // Init android library
    AwesomeLib.getInstance().init(this);
    }
    }
    115
    @nisrulz

    View Slide

  116. AutoInit Android Library
    public class MyApplication extends Application {
    @Override
    public void onCreate() {
    super.onCreate();
    // Init android library
    AwesomeLib.getInstance().init(this);
    }
    }
    116
    @nisrulz

    View Slide

  117. AutoInit Android Library
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:name=".MyApplication"
    ... >
    117
    @nisrulz

    View Slide

  118. AutoInit Android Library
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:name=".MyApplication"
    ... >
    118
    @nisrulz

    View Slide

  119. AutoInit Android Library
    ContentProvider can be used to simplify the process.
    119
    @nisrulz

    View Slide

  120. AutoInit Android Library
    ContentProvider can be used to simplify the process.
    Simply because ContentProvider
    ● Is created and initialized (on the main thread)
    before all other components
    ● Participate in manifest merging at build time.
    120
    @nisrulz

    View Slide

  121. AutoInit Android Library
    public class AwesomeLibInitProvider extends ContentProvider {
    ...
    @Override
    public boolean onCreate() {
    // get the context (Application context)
    Context context = getContext();
    // initialize AwesomeLib here
    AwesomeLib.getInstance().init(context);
    return false;
    }
    ...
    }
    121
    @nisrulz

    View Slide

  122. AutoInit Android Library
    public class AwesomeLibInitProvider extends ContentProvider {
    ...
    @Override
    public boolean onCreate() {
    // get the context (Application context)
    Context context = getContext();
    // initialize AwesomeLib here
    AwesomeLib.getInstance().init(context);
    return false;
    }
    ...
    }
    122
    @nisrulz

    View Slide

  123. AutoInit Android Library
    package="github.nisrulz.sample.awesomelib">

    android:name=".AwesomeLibInitProvider"
    android:authorities="${applicationId}.awesomelibinitprovider"
    android:enabled="true"
    android:exported="false"/>


    123
    @nisrulz

    View Slide

  124. AutoInit Android Library
    package="github.nisrulz.sample.awesomelib">

    android:name=".AwesomeLibInitProvider"
    android:authorities="${applicationId}.awesomelibinitprovider"
    android:enabled="true"
    android:exported="false"/>


    124
    @nisrulz

    View Slide

  125. AutoInit Android Library
    package="github.nisrulz.sample.awesomelib">

    android:name=".AwesomeLibInitProvider"
    android:authorities="${applicationId}.awesomelibinitprovider"
    android:enabled="true"
    android:exported="false"/>


    125
    @nisrulz

    View Slide

  126. AutoInit Android Library
    package="github.nisrulz.sample.awesomelib">

    android:name=".AwesomeLibInitProvider"
    android:authorities="${applicationId}.awesomelibinitprovider"
    android:enabled="true"
    android:exported="false"/>


    126
    @nisrulz

    View Slide

  127. AutoInit Android Library
    ContentProvider can be used to simplify the process.
    127
    @nisrulz

    View Slide

  128. AutoInit Android Library
    ContentProvider can be used to simplify the process.
    Challenges:
    ● There can be only one Content Provider with a given
    “authority” string
    ● Only run on main thread
    128
    @nisrulz

    View Slide

  129. AutoInit Android Library
    ContentProvider can be used to simplify the process.
    129
    @nisrulz

    View Slide

  130. AutoInit Android Library
    ContentProvider can be used to simplify the process.
    Why this is a bad idea:
    ● Increases startup time
    ● Bloats applications even when not used
    ● Abusing functionality of ContentProvider
    130
    @nisrulz

    View Slide

  131. AutoInit Android Library
    ContentProvider can be used to simplify the process.
    Why this is a bad idea:
    ● Increases startup time (Solution: async initialize)
    ● Bloats applications even when not used
    ● Abusing functionality of ContentProvider
    131
    @nisrulz

    View Slide

  132. AutoInit Android Library
    Some android libraries that use this...
    132
    @nisrulz

    View Slide

  133. AutoInit Android Library
    ProcessLifecycleOwner
    [androidx.lifecycle:lifecycle-extensions:2.0.0]

    android:name="androidx.lifecycle.ProcessLifecycleOwnerInitializer"
    android:authorities="${applicationId}.lifecycle-process"
    android:exported="false"
    android:multiprocess="true" />

    133
    @nisrulz

    View Slide

  134. AutoInit Android Library
    Firebase
    [com.google.firebase:firebase-common:16.0.5]

    android:name="com.google.firebase.provider.FirebaseInitProvider"
    android:authorities="${applicationId}.firebaseinitprovider"
    android:exported="false"
    android:initOrder="100" />

    134
    @nisrulz

    View Slide

  135. AutoInit Android Library
    Facebook-Core
    [com.facebook.android:facebook-core:4.34.0]

    android:name="com.facebook.internal.FacebookInitProvider"
    android:authorities="${applicationId}.FacebookInitProvider"
    android:exported="false" />

    135
    @nisrulz

    View Slide

  136. AutoInit Android Library
    Facebook-Marketing
    [com.facebook.android:facebook-marketing:4.34.0]

    android:name="com.facebook.marketing.internal.MarketingInitProvider"
    android:authorities="${applicationId}.MarketingInitProvider"
    android:exported="false" />

    136
    @nisrulz

    View Slide

  137. AutoInit Android Library
    Crashlytics
    [com.crashlytics.sdk.android:crashlytics:2.9.5]

    android:name="com.crashlytics.android.CrashlyticsInitProvider"
    android:authorities="${applicationId}.crashlyticsinitprovider"
    android:exported="false"
    android:initOrder="90" />

    137
    @nisrulz

    View Slide

  138. AutoInit Android Library
    Picasso
    // Pre - v2.71828
    Picasso.with(this).load("......").into(imageView);
    // After - v2.71828
    Picasso.get().load("......").into(imageView);
    138
    @nisrulz

    View Slide

  139. AutoInit Android Library
    Picasso
    // Pre - v2.71828
    Picasso.with(this).load("......").into(imageView);
    // After - v2.71828
    Picasso.get().load("......").into(imageView);
    139
    @nisrulz

    View Slide

  140. AutoInit Android Library
    Picasso
    [com.squareup.picasso:picasso:2.71828]

    android:name=".PicassoContentProvider"
    android:authorities="${applicationId}.com.squareup.picasso3"
    android:exported="false"/>

    140
    @nisrulz

    View Slide

  141. Links/References
    Android Libraries I have built:
    https://github.com/nisrulz/nisrulz.github.io#open-source-co
    ntributions
    Auto initialize android library example:
    https://github.com/nisrulz/android-examples/tree/develop/Au
    toInitLibrary
    Lifecycle Aware android library example:
    https://github.com/nisrulz/android-examples/tree/develop/Li
    feCycleCompForLib
    141
    @nisrulz

    View Slide

  142. 142
    twitter.com/nisrulz
    github.com/nisrulz
    www.nisrulz.com

    View Slide

  143. twitter.com/nisrulz
    github.com/nisrulz
    www.nisrulz.com
    143

    View Slide