A Deep Dive into Open Source Android
DevelopmentDavid Wu@wuman
blog.wu-man.com
Taipei Google Technology User Group (2013/01/02)
Taipei Open Source Software User Group (2012/12/18)
元智大學資工學系 開放源碼於行動終端之發展講座 (2012/12/07)
1
about.me/wuman2
Overview
• Why use open source?
• Popular open source Android libraries
• Why open source?
• How to open source
• Conclusion
3
Why use open source?
4
Better Quality
• Developed by many passionate developers
• Innovation and enhancements over time
• Improvements and bug fixes by more people
• Closest to user needs
5
Freedom
• Make custom changes to tailor to own needs
• Good open source software usually adheres to open standards and promotes interoperability
6
Learn from the Masters
• Open source developers are usually good at what they do
• The fastest way to improve is to learn from reading their code
• Discussions are usually carried out in the open via mailing lists
7
Not Possible Otherwise
• It is much harder to develop an Android app without using open source software
• Platform compatibility
• UI compatibility
8
Android app development is
NOT easy!
9
Apps targeting the widest audience need to care about platform compatibility
Jelly Bean
Ice Cream Sandwich
HoneycombGingerbread
Froyo
Eclair & olderVersion Codename API Distribution
1.5 Cupcake 3 0.1%
1.6 Donut 4 0.3%
2.1 Eclair 7 2.7%
2.2 Froyo 8 10.3%
2.3 - 2.3.2Gingerbread
9 0.2%
2.3.3 - 2.3.7Gingerbread
10 50.6%
3.1Honeycomb
12 0.4%
3.2Honeycomb
13 1.2%
4.0.3 - 4.0.4 Ice Cream Sandwich 15 27.5%
4.1Jelly Bean
16 5.9%
4.2Jelly Bean
17 0.8%
10
UI Requirements for Featured Apps
• Follow Android Design guidelines
• Navigation
• Action Bar
• Use common UI patterns and icons
11
Action Bar Incompatibility
• Before 3.0, there was no common pattern or API for in-app navigation.
• Action Bar API and pattern guidelines (tablet-only) are introduced in ICS.
• Additional API changes for the phone are introduced in Jelly Bean.
12
Theme Incompatibility
• There is not a common cross-platform default theme for developers to derive from.
13
Common UI Pattern Implementations
• Some common UI patterns are not provided as part of the Android framework.
• Pull-to-refresh ListView
• Sliding Drawer Menu (ViewDeck)
14
Common Tools and Usage Patterns
• Some common tools and usage patterns are not provided as part of the Android framework.
• LRU cache that persists to disk
• Image loading with cache support
• Logging and user feedback support
15
Popular Open Source Libraries
16
UI and Compatibility
17
ActionBarSherlock
http://actionbarsherlock.com/
18
Action Bar General Layout
• App icon and “up” affordance
• View switch control
• Action buttons
• Action overflow
19
Split Action Bar
• Main action bar
• Top bar via tabs or spinner
• Bottom bar with action buttons and overflow
20
Contextual Action Bars
21
HoloEverywhere
https://github.com/ChristopheVersieux/HoloEverywhere
• Back ports the Holo themes from Jelly Bean to Eclair and above
22
NineOldAndroids
• Back ports the android.animation.* API from Honeycomb to all previous platforms
• Drawing vs. View properties
http://nineoldandroids.com/
ObjectAnimator.ofFloat(myObject, "translationY", -myObject.getHeight()).start();
23
UnifiedPreference
https://github.com/saik0/UnifiedPreference
24
Android Support Package
• Back ports multi-pane Fragment support from Honeycomb to Donut
25
Android Support Package
• Includes ViewPager, PagerTitleStrip, PagerTabStrip implementations
26
Android Support Package
• Back ports all Notification features from Jelly Bean to Donut
27
Android Support Package
• Back ports asynchronous background Loader support from Honeycomb to Donut
• Includes implementation for a memory-based LruCache
28
Android-MenuDrawer
https://github.com/SimonVT/android-menudrawer
29
Android-PullToRefresh
https://github.com/chrisbanes/Android-PullToRefresh
30
Polaris
https://github.com/cyrilmottier/Polaris
31
Crouton
https://github.com/keyboardsurfer/Crouton
32
Android-Query
http://code.google.com/p/android-query/
• Enables easier UI manipulation via method chaining
AQuery aq = new AQuery(view); aq.id(R.id.icon) .image(R.drawable.icon) .visible() .clicked(this, "someMethod");aq.id(R.id.name) .text(content.getPname());aq.id(R.id.time) .text(FormatUtility.relativeTime( System.currentTimeMillis(), content.getCreate())) .visible();aq.id(R.id.desc) .text(content.getDesc()) .visible();
33
Caching and Networking
34
DiskLruCache
• Back ports the DiskLruCache from Ice Cream Sandwich to all versions of Android
https://github.com/JakeWharton/DiskLruCache
35
TwoLevelLruCache
• A two-level LRU cache composed of
• first level memory-based LruCache
• second level disk-based DiskLruCache
http://wuman.github.com/TwoLevelLruCache/
36
AndroidImageLoader
• Asynchronous image loading
• Images are downloaded and saved to TwoLevelLruCache via a pool of background threads
• Supports Bitmap transformations
http://wuman.github.com/AndroidImageLoader/
37
HttpResponseCache
• Back ports the persistent HttpResonseCache from Ice Cream Sandwich to all versions of Android
• Provides transparent and automatic persistent caching of HTTP and HTTPS requests that use the HttpUrlConnection class
https://github.com/candrews/HttpResponseCache
38
HTTP-Request
• Provides a simpler and easier interface to HttpURLConnection
• Uses method chaining
https://github.com/kevinsawicki/http-request
HttpRequest.get("http://google.com").receive(System.out);
39
Concurrency and Communication
40
Tape
• Provides a persistent task queue
http://square.github.com/tape/
TaskQueueadd()
peek()remove()
Client UI
Server
ServiceUploadTask UploadTask
41
Otto
• An event bus forked from EventBus of Google Guava targeting the Android platform
http://square.github.com/otto/
Bus
Fragment Fragment
FragmentFragment
Service Activity
Publish Subscribe
42
Data Representation and Processing
43
GSON
• POJO to JSON bi-directional conversion
• Built-in serializers and deserializers for primitive data types
• Supports extensions for complex objects
http://code.google.com/p/google-gson/
44
Jackson JSON Processor
• Streaming JSON parser and serializer
• Supposedly faster than the built-in ones
http://wiki.fasterxml.com/JacksonHome
45
Json-Path
• XPath- and jQuery-like selector for JSON
{ "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fianceection", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99, "isbn": "0-553-21311-3" } ], "bicycle": { "color": "red", "price": 19.95 } }}
String author = JsonPath.read(json, "$.store.book[1].author");
http://code.google.com/p/json-path/
46
jOOX - Java Object Oriented XML
• XML manipulative parser with selector syntax
• XML document creation
https://github.com/jOOQ/jOOX
47
JSoup
• HTML parser for Java using jQuery-like selector syntax
• Manipulates HTML elements, attributes and text
• Prettifies HTML
http://jsoup.org/
48
OrmLite
• ORM library that persists POJO to SQLite databases
http://ormlite.com/
public class SimpleData {
! @DatabaseField(generatedId = true)! int id;! @DatabaseField(index = true)! String string;! @DatabaseField! long millis;! @DatabaseField! Date date;! @DatabaseField! boolean even;
! SimpleData() {! ! // needed by ormlite! }
! public SimpleData(long millis) {! ! this.date = new Date(millis);! ! this.string = (millis % 1000) + "ms";! ! this.millis = millis;! ! this.even = ((millis % 2) == 0);! }}
49
Google Guava
• Many utilities to make Java development easier
http://code.google.com/p/guava-libraries/
50
Dependency Injection
51
AndroidAnnotations
• Runtime injection of Android views, extras, system services, resources, etc.
• Method annotation to indicate which thread to run in
• Method annotation to bind event listeners to events
http://androidannotations.org/
52
RoboGuice
• Runtime injection of Android views, system services, resources, POJO, etc.
http://code.google.com/p/roboguice/
53
Dagger
• Compile-time dependency injection (binding validation) for Android
• Not as feature-rich as other dependency injection frameworks but much faster
• API very similar to Google Guice
http://square.github.com/dagger/
†54
Testing
55
Android Test Framework
• Built-in Android Test Project support
• Use AndroidTestCase to test non-visual components
• Use Instrumentation to control visual parts of an application
• Command line monkey tool to send random events to device
56
Robotium
• Black-box testing framework for Android
• Improved readability of test cases compared to standard Instrumentation tests
• Handles multiple Android activities
http://code.google.com/p/robotium/
57
Robotium
http://www.vogella.com/articles/AndroidTesting/article.html
// Check that we have the right activitysolo.assertCurrentActivity("wrong activiy", SimpleActivity.class);
// Click a button which will start a new Activity// Here we use the ID of the string to find the right buttonsolo.clickOnButton(solo.getString(R.string.button1));// Validate that the Activity is the correct onesolo.assertCurrentActivity("wrong activiy", SimpleListActivity.class);
// Open the menusolo.sendKey(Solo.MENU);solo.clickOnText("Preferences");solo.clickOnText("User");solo.clearEditText(0);Assert.assertTrue(solo.searchText(""));solo.enterText(0, "http//:www.vogella.com");Assert.assertTrue(solo.searchText("http//:www.vogella.com"));solo.goBack();
58
Mochito
• Android mocking framework
• API makes mocking tests very readable
http://code.google.com/p/mockito/
public void makePurchase(CreditCardManager creditCard) { if (creditCard.getCardType() == CREDIT_CARD_VISA) { creditCard.makePurchase(500); }}
public void testMasterCardTransaction() { CreditCardManager creditCard = Mockito.mock(CreditCardManager.class); Mockito.when(creditCard.getCardType()) .thenReturn(CREDIT_CARD_MASTER);
makePurchase(creditCard);
Mockito.verify(creditCard).getCardType(); Mockito.verifyNoMoreInteractions(creditCard);}
59
Robolectric
• Allows JVM unit testing with the JUnit4 framework
• Reduces testing time from minutes to seconds
• Intercepts Android class loading and forward method bodies to shadow objects
http://pivotal.github.com/robolectric/
60
Robolectric
http://pivotal.github.com/robolectric/
// Test class for MyActivity@RunWith(RobolectricTestRunner.class)public class MyActivityTest { private Activity activity; private Button pressMeButton; private TextView results;
@Before public void setUp() throws Exception { activity = new MyActivity(); activity.onCreate(null); pressMeButton = (Button) activity.findViewById(R.id.press_me_button); results = (TextView) activity.findViewById(R.id.results_text_view); }
@Test public void shouldUpdateResultsWhenButtonIsClicked() throws Exception { pressMeButton.performClick(); String resultsText = results.getText().toString(); assertThat(resultsText, equalTo("Testing Android Rocks!")); }}
61
User Feedback
62
ACRA
• Sends a detailed bug or crash report to Google Docs
http://acra.ch/
63
BugSense/Crittercism
• Collects bug and crash reports
• Generates analytics for crash reports
• Supports fix versioning and notifications
http://www.bugsense.com/docs/android
64
Google Analytics for Android
• Collect user engagement data and generate real time analytics
• Demo
https://developers.google.com/analytics/devguides/collection/android/v2/
65
Bootstrap Project Generator
66
Android Bootstrap
• Includes a full working implementation of
• Android support package
• android-maven-plugin
• RoboGuice
• ActionBarSherlock
• http-request
• GSON
• Robotium
• API on Parse.comhttp://www.androidbootstrap.com/
67
AndroidKickstartR
• Includes a full working implementation of
• Android support package
• android-maven-plugin
• AndroidAnnotations
• ActionBarSherlock
• NineOldAndroids
• ACRA
http://androidkickstartr.com/
68
Tools
69
Android Asset Studio
• Demo
http://android-ui-utils.googlecode.com/hg/asset-studio/dist/index.html
70
Subtle Patterns
• Collection of free tilable textured patterns
• Demo
http://subtlepatterns.com/
71
Charles
• HTTP proxy that enables developers to view all HTTP/HTTPS traffic between the device and the Internet
http://www.charlesproxy.com/
72
Others
73
More Detailed Listing
• App Dev Wiki http://appdevwiki.com/wiki/show/HomePage
• The Ultimate Android Library http://www.theultimateandroidlibrary.com/
• AppBrain Android Developer Tools http://www.appbrain.com/stats/libraries/dev
74
Why open source?
75
Better App Quality
• Normally for various practical reasons we don’t open source the entire app
• Open source useful components within the app into a library
• More debugging for you
• The process of open sourcing forces you to rethink your architecture critically
76
Reciprocity
• A way to give back to the community
• Feels good
77
Portfolio Buildup
• GitHub, not LinkedIn
78
Grow Faster
• The more you engage in the open source community, the faster you learn and grow as a tech professional.
• The process of open sourcing encompasses almost all areas of software development.
79
Better World
• What goes around comes around
• The template for this Keynote presentation is derived from an open source project!
https://github.com/JakeWharton/AndroidDesignKeynoteTheme
80
How to Open Source
81
Disclaimer
What follows is based on the presentation “Effective Open Source” given by Jake Wharton and additionally, a more elaborate presentation based on my own experiences.
https://github.com/JakeWharton/EffectiveOpenSource
82
Component Identification
• Identify the part of your app that can be extracted out as an isolated, reusable component.
• The component should serve to do a focused task very well.
83
Code Abstraction
• Extract the component into a separate package or module and expose only via a small set of public API.
• This is kind of like refactoring. The app should continue to work as expected and the module should be treated just like an external dependency.
• Reiterate the refactoring step several times until
• the exposed public API is minimal and clean
• the client code has good readability
84
Library Project Directory Structure
• Make the module either an independent Java library project or an Android library project depending on whether Android resources are needed in the library.
• Follow a common directory structure as defined in a maven archetype:
• org.apache.maven.archetypes/maven-archetype-quickstart
• de.akquinet.android.archetypes/android-release
85
Android Library Project Directory Structure
library/ Android Library project
test/ Android Test project
samples/ Samples project (Android project)
README Project’s readme
LICENSE Project’s license
NOTICE Notices and attributions required by libraries that the project depends on
86
Java Library Project Directory Structure
library/ Java library project
library/src/main/java/ Java library sources
library/src/test/java/ Test sources
samples/ Samples project (Android project)
README Project’s readme
LICENSE Project’s license
NOTICE Notices and attributions required by libraries that the project depends on
87
Include Tests
• Good libraries are always bundled with tests. It gives people confidence and ensures quality.
• Tests are never enough. Write as many as you can think of.
• Ensure all the tests are passed.
88
Code Quality and Style
• Standardize code conventions.
• Enforce coding style at compile time by using Checkstyle for Java.
• This ensures that future patches have a consistent coding style.
89
Inclusion of Examples
• Add at least one or more working examples.
• Separate examples to showcase a specific aspect of the library.
90
Documentation
• Make sure all exposed public APIs have documentation that follow the javadoc syntax.
• Ensure that a javadoc jar is generated for each release. This is best achieved via the maven-javadoc-plugin.
91
README
• Write a README that follows the Markdown syntax.
• It should include the following sections:
• project description
• how to obtain the library
• snippets of quick start sample code
• external dependencies
• license information
http://daringfireball.net/projects/markdown/syntax
92
Git Ignore
• Always include a .gitignore file to keep the source tree clean. There are many samples online.
• In general exclude these files:
• IDE-specific files (Eclipse.gitignore)
• OS-specific files (OSX.gitignore)
• Android outputs and binaries (Android.gitignore)
• Java compiled classes and package files (Java.gitignore)
https://github.com/github/gitignore
93
Build Management Tool
• Use a build management tool to help people painlessly build your code without needing to know much about the library.
• Most Android people use Maven.
• Write the configuration file that works with your build management tool. In the case of Maven it should be pom.xml.
94
Maven
• Install the latest com.jayway.maven.plugins.android.generation2/android-maven-plugin.
• The packaging for the library project should be either jar or apklib, depending on whether your library is a Java project or an Android Library project.
• The packaging for the samples project should be apk.
http://code.google.com/p/maven-android-plugin/
95
Build with Maven
• Make sure the build management tool builds your project correctly.
• For Maven, you should be able to run the following without errors:
http://maven.apache.org/pom.html
$ mvn clean install
96
Continuous Integration
• Setup continuous integration. The simplest open source service is Travis. Have your GitHub repository linked to Travis by activating a hook.
• Write the configuration file .travis.yml.
https://travis-ci.org/
language: java
notifications: email: false
before_install: -‐ wget http://dl.google.com/android/android-‐sdk_r20.0.3-‐linux.tgz -‐ tar -‐zxf android-‐sdk_r20.0.3-‐linux.tgz -‐ export ANDROID_HOME=~/builds/username/projectName/android-‐sdk-‐linux -‐ export PATH=${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-‐tools -‐ android list sdk -‐ android update sdk -‐-‐filter 1,2,3 -‐-‐no-‐ui -‐-‐force
97
Site Setup
• Setup a project web site.
• If you’re lazy and wish to use just the GitHub README, then the best alternative is the DocumentUp service.
• Configure Travis indicator and Google Analytics tracking for the web site.
http://documentup.com/
<script src="https://raw.github.com/jeromegn/DocumentUp/master/documentup.min.js"></script><script>
DocumentUp.document({repo: "wuman/AndroidImageLoader",name: "AndroidImageLoader",twitter: ["wuman"],issues: true,travis: true,google_analytics: "UA-‐4156099-‐13"
});</script>
98
Issue Management
• GitHub has built-in issue management support, although many developers consider Google Code to be better for issue management.
• Quick triage of issues
99
Mailing List
• Setup a Google Groups mailing list for the project so that people can have a place for discussion.
100
Downloadable Published Packages
• Always make the released packages (usually jars) available for download. Use the com.github.github/downloads-maven-plugin.
• If your library has dependencies, it is best to release a separate jar with dependencies using the maven-assembly-plugin.
https://github.com/github/maven-plugins
101
Release to Sonatype and Maven Central
• Sonatype provides an OSS repository hosting service for free. You can deploy snapshots and releases so that they are also synced periodically to Maven Central.
• Follow their detailed guide.
• In the end you should be able to deploy your project with:
https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide
$ mvn clean package release:prepare$ mvn release:perform
102
Promote the Library
• Write a blog post to talk about the motivations behind the project, technical explanations and sample code snippets. Also direct readers to the project page.
• Publish your project everywhere: social networks, related communities, etc.
• Encourage people to use and contribute.
• Ask for feedback.
103
Join the Android Community
• Follow these smart people on Google+:
• Googlers
• Chet Haase, Dan Morrill, Dianne Hackborn, Jean-Baptiste Quéru, Jeff Sharkey, Kirill Grouchnikov, Matias Duarte, Patrick Dubroy, Reto Meier, Roman Nurik, Romain Guy, Tor Norbye, Xavier Ducrohet
• Android Developers
• Community
• Bob Lee, Chris Banes, Cyril Mottier, David Wu (shameless plug), Eric Burke, Jake Wharton, Jesse Wilson, Lars Vogel, Steve Kondik
104
Conclusion
105
106
“Only the children know what they are looking for.”
The Little Prince
106
Thank you
107
Q & A
108