DEVELOPING ANDROID LIBRARIES:
LESSONS FROM REALM
EMANUELE ZATTIN (@EMANUELEZ)
DEVIEW, SEPTEMBER 14, 2015
THANK YOU NAVER!
LET me KNOW YOU
WHAT IS REALM?
REALM IS A
MOBILE
DATABASE
REALM IS A
ZERO-COPY
OBJECT STORE
REALM FOR ANDROID WAS
FIRST RELEASED ONE YEAR
AGO HERE AT DEVIEW
SOME OF OUR USERS*
IN KOREA
*
Find out more at http://realm.io/kr/users
WHY WOULD YOU WRITE A
LIBRARY?
MODULARITY
The ability to split your code base into several units with well defined
interface. This allows to focus on smaller problems, producing more
testable code
REUSABILITY
A consequence of modularity. Now you can use that unit again in several
places in your projects or accross several different ones
SHAREABILITY
A consequence or reusability. You found a nice way to solve a particular
issue. Why now helping other developers? Get your name out there!
WHY WOULD YOU WRITE AN
ANDROID LIBRARY?
▸ UI
▸ Looper/Handler
▸ Sensors
▸ Native code
▸ Many more!
WHY WOULD REALM WRITE
AN ANDROID LIBRARY?
▸ UI
▸ Looper/Handler
▸ Sensors
▸ Native code
▸ Many more!
CHALLENGE 1HOW TO START AN ANDROID
LIBRARY PROJECT?
THE PROBLEM
ANDROID STUDIO ALLOWS YOU TO:
▸ Create a new Application project
▸ Create a new Library project
▸ Add a new Application module
▸ Add a new Library module
SOLUTION 1
From Android Studio:
1. Create a new Application project
2. Add a new Library module
3. Remove the Application module
SOLUTION 2
From the command line:
android create lib-project -t 1 -k kr.deview.awesomelib -p . -g -v 1.3.0
-t: target (Use android list targets to get a list of target ids)
-k: package name
-p: path to the project
-g: make it a Gradle project (requires SDK >= 19)
-v: version of the Android Gradle plugin to use
CHALLENGE 2API DESIGN
SOLUTION
DEFINE WHAT A GOOD API IS
▸ Easy to learn
▸ Easy to use, even without documentation
▸ Hard to misuse
▸ Easy to read and maintain code that uses it
▸ Sufficiently powerful to satisfy requirements
▸ Easy to extend
▸ Appropriate to audience
STAND ON THE SHOUDERS OF GIANTS
▸ Effective Java 2 by Joshua Bloch
▸ How To Design A Good API and Why it Matters by Joshua Bloch
CHALLENGE 3TESTING
TESTING IS EVEN MORE IMPORTANT FOR
LIBRARIES THAN FOR APPLICATIONS
BECAUSE YOU HAVE NO IDEA HOW YOUR
CUSTOMERS ARE GOING TO USE IT.
SOLUTION 1
PREFER JUNIT41
OVER JUNIT3
1
Because parametric tests will save your life!
SOLUTION 2
AUTOMATE ALL THE THINGS!
LET JENKINS BECOME YOUR
BEST FRIEND
USEFUL JENKINS PLUGINS
▸ Job Config History
▸ Git
▸ Android Emulator
▸ Matrix Job2
▸ Junit2
2
It comes preloaded with Jenkins
SOLUTION 3
WRITE SAMPLE APPS!
▸ Additional integration tests
▸ Showcase how to use your library
▸ Validate your core principles
CHALLENGE 4JAR OR AAR?
DO YOU WANT TO SUPPORT ECLIPSE?
SHOW ME YOUR HANDS ONCE AGAIN
SOLUTION
USE AAR
CHALLENGE 5WHERE TO PUBLISH?
SOLUTION
BINTRAY
HOW TO PRODUCE A SOURCE JAR
task androidSourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
}
HOW TO PRODUCE A JAVADOC JAR
android.libraryVariants.all { variant ->
task("javadoc${variant.name.capitalize()}", type: Javadoc) {
description "Generates Javadoc for $variant.name."
group 'Docs'
source = variant.javaCompile.source
ext.androidJar = files(project.android.getBootClasspath())
classpath = files(variant.javaCompile.classpath.files) +
ext.androidJar
exclude '**/BuildConfig.java'
exclude '**/R.java'
}
}
Bintray also provides a Gradle plugin for the actual publishing
The configuration is not trivial, and in the beginning it might be easier
to just do the release manually on the binary website
CHALLENGE 6INTROSPECTION IS SLOW
Sometimes libraries need to be smart behind the scenes to save the
user from writing boilerplate code
SOLUTION
ANNOTATION PROCESSING
! PROS:
▸ It allows you to write new Java files
▸ It happens at compilation time
! CONS
▸ It does not allow to modify existing code
▸ It's not very easy to use
SOME VERY cool libraries USE IT!
▸ Dagger
▸ Butter Knife
▸ AutoValue/AutoParcel
▸ Realm
BAD NEWS
Android does not include the package
javax.annotation.processing
WORKAROUND
Create two Java sub-projects:
1. annotations (used both by the library and the processor)
2. annotations processor
YOU NEED TO INCLUDE THE ANNOTATIONS IN THE JAVADOC
android.libraryVariants.all { variant ->
task("javadoc${variant.name.capitalize()}", type: Javadoc) {
description "Generates Javadoc for $variant.name."
group 'Docs'
source = variant.javaCompile.source
source "../annotations/src/main/java" // <-- Remember this!
ext.androidJar = files(project.android.getBootClasspath())
classpath = files(variant.javaCompile.classpath.files)
+ ext.androidJar
exclude '**/BuildConfig.java'
exclude '**/R.java'
}
}
CHALLENGE 7
SOMETIMES ANNOTATION
PROCESSING IS NOT
POWERFUL ENOUGH
! PROS:
▸ It allows you to write new Java files
▸ It happens at compilation time
! CONS
▸ It does not allow to modify existing code
▸ It's not very easy to use
SOLUTION
BYTECODE WEAVING
! PROS:
▸ It allows to modify existing code ❤
▸ It's easier to use compared to Annotation Processing
! CONS
▸ You really need to know what you are doing
▸ It might look weird in the debugger
TOOLS THAT ALLOW TO DO BYTECODE WEAVING
▸ Javassist
▸ ASM
▸ AspectJ
THANK YOU STEPHANE NICOLAS!
https://github.com/stephanenicolas/injects
CHALLENGE 8NATIVE CODE
THE BAD NEWS
THE ANDROID GRADLE PLUGIN
DOES NOT SUPPORT NDK
ANYMORE
THE GOOD NEWS
GOOGLE IS DEVELOPING AN
EXPERIMENTAL NEW PLUGIN
THAT SUPPORTS NDK
HOW TO START USING IT
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.2.0'
}
}
apply plugin: 'com.android.model.application'
THE DSL IS SLIGHTLY DIFFERENT
model { // <-- This!
android {
compileSdkVersion = 22 // Now it's a property, not a method
buildToolsVersion = "22.0.1" // Same here and the rest of the example
defaultConfig.with { // Use the with method
applicationId = "com.example.user.myapplication"
minSdkVersion.apiLevel = 15 // Use the apiLevel property
targetSdkVersion.apiLevel = 22 // Same here
versionCode = 1
versionName = "1.0"
}
}
}
FIND OUT MORE ABOUT IT
http://tools.android.com/tech-docs/new-build-system/gradle-
experimental
ONE ANNOYING LIMITATION
NO SUPPORT FOR CREATING
AND DEPENDING ON STATIC
LIBRARIES
THANK YOU!
REALM 부스에
많이 방문해주세요!
오늘만 열어요

