Crash Wars - The handling awakens

71
Crash Wars - The handling awakens ŽELJKO PLESAC

Transcript of Crash Wars - The handling awakens

Crash Wars - The handling awakens

ŽELJKO PLESAC

ANDROID NOWADAYS

1.4 billion users

23 SDK versions

1,294 device vendors with

24,093 distinct Android devices

BEAUTIFUL APPS BEST POSSIBLE UX

I believe that the details will define the difference between good and really amazing. We prefer amazing.

- ANA BAOTIĆ

CRASHES HAVE AN ENORMOUS EFFECT ON THE

UX

NOBODY LIKES CRASHES*.

* EXCEPT QA

PROVIDE A BETTER CRASH EXPERIENCEYou should try to minimise your crashes.

Optimise your apps in a way you are able to detect crashes

even before they occur.

HOW TO PROVIDE A BETTER CRASH EXPERIENCE?

STATIC CODE CHECKERS

STATIC CODE CHECKERS

• Lint, PMD, Checkstyle, FindBugs

• ErrorProne

• SonarQube

• Facebook Infer

public class DataUtils {

public boolean testMethod(String test){ return test == null && test.length() == 0; } }

BUILD YOUR OWN “STATIC CODE CHECKERS” - USE CUSTOM LINT RULES

• define custom Lint rules that are best suited to your needs

• user/project/team specific

IF YOU’RE USING STATIC CODE CHECKERS, DON’T CHEAT.

Be a perfectionist.

WRITE TESTS.

WRITE TESTS

• black box tests, integration tests, UI tests, unit tests…

• TDD

• lot of tools - Espresso, Robolectric, Mockito…

HOW TO INCREASE YOUR TEST QUALITY?

Enforce strict testing rules.

TESTS STABILITY? Test frameworks have bugs. CI servers also. Android platform also.

HANDLE FAILURES

• all failed tests have to be examined carefully

• if your code didn’t cause them, ignore them but test them

once again when new version of testing platform is available

USE CONTINUOUS INTEGRATION

CONTINOUS INTEGRATION

Automate static code checkers & tests execution

A many products available - Jenkins, Travis, CircleCI…

HANDLE COMMON ANDROID PROBLEMS - MEMORY LEAKS

MEMORY LEAKS

• they will cause problems and crash your applications

• many great tools for detection

A memory leak detection library for Android and Java,

developed by Square (Pierre-Yves Ricau).

LEAK CANARY

• detects memory leaks in your

application, external libraries,

even Android OS itself

• it will not give you an answer

what the cause of a leak is, just

the information that the leak has

occurred

ANDROID STUDIO MEMORY PROFILERS

• Memory monitor, Heap and Allocation Trackers

• introduced in Android Studio 2.0

• can help you investigate memory leaks

ANDROID STUDIO MEMORY MONITOR

WEAK REFERENCES ARE NOT THE ANSWER TO

EVERYTHING.

USE MULTITHREADING

Android OS is multithreaded - there are other threads beside main UI thread.

ENFORCE RULES

• don’t block the main thread - even regular users will notice

flickering

• get familiar with multithreading components

• use Traceview and dmtracedump

STRICT MODE

• use Strict mode in debug builds - set penalty death • detectDiskReads() • detectDiskWrites()

DETECT ANR’S

• ANRWatchDog (link) • detects Android ANRs (Application Not

Responding) problems • can either crash your application or notify you via

callback

CRASH FAST

CRASH YOU APPLICATIONS AS SOON AS POSSIBLE

• Square’s approach to handling crashes (presentation and

video)

• organise your code in a way that it crashes as soon as

possible

• returning null values is evil

public class Person {

private String name;

private String surname;

public Person(String name, String surname) { this.name = name; this.surname = surname; }

… }

public static String getFullName(Person person) { return person.getName() + person.getSurname(); }

public static String getFullName(Person person) { if(person != null){

return person.getName() + person.getSurname(); }

else{ return null;

} }

