Share
Embed
Writing Android Libraries
Presented to the Bay Area Android Group on March 25th 2015
Realm
April 06, 2015
Transcript
69 slides
-
Writing Android Libraries Emanuele Zattin March 23, 2015 Bay Area
Android Developer Group -
Emanuele Zattin Born and raised in Padova, Italy Living in
Copenhagen, Denmark since 2005 Automation enthusiast Jenkins CI contributor since 2010 Java developer at Realm About me -
Embedded on-device mobile database Easy — saves app makers months
of time Cross-platform — iOS & Android for now. More are coming Fast — way faster than existing solutions About Realm -
Your code depends on Android idioms: • UI • Looper/Handler
• Sensors • Native code • Many more! Why writing an Android library? -
How hard can it be right? Just fire Android Studio
up and start a new project! Step one: Getting started! -
Android Studio supports the creation of: Step one: Getting started!
Application Library New project ✓ ✗ New module ✓ ✓ -
Option 1: Android Studio 1. Create a new application project
2. Add a library module 3. Remove the application module Step one: Getting started! -
Option 2: The Command Line $ android create lib-project -t
1 -k it.droidcon.awesomelib -p . -g -v 1.1.3 -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 Step one: Getting started! -
API Design It’s a huge subject that goes far beyond
this presentation but here are some pointers and reference: Effective Java 2, Joshua Bloch How To Design A Good API and Why it Matters, Joshua Bloch Step two: Code, code, code! -
Characteristics of a good API (Joshua Bloch) • 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 Step two: Code, code, code! -
Testing is universally important but even more so for libraries
Step three: Test -
Testing is universally important but even more so for libraries
Testing an Android library is just like testing an Android application Step three: Test -
Testing is universally important but even more so for libraries
Testing an Android library is just like testing an Android application Yes, JUnit 3 is not so good and lacks a particularly important feature when testing libraries: parametric tests Step three: Test -
Testing is universally important but even more so for libraries
Testing an Android library is just like testing an Android application Yes, JUnit 3 is not so good and lacks a particularly important feature when testing libraries: parametric tests Luckily there’s a solution: Burst Step three: Test -
Automate your tests! Jenkins is a wonderful tool for this.
It offers more than one thousand plugins some of which specialised for Android development. Step three: Test -
Some must-have Jenkins plugins include: • Job Config History plugin
Step three: Test -
Some must-have Jenkins plugins include: • Job Config History plugin
• Git plugin Step three: Test -
Some must-have Jenkins plugins include: • Job Config History plugin
• Git plugin • Gradle plugin Step three: Test -
Some must-have Jenkins plugins include: • Job Config History plugin
• Git plugin • Gradle plugin • Android Emulator plugin Step three: Test -
Some must-have Jenkins plugins include: • Job Config History plugin
• Git plugin • Gradle plugin • Android Emulator plugin • Jenkins comes with JUnit and Matrix job support out of the box Step three: Test -
Another useful way to test your library (and showcase it)
is to write one or more example apps. Step three: Test -
Another useful way to test your library (and showcase it)
is to write one or more example apps. Running monkey on the app ensures it doesn’t suffer from crashes and ANRs Step three: Test -
Another useful way to test your library (and showcase it)
is to write one or more example apps. Running monkey on the app ensures it doesn’t suffer from crashes and ANRs A useful Gradle plugin: https://github.com/novoda/gradle-android-command-plugin Step three: Test -
Aar vs Jar • Aar is supported by Gradle and
Android Studio Step four: Publish -
Aar vs Jar • Aar is supported by Gradle and
Android Studio • Aar is not supported by Ant and Eclipse Step four: Publish -
Aar vs Jar • Aar is supported by Gradle and
Android Studio • Aar is not supported by Ant and Eclipse • Using local Aar files is not trivial Step four: Publish -
Aar vs Jar • Aar is supported by Gradle and
Android Studio • Aar is not supported by Ant and Eclipse • Using local Aar files is not trivial • Do you want to support Eclipse? Use Jar! Step four: Publish -
The Android Gradle plugin will generate an Aar file How
to generate a Jar instead? The Aar actually contains our Jar already! task generateJar(type: Copy) { group 'Build' description 'blah blah...' dependsOn assemble from 'build/intermediates/bundles/release/classes.jar' into 'build/libs' rename('classes.jar', 'awesome-library.jar') } Step four: Publish -
Bintray requires a source Jar task androidSourcesJar(type: Jar) { from
android.sourceSets.main.java.srcDirs } Step four: Publish -
Bintray also requires 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(plugins .findPlugin(“com.android.library") .getBootClasspath()) classpath = files(variant.javaCompile.classpath.files) + ext.androidJar exclude '**/BuildConfig.java' exclude '**/R.java' } } Step four: Publish -
Bintray also provides a Gradle plugin for the actual publishing
https://github.com/bintray/gradle-bintray-plugin The configuration is not trivial, and in the beginning it might be easier to just do the release manually on the binary website Step four: Publish -
Annotation processing is a functionality of javac used for scanning
and processing annotations at compile time Advanced Topics: Annotation Processor -
Annotation processing is a functionality of javac used for scanning
and processing annotations at compile time You can write your own annotation processor. Advanced Topics: Annotation Processor -
Annotation processing is a functionality of javac used for scanning
and processing annotations at compile time You can write your own annotation processor. Problems that annotation processing is good at solving: Advanced Topics: Annotation Processor -
Annotation processing is a functionality of javac used for scanning
and processing annotations at compile time You can write your own annotation processor. Problems that annotation processing is good at solving: • Boilerplate removal Advanced Topics: Annotation Processor -
Annotation processing is a functionality of javac used for scanning
and processing annotations at compile time You can write your own annotation processor. Problems that annotation processing is good at solving: • Boilerplate removal • Introspection removal Advanced Topics: Annotation Processor -
Popular Android libraries using annotation processing: • Dagger Advanced Topics:
Annotation Processor -
Popular Android libraries using annotation processing: • Dagger • Butter
Knife Advanced Topics: Annotation Processor -
Popular Android libraries using annotation processing: • Dagger • Butter
Knife • Autovalue/Autoparcel Advanced Topics: Annotation Processor -
Popular Android libraries using annotation processing: • Dagger • Butter
Knife • Autovalue/Autoparcel • Realm Advanced Topics: Annotation Processor -
Bad news! The Android API does not support the
javax.annotation.processing package Advanced Topics: Annotation Processor -
Create two new java sub-projects: • annotations (used both by
the library and the processor) • annotations processor Advanced Topics: Annotation Processor -
The Jar task will need to be modified: task androidJar(type:
Jar) { dependsOn assemble group 'Build' description ‘blah blah’ from zipTree( 'build/intermediates/bundles/release/classes.jar') from zipTree( '../annotations-processor/build/libs/processor.jar') from zipTree( '../annotations/build/libs/annotations.jar') } Advanced Topics: Annotation Processor -
The javadoc tasks will also have to be modified: 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" ext.androidJar = files(plugins .findPlugin(“com.android.library") .getBootClasspath()) classpath = files(variant.javaCompile.classpath.files) + ext.androidJar exclude '**/BuildConfig.java' exclude '**/R.java' } } Advanced Topics: Annotation Processor -
WARNING [Project: :lib] Current NDK support is deprecated.
Alternative will be provided in the future. Advanced Topics: Native code -
Solution 1 Ignore Google’s warning and keep using the Gradle
NDK support. It works* but there is one missing feature: no ldFlags ndk { moduleName "sanangeles" cFlags "-‐DANDROID_NDK -‐DDISABLE_IMPORTGL" ldLibs "GLESv1_CM", "dl", "log" stl "stlport_static" } *for some definition of “works” Advanced Topics: Native code -
Solution 2 Gradle native plugin Gotchas: • Requires extra logic
to handle standalone toolchains • It might soon become obsolete Advanced Topics: Native code -
How to include the native libraries in the Jar file?
$ tree . !"" META-INF # $"" MANIFEST.MF !"" com # $"" amazing-library # $"" AmazingLibrary.class $"" lib !"" armeabi # $"" amazing-library.so !"" armeabi-v7a # $"" amazing-library.so $"" x86 $"" amazing-library.so Advanced Topics: Native code -
How to generate the jar file in Gradle? task androidJar(type:
Jar, dependsOn: ['assemble']) { group 'Build' description ‘blah blah' from zipTree('build/intermediates/bundles/release/classes.jar') from(file('src/main/jniLibs')) { into 'lib' } } Advanced Topics: Native code -
• Embrace Gradle • Explore Gradle plugins • Automate your
tests Takeaways -
• Embrace Gradle • Explore Gradle plugins • Automate your
tests • Bintray is the go-to solution for publishing Takeaways -
• Embrace Gradle • Explore Gradle plugins • Automate your
tests • Bintray is the go-to solution for publishing • Writing libraries rocks! Takeaways