crash wars - the handling awakens

81
Crash Wars - The handling awakens ŽELJKO PLESAC

Upload: zeljko-plesac

Post on 14-Apr-2017

238 views

Category:

Software


7 download

TRANSCRIPT

Page 1: Crash wars - The handling awakens

Crash Wars - The handling awakens

ŽELJKO PLESAC

Page 2: Crash wars - The handling awakens

Independent design & development agency

100 people in 3 offices

18 Android engineers

ABOUT INFINUM

Page 3: Crash wars - The handling awakens

ANDROID NOWADAYS

24 SDK versions

1,294 device vendors with

24,093 distinct Android devices

Page 4: Crash wars - The handling awakens

BEAUTIFUL APPS BEST POSSIBLE UX

Page 5: Crash wars - The handling awakens

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

- JULIUS CESAR

Page 6: Crash wars - The handling awakens

CRASHES HAVE AN ENORMOUS EFFECT ON THE

UX

Page 7: Crash wars - The handling awakens

NOBODY LIKES CRASHES*.

* EXCEPT QA

Page 8: Crash wars - The handling awakens

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.

Page 9: Crash wars - The handling awakens

HOW TO PROVIDE A BETTER CRASH EXPERIENCE?

Page 10: Crash wars - The handling awakens
Page 11: Crash wars - The handling awakens

STATIC CODE CHECKERS

Page 12: Crash wars - The handling awakens

STATIC CODE CHECKERS

• Lint, PMD, Checkstyle, FindBugs

• ErrorProne

• SonarQube

• Facebook Infer

Page 13: Crash wars - The handling awakens

public class DataUtils {

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

Page 14: Crash wars - The handling awakens

JAVA.NET.URL

@Testpublic void urlEquals() throws Exception { URL url = new URL("https://infinum.co"); URL otherUrl = new URL("https://www.infinum.co"); Assert.assertEquals(url, otherUrl);}

Page 15: Crash wars - The handling awakens
Page 16: Crash wars - The handling awakens

JAVA.NET.URL - JAVADOCS

•Two hosts are considered equivalent if both host names can be resolved into the same IP addresses; else if either host name can't be resolved, the host names must be equal without regard to case; or both host names equal to null.

•Since hosts comparison requires name resolution, this operation is a blocking operation.

Page 17: Crash wars - The handling awakens

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

Page 18: Crash wars - The handling awakens

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

Page 19: Crash wars - The handling awakens

Be a perfectionist.

Page 20: Crash wars - The handling awakens

WRITE TESTS.

Page 21: Crash wars - The handling awakens

WRITE TESTS

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

• TDD

• lot of tools - Unit 4, Espresso, Robolectric, Mockito…

Page 22: Crash wars - The handling awakens

HOW TO INCREASE YOUR TEST QUALITY?

Page 23: Crash wars - The handling awakens

Enforce strict testing rules.

Page 24: Crash wars - The handling awakens

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

Page 25: Crash wars - The handling awakens

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

Page 26: Crash wars - The handling awakens

USE CONTINUOUS INTEGRATION

Page 27: Crash wars - The handling awakens

CONTINOUS INTEGRATION

Automate static code checkers & tests execution

Many available products - Jenkins, Travis, CircleCI…

Page 28: Crash wars - The handling awakens

Clients want their features

done yesterday.

Leads to “we’ll fix the build

after the release” behaviour.

BROKEN BUILDS

Page 29: Crash wars - The handling awakens
Page 30: Crash wars - The handling awakens
Page 31: Crash wars - The handling awakens

HANDLE COMMON ANDROID PROBLEMS - MEMORY LEAKS

Page 32: Crash wars - The handling awakens

MEMORY LEAKS

• they will cause problems and crash your applications

• many great tools for detection

Page 33: Crash wars - The handling awakens

A memory leak detection library for Android and Java,

developed by Square (Pierre-Yves Ricau).

LEAK CANARY

Page 34: Crash wars - The handling awakens

• 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

Page 35: Crash wars - The handling awakens

ANDROID STUDIO MEMORY PROFILERS

• Memory monitor, Heap and Allocation Trackers

• introduced in Android Studio 2.0

• can help you investigate memory leaks

Page 36: Crash wars - The handling awakens

ANDROID STUDIO MEMORY MONITOR

Page 37: Crash wars - The handling awakens

WEAK REFERENCES ARE NOT THE ANSWER TO

EVERYTHING.

Page 38: Crash wars - The handling awakens

UNRESPONSIVE APPS

Page 39: Crash wars - The handling awakens

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

Page 40: Crash wars - The handling awakens

ENFORCE RULES

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

flickering

• get familiar with multithreading components

• use Traceview and dmtracedump

Page 41: Crash wars - The handling awakens

STRICT MODE

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

Page 42: Crash wars - The handling awakens

DETECT ANR’S

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

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

callback

Page 43: Crash wars - The handling awakens

CRASH FAST

Page 44: Crash wars - The handling awakens

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

Page 45: Crash wars - The handling awakens

public class Person {

private String name;

private String surname;

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

… }

Page 46: Crash wars - The handling awakens

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

Page 47: Crash wars - The handling awakens

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

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

else{ return null;

} }