[113] lessons from realm

  • 1.
    DEVELOPING ANDROID LIBRARIES: LESSONSFROM REALM EMANUELE ZATTIN (@EMANUELEZ) DEVIEW, SEPTEMBER 14, 2015
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
    REALM FOR ANDROIDWAS FIRST RELEASED ONE YEAR AGO HERE AT DEVIEW
  • 8.
    SOME OF OURUSERS* IN KOREA * Find out more at http://realm.io/kr/users
  • 9.
    WHY WOULD YOUWRITE A LIBRARY?
  • 10.
    MODULARITY The ability tosplit your code base into several units with well defined interface. This allows to focus on smaller problems, producing more testable code
  • 11.
    REUSABILITY A consequence ofmodularity. Now you can use that unit again in several places in your projects or accross several different ones
  • 12.
    SHAREABILITY A consequence orreusability. You found a nice way to solve a particular issue. Why now helping other developers? Get your name out there!
  • 13.
    WHY WOULD YOUWRITE AN ANDROID LIBRARY?
  • 14.
    ▸ UI ▸ Looper/Handler ▸Sensors ▸ Native code ▸ Many more!
  • 15.
    WHY WOULD REALMWRITE AN ANDROID LIBRARY?
  • 16.
    ▸ UI ▸ Looper/Handler ▸Sensors ▸ Native code ▸ Many more!
  • 17.
    CHALLENGE 1HOW TOSTART AN ANDROID LIBRARY PROJECT?
  • 18.
    THE PROBLEM ANDROID STUDIOALLOWS YOU TO: ▸ Create a new Application project ▸ Create a new Library project ▸ Add a new Application module ▸ Add a new Library module
  • 19.
    SOLUTION 1 From AndroidStudio: 1. Create a new Application project 2. Add a new Library module 3. Remove the Application module
  • 20.
    SOLUTION 2 From thecommand line: android create lib-project -t 1 -k kr.deview.awesomelib -p . -g -v 1.3.0 -t: target (Use android list targets to get a list of target ids) -k: package name -p: path to the project -g: make it a Gradle project (requires SDK >= 19) -v: version of the Android Gradle plugin to use
  • 21.
  • 22.
  • 23.
    ▸ Easy tolearn ▸ Easy to use, even without documentation ▸ Hard to misuse ▸ Easy to read and maintain code that uses it ▸ Sufficiently powerful to satisfy requirements ▸ Easy to extend ▸ Appropriate to audience
  • 24.
    STAND ON THESHOUDERS OF GIANTS ▸ Effective Java 2 by Joshua Bloch ▸ How To Design A Good API and Why it Matters by Joshua Bloch
  • 25.
  • 26.
    TESTING IS EVENMORE IMPORTANT FOR LIBRARIES THAN FOR APPLICATIONS BECAUSE YOU HAVE NO IDEA HOW YOUR CUSTOMERS ARE GOING TO USE IT.
  • 27.
    SOLUTION 1 PREFER JUNIT41 OVERJUNIT3 1 Because parametric tests will save your life!
  • 28.
  • 29.
    LET JENKINS BECOMEYOUR BEST FRIEND
  • 30.
    USEFUL JENKINS PLUGINS ▸Job Config History ▸ Git ▸ Android Emulator ▸ Matrix Job2 ▸ Junit2 2 It comes preloaded with Jenkins
  • 31.
  • 32.
    ▸ Additional integrationtests ▸ Showcase how to use your library ▸ Validate your core principles
  • 33.
  • 34.
    DO YOU WANTTO SUPPORT ECLIPSE? SHOW ME YOUR HANDS ONCE AGAIN
  • 35.
  • 36.
  • 37.
  • 38.
    HOW TO PRODUCEA SOURCE JAR task androidSourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs }
  • 39.
    HOW TO PRODUCEA JAVADOC JAR android.libraryVariants.all { variant -> task("javadoc${variant.name.capitalize()}", type: Javadoc) { description "Generates Javadoc for $variant.name." group 'Docs' source = variant.javaCompile.source ext.androidJar = files(project.android.getBootClasspath()) classpath = files(variant.javaCompile.classpath.files) + ext.androidJar exclude '**/BuildConfig.java' exclude '**/R.java' } }
  • 40.
    Bintray also providesa Gradle plugin for the actual publishing The configuration is not trivial, and in the beginning it might be easier to just do the release manually on the binary website
  • 41.
  • 42.
    Sometimes libraries needto be smart behind the scenes to save the user from writing boilerplate code
  • 43.
  • 44.
    ! PROS: ▸ Itallows you to write new Java files ▸ It happens at compilation time ! CONS ▸ It does not allow to modify existing code ▸ It's not very easy to use
  • 45.
    SOME VERY coollibraries USE IT! ▸ Dagger ▸ Butter Knife ▸ AutoValue/AutoParcel ▸ Realm
  • 46.
    BAD NEWS Android doesnot include the package javax.annotation.processing
  • 47.
    WORKAROUND Create two Javasub-projects: 1. annotations (used both by the library and the processor) 2. annotations processor
  • 48.
    YOU NEED TOINCLUDE THE ANNOTATIONS IN THE JAVADOC android.libraryVariants.all { variant -> task("javadoc${variant.name.capitalize()}", type: Javadoc) { description "Generates Javadoc for $variant.name." group 'Docs' source = variant.javaCompile.source source "../annotations/src/main/java" // <-- Remember this! ext.androidJar = files(project.android.getBootClasspath()) classpath = files(variant.javaCompile.classpath.files) + ext.androidJar exclude '**/BuildConfig.java' exclude '**/R.java' } }
  • 49.
  • 50.
    ! PROS: ▸ Itallows you to write new Java files ▸ It happens at compilation time ! CONS ▸ It does not allow to modify existing code ▸ It's not very easy to use
  • 51.
  • 52.
    ! PROS: ▸ Itallows to modify existing code ❤ ▸ It's easier to use compared to Annotation Processing ! CONS ▸ You really need to know what you are doing ▸ It might look weird in the debugger
  • 53.
    TOOLS THAT ALLOWTO DO BYTECODE WEAVING ▸ Javassist ▸ ASM ▸ AspectJ
  • 54.
    THANK YOU STEPHANENICOLAS! https://github.com/stephanenicolas/injects
  • 55.
  • 56.
    THE BAD NEWS THEANDROID GRADLE PLUGIN DOES NOT SUPPORT NDK ANYMORE
  • 57.
    THE GOOD NEWS GOOGLEIS DEVELOPING AN EXPERIMENTAL NEW PLUGIN THAT SUPPORTS NDK
  • 58.
    HOW TO STARTUSING IT buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle-experimental:0.2.0' } } apply plugin: 'com.android.model.application'
  • 59.
    THE DSL ISSLIGHTLY DIFFERENT model { // <-- This! android { compileSdkVersion = 22 // Now it's a property, not a method buildToolsVersion = "22.0.1" // Same here and the rest of the example defaultConfig.with { // Use the with method applicationId = "com.example.user.myapplication" minSdkVersion.apiLevel = 15 // Use the apiLevel property targetSdkVersion.apiLevel = 22 // Same here versionCode = 1 versionName = "1.0" } } }
  • 60.
    FIND OUT MOREABOUT IT http://tools.android.com/tech-docs/new-build-system/gradle- experimental
  • 61.
    ONE ANNOYING LIMITATION NOSUPPORT FOR CREATING AND DEPENDING ON STATIC LIBRARIES
  • 62.
  • 63.