Download - It's always your fault. Poznań ADG 2016
Android Technical Lead
Applause Inc.
Przemek Jakubczyk
pjakubczyk
@pjakubczyk
1
A guide to make crashproof libraries
It's always your fault
2
Background
At Applause I am responsible for quality
Applause SDK is crash and bug reporting library
shipped to over 1000 customers
SDK works with apps around the world
3
History
Joined 2 years ago to project with no QA
Today ~1800 unit tests covering 3k methods
82% lines covered
Last major problem was support for Marshmallow
4
Other than that over 6 months of no customer complain
How your SDK should look like
Be universal
Work in every provided configuration
Be robust
Work in any environment
Be defensive
5
GRADLE
6
Just use it.
7
because it’s the base for Android build system
Gradle
use simple tricks to protect your
styling
8
android {
resourcePrefix 'applause_'
}
or pass custom values to source
code via DSL
defaultConfig {
resValue "string","applause_library_version”, "$version"
}
Gradle
easier integration with your Groovy
scripts
for example create own distribution
task
task buildAll (
dependsOn: 'assembleRelease',
type: Copy) {
from “build/outputs/”
into “another_path”
}
9
Gradle
10
Not possible :)
Often heard question. How to pass arguments to tasks?
Create new task for each configuration.
Gradle
11
task buildAll (
dependsOn:
["assembleFreeRelease,
assemblePaidRelease"]
)
Gradle
With great power comes great responsibility
Mind the execution time
Common trick is to use VCS for versionNumber, each run takes time
If possible (please!) don’t make http calls - huge delay, timeout, offline?
Use only in tasks, not in build script evaluation.
12
Java
13
Java
catching Exception doesn’t solve problem
often hides real cause
tempting but dangerous
14
try {
network.getClients();
} catch (Exception e) {
// handle exception
}
Java
Null Object Pattern
instead constantly checking for not null
value
15
public interface Api {
void post(String action);
Api NULL = new Api() {
void post(String action){}
};
}
getApi().post(“Works”)
Java
NPE
Null Pointer Exception is the most popular
exception thrown in runtime.
NullObject pattern partially solves the problem.
Use empty objects, collections etc;
16
List<User> fetchUsers(){
try {
return api.getAllUsers();
} catch (IOException e){
return new
ArrayList<Users>();
}
}
Java
Usually library is started by one static method
… and next versions provide more functionality
Init interface becomes complex
17
Java
public static void start(
String baseUrl,
String defaultUser,
String defaultPassword,
boolean cacheRequests,
boolean forceHttps,
int timeout
)
18
Conf conf = new Conf.Builder()
.withUrl(“http://api.github.com”)
.withUser(“pjakubczyk”)
.withPassword(“droidcon2015Krakow”)
.withCache(false)
.withHttps(true)
.withTimeout(15)
.build();
Library.start(conf);
Java
Builder pattern organize configuration
Easier data validation
Pass only parameters user wants
Handling default values
19
Java
methods, fields, constructors
default, private, protected, public
Might sound a bit controversial
I use default or public
A.Reflection
B.Allow developers to override, it’s their responsibility 20
Android
21
Android
View.inEditMode() determines if view is drawn in Android Studio
Usually to disable other components
Let’s invert the usage
22
23
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);
}
}
}
Android
Build.VERSION.SDK_INT
ApplicationInfo.targetSdkVersion
the library doesn’t know where it’s run
24
Android
usually 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 leak
queue is flooded with requests holding all references
25
Android
Android Studio is bundled with great profilers
Use memory usage graph to monitor you cache logic
Use cpu usage graph to monitor your custom views behaviour.
Use network traffic graph to check if your code doesn’t call web for stuff which
suppose to be in cache
26
Android
ProGuard is outstanding tool to shrink code and inject bytecode optimizations
While 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!27
Android http://www.methodscount.com/
28
Product Method count
com.squareup.okhttp3:okhttp:3.0.1 2704
io.relayr:android-sdk:1.0.2 5413
io.reactivex:rxjava:1.1.0 4605
com.google.code.gson:gson:2. 1341
com.applause:applause-sdk:3.4.0 5041
com.fasterxml.jackson.core:jackson-databind:2.7.0 10732
com.parse:parse-android:1.13.0 4543
The End
29
License
30
Licence
31
by default you own the copyright
no licence doesn’t conclue you can use it in your project
open code (found online) != open source movement
transferring code goes along with transferring the ownership
Check the licence
Check if it infects yours
(Apache, MIT vs GPL v2, LGPL, BSD)
Thank you
32
A guide to make crashproof libraries
It's always your fault
33