$30 off During Our Annual Pro Sale. View Details »

Building the Fabric SDKs - #MBLTDev (30 min)

Ty Smith
October 28, 2014

Building the Fabric SDKs - #MBLTDev (30 min)

Ty Smith

October 28, 2014
Tweet

More Decks by Ty Smith

Other Decks in Programming

Transcript

  1. dev.twitter.com @tsmith
    Building the Fabric SDKs
    Ty Smith
    Sr. Android Engineer

    View Slide

  2. View Slide

  3. View Slide

  4. View Slide

  5. View Slide

  6. Fabric Sample App
    Cannonball
    Open source for iOS & Android:
    github.com/twitterdev

    View Slide

  7. Powerful
    Lightweight

    View Slide

  8. Powerful

    View Slide

  9. Ease of
    Integration

    View Slide

  10. Ease of Integration
    Fabric.with(this, new Crashlytics());

    View Slide

  11. Extensible

    View Slide

  12. Extensible
    Crashlytics.start(this);

    View Slide

  13. Extensible
    Crashlytics.start(this, 5);
    Crashlytics.setListener(createCrashlyticsListener());
    Crashlytics.setPinningInfo(createPinningInfoProvider())
    Crashlytics.getInstance().setDebugMode(true);

    View Slide

  14. Extensible
    Crashlytics.setListener(createCrashlyticsListener());
    Crashlytics.setPinningInfo(createPinningInfoProvider());
    Crashlytics.getInstance().setDebugMode(true);
    Crashlytics.start(this, 5);

    View Slide

  15. Extensible
    Crashlytics.start(this, delay, listener, pinningInfo,
    debugMode);

    View Slide

  16. Extensible
    Crashlytics.start(this, 0, null, null, null, true);

    View Slide

  17. Fluent Pattern
    Crashlytics crashlytics = new Crashlytics.Builder()
    .delay(1)
    .listener(createCrashlyticsListener())
    .pinningInfo(createPinningInfoProvider())
    .build();
    Fabric.with(this, crashlytics);

    View Slide

  18. Fluent Pattern
    Fabric.with(new Fabric.Builder(this)
    .kits(new Crashlytics())
    .debuggable(true)
    .logger(new DefaultLogger(Log.VERBOSE))
    .looper(getCustomLooper())
    .executor(getCustomExecutorService())
    .build());

    View Slide

  19. Extensible Classes
    class MyApiClient extends TwitterApiClient {
    interface MyService {
    @GET(“/1.1/statuses/show.json”)
    Tweet getTweet(@Query(“id”) int id);
    }
    MyService getMyService() {
    return getService(MyService.class);
    }
    }

    View Slide

  20. Gracefully
    Degrade

    View Slide

  21. Gracefully Degrade
    if (TextUtils.isEmpty(apiKey)
    if (debuggable){
    throw new IllegalArgumentException(
    “apiKey is null!");
    } else {
    return null;
    }
    }

    View Slide

  22. Minimizing
    Permissions

    View Slide

  23. Minimizing Permissions

    View Slide

  24. Minimizing Permissions
    Crashlytics.setUserEmail(“[email protected]”);

    View Slide

  25. Permissions:
    Runtime Detection
    protected boolean canCheckNetworkState() {
    String permission = Manifest.permission.ACCESS_NETWORK_STATE;
    int result =
    context.checkCallingOrSelfPermission(permission);
    return (result == PackageManager.PERMISSION_GRANTED);
    }

    View Slide

  26. Multiple
    Application Types

    View Slide

  27. Multiple Application Types
    package com.example;
    import android.app.Service;
    public class MyService
    extends Service {
    }

    View Slide

  28. UI from Application Context
    WeakReference currentActivity = new WeakReference();
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    void registerLifecycleCallbacks() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
    final Application app = ((Application)context);
    app.registerActivityLifecycleCallbacks(
    new ActivityLifecycleCallbacks() {
    @Override
    public void onActivityResumed(Activity activity) {
    currentActivity.set(activity);
    }
    });
    }
    }

    View Slide

  29. Powerful SDKs
    Ease of Integration
    Extensibility
    Support all app types
    Permission detection

    View Slide

  30. Lightweight

    View Slide

  31. Binary Size

    View Slide

  32. Binary Size

    View Slide

  33. 3rd Party
    Library
    Mindfulness

    View Slide

  34. 3rd Party
    Library Mindfulness

    View Slide

  35. How big are Fabric AARs?
    Fabric: 190kb
    Crashlytics: 90kb
    Beta: 13kb
    Answers: 20kb
    Twitter API & SSO: 296kb
    Tweet UI: 120kb
    Tweet Composer: 5kb
    Digits: 236kb

    View Slide

  36. 3rd Party Library Mindfulness
    PROTOBUF
    KB
    OURS
    KB

    View Slide

  37. Dalvik
    Method
    Count

    View Slide

  38. Dalvik Method Count
    >./gradlew assemble

    Unable to execute dex: method ID not in [0,
    0xffff]: 65536
    Conversion to Dalvik format failed: Unable to
    execute dex: method ID not in [0, 0xffff]: 65536

    View Slide

  39. Dalvik Method Count
    > git clone [email protected]:mihaip/dex-method-counts.git
    > cd dex-method-counts
    > ant jar
    > ./dex-method-counts path/to/App.apk
    Read in 65490 method IDs.
    : 65490
    : 3
    accessibilityservice: 6
    bluetooth: 2
    content: 248
    pm: 22
    res: 45
    ...
    com: 53881
    adjust: 283
    sdk: 283

    View Slide

  40. Minimize
    Network
    Usage

    View Slide

  41. Network Usage
    10X SMALLER
    100X FASTER
    XML PROTOBUF

    View Slide

  42. Reduce
    Startup
    Time

    View Slide

  43. Startup Time
    Thread.start();
    Executors.newSingleThreadExecutor();

    View Slide

  44. Startup Time
    class MyThreadFactory implements ThreadFactory {
    @Override
    public Thread newThread(Runnable runnable) {
    final Thread thread = new Thread(runnable);
    thread.setPriority(Process.THREAD_PRIORITY_BACKGROUND);
    return thread;
    }
    }

    View Slide

  45. Lightweight SDKs
    Binary size
    3rd party library mindfulness
    Dalvik Method Count
    Network usage
    Startup time

    View Slide

  46. Lightweight
    Powerful

    View Slide

  47. Questions?
    dev.twitter.com
    @tsmith

    View Slide