Page 48: Crash wars - The handling awakens

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

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

Page 49: Crash wars - The handling awakens

LOG AND MEASURE

Page 50: Crash wars - The handling awakens

LOG AND MEASURE YOUR CRASHES

• many great tools (Crashlytics, AppsDynamics, Crittercism,

Firebase)

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

Page 51: Crash wars - The handling awakens
Page 52: Crash wars - The handling awakens

Disable crash reporting in debug builds.

Add GIT SHA to your crash reports.

Add additional data to your reports - custom keys, user

information.

PRO TIPS

Page 53: Crash wars - The handling awakens

HANDLE EXCEPTIONS

Page 54: Crash wars - The handling awakens

I don’t care about warnings, only errors.

- KING HENRIK VIII.

Page 55: Crash wars - The handling awakens

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

• they have to be logged and analysed

• should contain useful information

• define custom exceptions

Page 56: Crash wars - The handling awakens

public class ProfilePresenterImpl implements ProfilePresenter{

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

} }

Page 57: Crash wars - The handling awakens

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();

} }

Page 58: Crash wars - The handling awakens

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(); }

} }

Page 59: Crash wars - The handling awakens

TIMBER

• Utility on top of Android's default Log class

• by Jake Wharton

• can be configured

Page 60: Crash wars - The handling awakens

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); } }}

Page 61: Crash wars - The handling awakens

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()); } }

Page 62: Crash wars - The handling awakens

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(); }

} }

Page 63: Crash wars - The handling awakens
Page 64: Crash wars - The handling awakens

HIDE CRASHES FROM YOUR USERS

Page 65: Crash wars - The handling awakens

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

* IN MOST CASES

Page 66: Crash wars - The handling awakens

APP CRASH HANDLERS

• define custom app crash handler in everyone of your

production builds

• avoid ugly system dialogs

• watch out for app restart loops!

Page 67: Crash wars - The handling awakens

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

Page 68: Crash wars - The handling awakens

APPLICATION CLASS

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

Page 69: Crash wars - The handling awakens

EXAMPLE

Page 70: Crash wars - The handling awakens

GOOGLE PLAY FEATURES

Page 71: Crash wars - The handling awakens

UTILISE GOOGLE PLAY TOOLS

• alpha/beta test

• staged rollouts

Page 72: Crash wars - The handling awakens

HARSH TRUTH

Page 73: Crash wars - The handling awakens

THERE IS NO SUCH THING AS 100% CRASH FREE ANDROID

APPLICATION.

Page 74: Crash wars - The handling awakens

DEVICE FRAGMENTATION.

Page 75: Crash wars - The handling awakens
Page 76: Crash wars - The handling awakens

THINGS ARE GOING TO BECOME EVEN MORE

COMPLICATED.

Page 77: Crash wars - The handling awakens
Page 78: Crash wars - The handling awakens

MultiWindow support, Jack compiler, new APIs, deprecated

APIs, new programming languages…

ANDROID IS GETTING NEW FEATURES.

Page 79: Crash wars - The handling awakens

ROUNDUP.

Page 80: Crash wars - The handling awakens

Care.

Minimise.

Hide.

Page 81: Crash wars - The handling awakens

Thank you!

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

infinum.co infinumco infinumco infinum

@ZELJKOPLESAC [email protected]