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

Building Android SDK

Building Android SDK

Presented at,
- "GoogleIO 2017 Extended" Event in Mumbai hosted by MADMeetup
- Meetup hosted by GDG Toronto Android https://www.meetup.com/toandroiddev/events/250883174/

Jigar Brahmbhatt

May 17, 2017
Tweet

More Decks by Jigar Brahmbhatt

Other Decks in Programming

Transcript

  1. Building
    Android SDK/Library
    Jigar Brahmbhatt
    @jabbar_jigariyo

    View Slide

  2. Importance of tech talks
    Conferences/Meetups are not about
    teaching specifics, but all about
    inspiring and enlightening others
    about a topic
    At work, one may find a guide or
    mentor, but at the end everything
    depends on self-learning
    2

    View Slide

  3. Why build an SDK?
    3

    View Slide

  4. Why build an SDK?
    To build a product around it
    A paid SDK or an open-sourced library
    4

    View Slide

  5. 5
    To make your code re-usable/modular
    Thinking in terms of SDK design tends to improve quality of
    program that you write
    To build a product around it
    Why build an SDK?

    View Slide

  6. Characteristics of a good SDK
    6
    Reference:
    How To Design A Good API and Why it Matters
    - Joshua Bloch
    - https://www.youtube.com/watch?v=heh4OeB9A-c

    View Slide

  7. Characteristics of a good SDK
    7
    Easy to use, even without documentation

    View Slide

  8. Characteristics of a good SDK
    8
    Fabric.with(context, new Crashlytics());
    Easy to use, even without documentation

    View Slide

  9. Characteristics of a good SDK
    9
    Picasso.with(context)
    .load(“http://i.imgur.com/DvpvklR.png")
    .into(imageView);
    Easy to use, even without documentation

    View Slide

  10. Characteristics of a good SDK
    10
    Must have great documentation!

    View Slide

  11. Characteristics of a good SDK
    11
    Difficult to misuse!

    View Slide

  12. Characteristics of a good SDK
    12
    ‣ Methods taking int or null values
    ‣ Should I init on main thread or worker thread?
    ‣ Ask client to have your declarations in their manifest
    ‣ Encapsulation is not just for theory
    Difficult to misuse!

    View Slide

  13. Characteristics of a good SDK
    13
    Difficult to misuse!
    return Collections.unmodifiableList(list);
    return list;
    ‣ Methods taking int or null values
    ‣ Should I init on main thread or worker thread?
    ‣ Ask client to have your declarations in their manifest
    ‣ Encapsulation is not just for theory

    View Slide

  14. 14
    @MainThread
    @WorkerThread
    @AnyThread
    @NonNull
    @IntDef, @StringDef
    Fail fast (Exceptions)
    @LayoutRes,
    @StringRes, etc
    @RequiresPermission,
    @RequiresApi
    @IntRange, @FloatRange
    Characteristics of a good SDK
    Difficult to misuse!

    View Slide

  15. 15
    Characteristics of a good SDK
    Easy to read and maintain for users

    View Slide

  16. 16
    try {

    return xyzAPI.init(context);

    } catch (PermissionsNotSatisfied ignored) {

    }
    Characteristics of a good SDK
    Easy to read and maintain for users

    View Slide

  17. 17
    ImageLoadingOptions imageLoadingOptions = new ImageLoadingOptions
    .Builder()

    .load(url)

    .diskCacheStrategy(DiskCacheStrategy.SOURCE)

    .build();

    ImageLoader.downloadInto(iv_optionIcon, imageLoadingOptions);
    Characteristics of a good SDK
    Easy to read and maintain for users

    View Slide

  18. 18
    ImageLoadingOptions imageLoadingOptions = new ImageLoadingOptions
    .Builder()

    .load(url)

    .diskCacheStrategy(DiskCacheStrategy.SOURCE)

    .build();

    ImageLoader.downloadInto(iv_optionIcon, url);
    Characteristics of a good SDK
    Easy to read and maintain for users

    View Slide

  19. 19
    Characteristics of a good SDK
    Use popular patterns!
    Take reference from popular SDKs!

    View Slide

  20. 20
    Characteristics of a good SDK
    ‣ Builder Pattern for initialization, config etc
    ‣ Fluent interfaces
    ‣ Allows values like keys to be set via manifest metadata
    ‣ Create extendable APIs for more advanced control
    ‣ Provider both sync and async versions of methods, if
    applicable
    Use popular patterns!

    View Slide

  21. 21
    Characteristics of a good SDK
    Solid sample code/application!
    Very very important!

    View Slide

  22. 22
    Characteristics of a good SDK
    Method counts
    Hurts Android specifically!

    View Slide

  23. 23
    Characteristics of a good SDK
    Method counts
    23
    ‣ Proguard
    ‣ Java Synthetic Method
    ‣ Libraries which your library uses
    Exploring Java's Hidden Cost
    - Jake Wharton
    - https://www.youtube.com/watch?v=WALV33rWye4

    View Slide

  24. Misc Tips!

    View Slide

  25. 25
    Solid beginning is necessary

    View Slide

  26. 26
    ‣ No need to create full fledged first version
    ‣ Get core functionality/architecture VERY right
    ‣ Tip: Start your process with 2-3 page of top level
    documentation and get it validated
    ‣ Should be easy to evolve
    Solid beginning is necessary

    View Slide

  27. 27
    Define state of objects
    passed to/returned from
    library methods
    Reference:
    The Mutable State Monster and How to Defeat it
    - Anup Cowkur
    - https://www.youtube.com/watch?v=lE9XnvBV-ys

    View Slide

  28. 28
    Define state of objects
    passed to/returned from
    library methods
    @MainThread

    public void signUp(@NonNull User user, Callback callback)
    {

    Validate.notNull(user, "user");

    .............

    Auth.signUp(user, userCallback);

    }

    View Slide

  29. 29
    Define state of objects
    passed to/returned from
    library methods
    @MainThread

    public void signUp(@NonNull User user, Callback callback)
    {

    Validate.notNull(user, "user");

    .............

    Auth.signUp(user, userCallback);

    }
    What if client change this user in middle of something?

    View Slide

  30. 30
    Define state of objects
    passed to/returned from
    library methods
    @MainThread

    public void signUp(@NonNull User user, Callback callback)
    {

    Validate.notNull(user, "user");

    .............

    Auth.signUp(new User.Builder(user).build(), callback);

    }

    View Slide

  31. Use interface type in an API
    instead of implementation type
    (Can’t stress enough)

    View Slide

  32. Use interface type in an API
    instead of implementation type
    sendEvent(HashMap events)

    View Slide

  33. Use interface type in an API
    instead of implementation type
    sendEvent(HashMap events)
    sendEvent(HashMap events)

    View Slide

  34. Use interface type in an API
    instead of implementation type
    sendEvent(Map events)
    sendEvent(HashMap events)
    sendEvent(HashMap events)

    View Slide

  35. Use interface type in an API
    instead of implementation type
    setTextToAView(String text)

    View Slide

  36. Use interface type in an API
    instead of implementation type
    setTextToAView(String text)
    setTextToAView(CharSequence text)

    View Slide

  37. Resource Prefix

    View Slide

  38. Resource Prefix
    ‣ Remember resources like abc_actionbar_etc_etc?
    ‣ Prefix your resources to save from potential issues
    or misuse after manifest merger
    ‣ Utilize power of Gradle!

    View Slide

  39. Resource Prefix
    ‣ Remember resources like abc_actionbar_etc_etc?
    ‣ Prefix your resources to save from potential issues
    or misuse after manifest merger
    ‣ Utilize power of Gradle!
    android {

    resourcePrefix 'haptik_'

    }

    View Slide

  40. Resource Prefix
    ‣ Remember resources like abc_actionbar_etc_etc?
    ‣ Prefix your resources to save from potential issues
    or misuse after manifest merger
    ‣ Utilize power of Gradle!
    android {

    resourcePrefix 'haptik_'

    }

    View Slide

  41. Use ${applicationId} without fail

    View Slide

  42. Use ${applicationId} without fail
    android:authorities="${applicationId}.haptiklib.fileprovider"

    android:exported="false"

    android:grantUriPermissions="true">

    android:resource="@xml/yourlib_provider_paths" />


    View Slide

  43. Use ${applicationId} without fail

    android:protectionLevel="signature" />

    View Slide

  44. consumerProguardFiles

    View Slide

  45. consumerProguardFiles
    consumerProguardFiles 'proguard-consumer-rules.txt'
    Add our proguard rules in your proguard file

    View Slide

  46. consumerProguardFiles
    consumerProguardFiles 'proguard-consumer-rules.txt'

    View Slide

  47. Beware of default variant
    https://developer.android.com/studio/projects/android-library.html#publish_multiple_variants

    View Slide

  48. Be cautious about permissions

    View Slide

  49. Be cautious about permissions
    ‣ Make sure you’re not adding permissions for client
    app without clearly specifying
    ‣ Make sure your lib’s third party dependencies don’t
    add extra unnecessary permissions
    ‣ Analyze manifest of final APK via AndroidStudio
    ‣ Force remove if not necessary
    android:name="android.permission.USE_CREDENTIALS"

    tools:node="remove" />

    View Slide

  50. It’s DIFFICULT to build a solid SDK!

    View Slide

  51. It’s DIFFICULT to build a solid SDK!
    Expect to see mistakes after release

    View Slide

  52. Thank you
    Twitter: @jabbar_jigariyo

    View Slide

  53. View Slide