public static String getFullName(Person person) { if (person == null) { throw new IllegalStateException("Person cannot be null!”); }

return person.getName() + person.getSurname(); }

LOG AND MEASURE

LOG AND MEASURE YOUR CRASHES

• many great tools (Crashlytics, AppsDynamics, Crittercism)

• analyse your crashes • custom ROMs causing crashes? • cheap, low quality devices? • frequency of crashes?

I don’t care about warnings, only errors.

- ME 5 YEARS AGO

THE TRY-CATCH BLOCK AND EXCEPTIONS• you should care about your handled exceptions

• they have to be logged and analysed

• should contain useful information

public class ProfilePresenterImpl implements ProfilePresenter{

public void showPersonData() { view.showFullName(PersonUtils.getFullName(person))); view.showBirthday(PersonUtils.getFormattedBirthday(person))); view.hideLoadingDialog();

} }

public class ProfilePresenterImpl implements ProfilePresenter{

public void showPersonData() { String fullName = PersonUtils.getFullName(person));

if(fullName != null){ view.showFullName(PersonUtils.getFullName(person)));

}

view.showBirthday(PersonUtils.getFormattedBirthday(person))); view.hideLoadingDialog();

} }

public class ProfilePresenterImpl implements ProfilePresenter{

public void showPersonData() { try{

String fullName = PersonUtils.getFullName(person)); if(fullName != null){ view.showFullName(PersonUtils.getFullName(person)));

}

view.showBirthday(PersonUtils.getFormattedBirthday(person))));} } catch(Exception e){ e.printStackTrace();

view.showErrorDialog(); }

} }

TIMBER

• Utility on top of Android's default Log class

• by Jake Wharton

• can be configured

CRASH REPORTING TREE

private static class CrashReportingTree extends Timber.Tree { @Override protected void log(int priority, String tag, String message, Throwable t) { if (priority == Log.VERBOSE || priority == Log.DEBUG) { return; } // will write to the crash report but NOT to logcat Crashlytics.log(message); if (t != null) { Crashlytics.logException(t); } }}

CRASH REPORTING TREE

@Overridepublic void onCreate() { super.onCreate(); CrashlyticsCore crashlyticsCore = new CrashlyticsCore.Builder()

.disabled(BuildConfig.DEBUG).build(); Fabric.with(this, new Crashlytics.Builder().core(crashlyticsCore).build());

if (BuildConfig.DEBUG) { Timber.plant(new Timber.DebugTree()); } else { Timber.plant(new CrashReportingTree()); } }

public class ProfilePresenterImpl implements ProfilePresenter{

public void showPersonData() { try{

String fullName = PersonUtils.getFullName(person)); if(fullName != null){ view.showFullName(PersonUtils.getFullName(person)));

}

view.showBirthday(PersonUtils.getFormattedBirthday(person))));} } catch(Exception e){ Timber.e(e, “Failure in “ + getClass().getSimpleName());

view.showErrorDialog(); }

} }

HIDE CRASHES FROM YOUR USERS

Crashes are just exceptions, which are not handled by your application*.

* IN MOST CASES

APP CRASH HANDLERS

• define custom app crash handler in everyone of your

production builds

• avoid ugly system dialogs

• watch out for app restart loops!

public class AppCrashHandler implements Thread.UncaughtExceptionHandler { private Activity liveActivity; public AppCrashHandler(Application application) { application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() { @Override public void onActivityResumed(Activity activity) { liveActivity = activity; } @Override public void onActivityPaused(Activity activity) { liveActivity = null; } }); } @Override public void uncaughtException(Thread thread, Throwable ex) { if(liveActivity != null){ Intent intent = new Intent(getApplicationContext(), MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); liveActivity.finish(); liveActivity.startActivity(intent); } System.exit(0); } }

CUSTOM CRASH HANDLER

APPLICATION CLASS

@Overridepublic void onCreate() { super.onCreate(); Thread.setDefaultUncaughtExceptionHandler(new AppCrashHandler(this)); }

EXAMPLE

GOOGLE PLAY FEATURES

UTILISE GOOGLE PLAY TOOLS

• alpha/beta test

• staged rollouts

HARSH TRUTH

THERE IS NO SUCH THING AS 100% CRASH FREE ANDROID

APPLICATION.

DEVICE FRAGMENTATION.

THINGS ARE GOING TO BECOME EVEN MORE

COMPLICATED.

MultiWindow support, Jack compiler, new APIs, deprecated

APIs, new programming languages…

ANDROID IS GETTING NEW FEATURES.

ROUNDUP.

Care

Minimise

Hide

Thank you!

Visit www.infinum.co or find us on social networks:

infinum.co infinumco infinumco infinum

@ZELJKOPLESAC [email protected]