Droidcon Berlin Barcamp 2016

of 37/37
Android Technical Lead Applause Inc. Przemek Jakubczyk pjakubczy k @pjakubczy k 1
  • date post

    16-Apr-2017
  • Category

    Mobile

  • view

    362
  • download

    1

Embed Size (px)

Transcript of Droidcon Berlin Barcamp 2016

Android Technical LeadApplause Inc.Przemek Jakubczykpjakubczyk

@pjakubczyk

#

A guide to make crashproof librariesIt's always your fault#

BackgroundAt Applause I am responsible for qualityApplause SDK is crash and bug reporting libraryshipped to over 1000 customersSDK works with apps around the world#

HistoryJoined 2 years ago to project with no QAToday ~2200 unit tests covering 3k methods82% lines coveredLast major problem was support for Marshmallow#Other than that over 6 months of no customer complain

How your SDK should look likeBe universalWork in every provided configurationBe robustWork in any environmentBe defensive#

GRADLE#

Just use it.#because its the base for Android build system

Gradleuse simple tricks to protect your styling#android { resourcePrefix 'applause_'}

or pass custom values to source code via DSLdefaultConfig { resValue "string","applause_library_version, "$version"}

Mind that previous part will guard second one

Gradleeasier integration with your Groovy scriptsfor example create own distribution tasktask buildAll (dependsOn: 'assembleRelease', type: Copy){from build/outputs/into another_path}#

Gradle#Not possible :)Often heard question. How to pass arguments to tasks?

Good that we are talking about tasks

Create new task for each configuration.

Gradle#task buildAll ( dependsOn: ["assembleFreeRelease, assemblePaidRelease"])

Java#

Javacatching Exception doesnt solve problemoften hides real causetempting but dangerous#try { network.getClients();} catch (Exception e) { // handle exception}

JavaNull Object Pattern instead constantly checking for not null value#public interface Api { void post(String action); Api NULL = new Api() {void post(String action){} };}

getApi().post(Works)

JavaNPENull Pointer Exception is the most popular exception thrown in runtime.NullObject pattern partially solves the problem.Use empty objects, collections etc;#List fetchUsers(){ try {return api.getAllUsers(); } catch (IOException e){return new ArrayList(); }}

JavaUsually library is started by one static method and next versions provide more functionalityInit interface becomes complex#

Javapublic static void start(String baseUrl,String defaultUser,String defaultPassword,boolean cacheRequests,boolean forceHttps,int timeout)#Conf conf = new Conf.Builder().withUrl(http://api.github.com).withUser(pjakubczyk).withPassword(droidcon2016Berlin).withCache(false).withHttps(true).withTimeout(15).build();

Library.start(conf);

JavaBuilder pattern organize configurationEasier data validationPass only parameters user wantsHandling default values

#

Examples Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build();

#Stetho.newInitializerBuilder(context) .enableWebKitInspector(myInspector) .build()

ConcurrencyNew Thread is your enemy

#ExecutorService EXECUTOR = Executors.newSingleThreadExecutor(new ThreadFactory() { @Override public Thread newThread(Runnable r) { return new Thread(r, "NetworkExecutor"); }});

The StringString is a bad information holderOften passing 2 string parameters to methodLead to simple mistakesUser vs PersonInstead of getters maybe method serializeForAuth ?#

Android#

AndroidView.inEditMode() determines if view is drawn in Android StudioUsually to disable other componentsLets invert the usage

#

#public void onFinishInflate(){TextView title = findViewById(R.id.title);if(inEditMode()) {int count = title.getText().length();if(count > 30){title.setTextSize(24.0f);} else {title.setTextSize(30.0f);}}}

AndroidBuild.VERSION.SDK_INTApplicationInfo.targetSdkVersionthe library doesnt know where its run#

Androidusually interface for loading pictures from to web to Widget looks like this:pictureLoader.load(url_to_resource, imageView);passing arguments extending from View, Activity etc. often lead to Memory leakqueue is flooded with requests holding all referencesGo back to javadoc and check java.lang.ref.WeakReference :)#

AndroidWrap OS Exceptions with your own implementationBitmapFactoryThrows unchecked OutOfMemoryError#

#public static class BitmapCreatorException extends Exception { public BitmapCreatorException(String detailMessage) { super(detailMessage); }

public BitmapCreatorException(Throwable throwable) { super(throwable); } }

#Bitmap createScaled(Bitmap bitmap, int width, int height) throws BitmapCreatorException { try { Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, width, height, true); return nullCheck(scaledBitmap); } catch (OutOfMemoryError error) { throw new BitmapCreatorException(error); }}

Bitmap Provider

#Bitmap nullCheck(Bitmap bitmap) throws BitmapCreatorException { if (bitmap == null) throw new BitmapCreatorException("Bitmap is empty"); else return bitmap;}

Bitmap Provider

AndroidProGuard is outstanding tool to shrink code and inject bytecode optimizationsWhile shipping your code you must either provide:copy&paste configuration to ProGuard (latest plugin supports auto-configuration)be transparent to ProGuard.Configuration vs Transparency?Transparency!#

Android http://www.methodscount.com/#ProductMethod countcom.squareup.okhttp3:okhttp:3.0.12704io.relayr:android-sdk:1.0.25413io.reactivex:rxjava:1.1.04605com.google.code.gson:gson:2.1341com.applause:applause-sdk:3.4.05041com.fasterxml.jackson.core:jackson-databind:2.7.010732com.parse:parse-android:1.13.04543

The End#

License#

Licence#by default you own the copyright no licence doesnt conclue you can use it in your projectopen code (found online) != open source movementtransferring code goes along with transferring the ownership Check the licenceCheck if it infects yours(Apache, MIT vs GPL v2, LGPL, BSD)

Thank you#

A guide to make crashproof librariesIt's always your fault#