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

Build.Better.­Android.Libraries

 Build.Better.­Android.Libraries

As more and more people start building Android Libraries, the whole process of building a better API for developers is getting bloated and everyone is coming up with their own ideas. However, if android library developers follow a certain standard with a rationale they can avoid most of the pitfalls. Building an android library is easy, but building one that keeps in mind developer happiness is rare but definitely not hard. The session would cover how one can build android libraries taking in consideration to exposing more informative API, making sure the best resources are utilized efficiently and that one does not force the app developer with redundant dependencies and complexities.

Working Gif Version: https://goo.gl/HQFX7n

Nishant Srivastava

April 25, 2017
Tweet

More Decks by Nishant Srivastava

Other Decks in Technology

Transcript

  1. Build.Better.
    Android.Libraries
    Nishant Srivastava
    @nisrulz

    View full-size slide

  2. About me
    Nishant Srivastava
    Software Engineer/Founding Team Member (at)
    Omni Labs, Inc.
    Lead Organizer (at) GDG, New Delhi, India
    Open Source enthusiast
    @nisrulz

    View full-size slide

  3. Before we begin...
    @nisrulz

    View full-size slide

  4. What
    Is an Android Library?
    @nisrulz

    View full-size slide

  5. Android Library is...
    ...simply put, pre-written reusable logic in
    code, for android apps...
    @nisrulz

    View full-size slide

  6. Android Library is...
    ...simply put, pre-written reusable logic in
    code, for android apps...
    @nisrulz

    View full-size slide

  7. Android Library is...
    Java code
    +

    +

    =
    @nisrulz

    View full-size slide

  8. Android Library is...
    Java code
    +
    android resources
    +

    =
    @nisrulz

    View full-size slide

  9. Android Library is...
    Java code
    +
    android resources
    +
    android manifest stub
    =
    @nisrulz

    View full-size slide

  10. Android Library is...
    Java code
    +
    android resources
    +
    android manifest stub
    =
    Android
    ARchive
    (AAR)
    @nisrulz

    View full-size slide

  11. Why
    create an Android Library?
    @nisrulz

    View full-size slide

  12. Why create an Android Library?
    Short Answer
    @nisrulz

    View full-size slide

  13. Why create an Android Library?
    Short Answer
    You don’t have to
    @nisrulz

    View full-size slide

  14. Why create an Android Library?
    Short Answer
    You don’t have to
    @nisrulz
    If a solution already exists, use it

    View full-size slide

  15. Best Practices
    for building android libraries...
    @nisrulz
    ...with that, let us move on to

    View full-size slide

  16. Ease of use
    Intuitive
    @nisrulz

    View full-size slide

  17. Ease of use
    Intuitive
    ○ It should do what the user of android library expects it to
    do without having to look up the documentation.
    @nisrulz

    View full-size slide

  18. Ease of use
    Intuitive
    ○ It should do what the user of android library expects it to
    do without having to look up the documentation.
    Consistent
    @nisrulz

    View full-size slide

  19. Ease of use
    Intuitive
    ○ It should do what the user of android library expects it to
    do without having to look up the documentation.
    Consistent
    ○ The code for the android library should be well thought and
    should not change drastically between versions
    @nisrulz

    View full-size slide

  20. Ease of use
    Intuitive
    ○ It should do what the user of android library expects it to
    do without having to look up the documentation.
    Consistent
    ○ The code for the android library should be well thought and
    should not change drastically between versions
    Easy to use, hard to misuse
    @nisrulz

    View full-size slide

  21. Ease of use
    Intuitive
    ○ It should do what the user of android library expects it to
    do without having to look up the documentation.
    Consistent
    ○ The code for the android library should be well thought and
    should not change drastically between versions
    Easy to use, hard to misuse
    ○ Validation checks, sane defaults, handle errors
    @nisrulz

    View full-size slide

  22. Avoid multiple arguments
    @nisrulz

    View full-size slide

  23. Avoid multiple arguments
    // Do not DO this
    void init(String apikey, int refresh, long interval, String type, String username, String
    email, String password);
    @nisrulz

    View full-size slide

  24. Avoid multiple arguments
    // Do not DO this
    void init(String apikey, int refresh, long interval, String type, String username, String
    email, String password);
    @nisrulz
    // WHY?

    View full-size slide

  25. Avoid multiple arguments
    // Do not DO this
    void init(String apikey, int refresh, long interval, String type, String username, String
    email, String password);
    @nisrulz
    // WHY?
    void init(“0123456789”, true, 1000, “prod”, “nishant”, ”1234”, “[email protected]”);

    View full-size slide

  26. Avoid multiple arguments
    // Do not DO this
    void init(String apikey, int refresh, long interval, String type, String username, String
    email, String password);
    @nisrulz
    // WHY?
    void init(“0123456789”, true, 1000, “prod”, “nishant”, ”1234”, “[email protected]”);
    // Easy to mess up things here :(

    View full-size slide

  27. Avoid multiple arguments
    // Do not DO this
    void init(String apikey, int refresh, long interval, String type, String username, String
    email, String password);
    @nisrulz
    // DO this
    void init(ApiSecret apisecret);

    View full-size slide

  28. // where ApiSecret
    public class ApiSecret{
    String apikey;
    int refresh;
    long interval;
    String type;
    String name;
    String email;
    String pass;
    // constructor
    /* you can define proper checks(such as type safety) and
    * conditions to validate data before it gets set
    */
    // setter and getters
    }
    @nisrulz

    View full-size slide

  29. Avoid multiple arguments
    // Do not DO this
    boolean init(String apikey, int refresh, long interval, String type, String username,
    String email, String password);
    @nisrulz
    // DO this
    boolean init(ApiSecret apisecret);
    // Or use a Builder Pattern

    View full-size slide

  30. // Builder Pattern
    AwesomeLib awesomelib = new
    AwesomeLib.AwesomeLibBuilder()
    .apisecret(mApisecret)
    .refresh(mRefresh)
    .interval(mInterval)
    .type(mType)
    .username(mUsername)
    .email(mEmail)
    .password(mPassword)
    .build();
    }
    @nisrulz

    View full-size slide

  31. Minimize Permissions
    Use Intents
    @nisrulz

    View full-size slide

  32. Minimize Permissions
    Use Intents
    ○ Let dedicated apps do the work for you.
    @nisrulz

    View full-size slide

  33. Minimize Permissions
    Use Intents
    ○ Let dedicated apps do the work for you.
    Reduce the no. of permissions
    @nisrulz

    View full-size slide

  34. Minimize Permissions
    Use Intents
    ○ Let dedicated apps do the work for you.
    Reduce the no. of permissions
    Check for permission, use fallbacks
    @nisrulz

    View full-size slide

  35. Minimize Permissions
    Use Intents
    ○ Let dedicated apps do the work for you.
    Reduce the no. of permissions
    Check for permission, use fallbacks
    ○ public boolean hasPermission(Context context, String permission) {
    int result = context.checkCallingOrSelfPermission(permission);
    return result == PackageManager.PERMISSION_GRANTED;
    }
    @nisrulz

    View full-size slide

  36. Minimize Requisites
    // Do not do this

    @nisrulz

    View full-size slide

  37. Minimize Requisites
    // Do not do this

    // Use this
    String feature = PackageManager.FEATURE_BLUETOOTH;
    public boolean isFeatureAvailable(Context context, String feature) {
    return context.getPackageManager().hasSystemFeature(feature);
    }
    @nisrulz

    View full-size slide

  38. Minimize Requisites
    // Do not do this

    // Use this
    String feature = PackageManager.FEATURE_BLUETOOTH;
    public boolean isFeatureAvailable(Context context, String feature) {
    return context.getPackageManager().hasSystemFeature(feature);
    }
    // Enable/Disable the functionality dependent on the
    // feature as per requirement
    @nisrulz

    View full-size slide

  39. Support different versions
    /* RULE OF THUMB : Support the full spectrum of android
    * versions
    */
    @nisrulz

    View full-size slide

  40. Support different versions
    /* RULE OF THUMB : Support the full spectrum of android
    * versions
    */
    android {
    ...
    defaultConfig {
    ..
    minSdkVersion 9
    targetSdkVersion 25
    ..
    }
    }
    @nisrulz

    View full-size slide

  41. Support different versions
    /* RULE OF THUMB : Enable/Disable features or use a fallback
    * based on detected version
    */
    @nisrulz

    View full-size slide

  42. Support different versions
    /* RULE OF THUMB : Enable/Disable features or use a fallback
    * based on detected version
    */
    // Method to check if the Android Version on the device is greater than or equal to
    Marshmallow.
    public boolean isMarshmallow(){
    return Build.VERSION.SDK_INT>= Build.VERSION_CODES.M;
    }
    @nisrulz

    View full-size slide

  43. Do not log in production
    @nisrulz

    View full-size slide

  44. Do not log in production
    @nisrulz
    ...just Don’t. Seriously don’t.

    View full-size slide

  45. Do not log in production
    Use Build Variants
    @nisrulz

    View full-size slide

  46. Do not log in production
    Use Build Variants
    Flagged Logging
    @nisrulz

    View full-size slide

  47. Do not log in production
    Use Build Variants
    Flagged Logging
    ○ MyAwesomeLibrary.init(apisecret,BuildConfig.DEBUG);
    @nisrulz

    View full-size slide

  48. Do not log in production
    Use proguard
    // add to your proguard file
    -assumenosideeffects class android.util.Log {
    public static boolean isLoggable(java.lang.String, int);
    public static int v(...);
    public static int i(...);
    public static int w(...);
    public static int d(...);
    public static int e(...);
    }
    @nisrulz

    View full-size slide

  49. Do not log in production
    Use proguard
    // enable proguard in build.gradle, switch to proguard-android-optimize
    .txt
    android {
    ...
    buildTypes {
    release {
    ...
    minifyEnabled false
    proguardFiles getDefaultProguardFile('proguard-android-optimize
    .txt'), 'proguard-rules.pro'
    }
    }
    }
    @nisrulz

    View full-size slide

  50. … we do not want this to happen!
    @nisrulz

    View full-size slide

  51. Do not crash silently and
    fail fast
    @nisrulz
    Log Errors and Exception

    View full-size slide

  52. // Provide flexibility to log when debug flag is true
    void init(ApiSecret apisecret,boolean debuggable){
    ...
    try{
    ...
    } catch(Exception ex){
    If (debuggable){
    // This is printed only when debuggable is true
    ex.printStackTrace();
    }
    }
    ....
    }
    @nisrulz

    View full-size slide

  53. Degrade gracefully in an
    event of an error
    @nisrulz
    Don’t crash the app,
    Disable functionality

    View full-size slide

  54. Catch specific exception
    @nisrulz
    // Do not do this
    try {
    // ...
    } catch(Exception e) {
    // ...
    }

    View full-size slide

  55. Catch specific exception
    @nisrulz
    // Do this
    try {
    // ...
    } catch(NullpointerException e) {
    // ...
    }

    View full-size slide

  56. Handle poor network
    conditions
    @nisrulz

    View full-size slide

  57. Handle poor network
    conditions
    1. Prepare for unreliable/flaky network conditions
    @nisrulz

    View full-size slide

  58. Handle poor network
    conditions
    1. Prepare for unreliable/flaky network conditions
    2. Batch your network calls
    @nisrulz

    View full-size slide

  59. Handle poor network
    conditions
    1. Prepare for unreliable/flaky network conditions
    2. Batch your network calls
    3. Prefetch data ahead of time
    @nisrulz

    View full-size slide

  60. Handle poor network
    conditions
    1. Prepare for unreliable/flaky network conditions
    2. Batch your network calls
    3. Prefetch data ahead of time
    4. Replace JSON/XML with flatbuffers
    @nisrulz

    View full-size slide

  61. Handle poor network
    conditions
    1. Prepare for unreliable/flaky network conditions
    2. Batch your network calls
    3. Prefetch data ahead of time
    4. Replace JSON/XML with flatbuffers
    @nisrulz

    View full-size slide

  62. Reluctance to include large
    libraries as dependencies
    @nisrulz

    View full-size slide

  63. Reluctance to include large
    libraries as dependencies
    WHY ?
    @nisrulz

    View full-size slide

  64. Reluctance to include large
    libraries as dependencies
    WHY ?
    Methods Counts!
    @nisrulz

    View full-size slide

  65. Do not require dependencies
    unless you very much have to
    Avoid bloating the library with dependencies
    @nisrulz

    View full-size slide

  66. Do not require dependencies
    unless you very much have to
    Get the developer to provide you those dependencies
    @nisrulz

    View full-size slide

  67. Do not require dependencies
    unless you very much have to
    Get the developer to provide you those dependencies
    dependencies {
    // for gradle version 2.12 and below
    provided 'com.squareup.okhttp3:okhttp:3.7.0'
    // or for gradle version 2.12+
    compileOnly 'com.squareup.okhttp3:okhttp:3.7.0'
    }
    @nisrulz

    View full-size slide

  68. Do not require dependencies
    unless you very much have to
    Enable/disable features based on availability of dependency
    @nisrulz

    View full-size slide

  69. Do not require dependencies
    unless you very much have to
    Enable/disable features based on availability of dependency
    private boolean hasOKHttpOnClasspath() {
    try {
    Class.forName("com.squareup.okhttp3.OkHttpClient");
    return true;
    } catch (ClassNotFoundException ex) {
    ex.printStackTrace();
    }
    return false;
    }
    @nisrulz

    View full-size slide

  70. Try not to hog the startup
    @nisrulz

    View full-size slide

  71. Try not to hog the startup
    @nisrulz

    View full-size slide

  72. Remove features and
    functionalities gracefully
    @nisrulz

    View full-size slide

  73. Remove features and
    functionalities gracefully
    Mark @Deprecated before removing a public API

    View full-size slide

  74. Make your code
    testable
    @nisrulz

    View full-size slide

  75. Document Everything!
    @nisrulz

    View full-size slide

  76. Document Everything!
    1. Create a Readme.md file
    @nisrulz

    View full-size slide

  77. Document Everything!
    1. Create a Readme.md file
    2. Have Javadoc comments
    @nisrulz

    View full-size slide

  78. Document Everything!
    1. Create a Readme.md file
    2. Have Javadoc comments
    3. Bundle a sample app
    @nisrulz

    View full-size slide

  79. Document Everything!
    1. Create a Readme.md file
    2. Have Javadoc comments
    3. Bundle a sample app
    4. Keep a detailed changelog of releases
    @nisrulz

    View full-size slide

  80. Document Everything!
    @nisrulz

    View full-size slide

  81. Provide a most minimalistic
    sample app
    @nisrulz

    View full-size slide

  82. Consider putting up a license
    @nisrulz
    https://choosealicense.com/

    View full-size slide

  83. Get feedback, lots of them
    @nisrulz

    View full-size slide

  84. As a rule of thumb follow the rule of SPOIL-ing your Library
    Simple — Briefly and Clearly expressed
    Purposeful — Having or showing resolve
    Opensource — Universal Access, Free license
    Idiomatic — Natural to the native environment
    Logical — Clear, Sound Reasoning
    @nisrulz

    View full-size slide

  85. References
    BlogPost:
    https://android.jlelse.eu/things-i-wish-i-knew-when-i-started-bu
    ilding-android-sdk-libraries-dba1a524d619
    Open Source android libraries I have made:
    https://github.com/nisrulz/nisrulz.github.io#android-librariessdk
    @nisrulz

    View full-size slide

  86. Thank You
    Questions?
    @nisrulz

    View full-size slide