New Android build system
Flavored with Roboguice and Robolectric

Andreas Würl, Thomas Endres
Ultracode Meetup, 2013-11-13
Overview
A short introduction
New Android build system
Roboguice
Robolectric
The speakers
Andreas Würl is an IT consultant for TNG Technology
consulting currently working in Unterföhring. In his free...
Our apps
Blitzortung
Simple to use map based application visualizing real time
lightning data provided by blitzortung.org....
Overview
A short introduction
New Android build system
Roboguice
Robolectric
Building Android applications
Old school

Based on Ant
No built-in dependency management
Quite inflexible
Using old built-...
The build xml file
<target name="compile" depends="-resource-src, -aidl"
description="Compiles project's .java files into ...
Building Android applications
The alternative

Based on Maven → Maven plugin
Allows for dependency management
A lot more f...
The POM file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://w...
Building Android applications
The new way

Based on Gradle → Gradle-Plugin
Built-in dependency management
Using common Jav...
The Gradle build file
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:grad...
Android Studio
Android Studio
The facts

Based on IntelliJ
Ready to use
No additional plugins needed
Brings shortcuts for AVD and SDK man...
Overview
A short introduction
New Android build system
Roboguice
Robolectric
What the heck is Roboguice?
A dependency injection container
An implementation of JSR 330
A fork of the Guice framework fo...
Dependency injection

Instead of taking

public class MainActivity extends Activity{
private LocationManager locationManag...
Principles of DI
Don't let a class create objects on its own
Instead, pass them the objects they need
Then you can exchang...
How can you inject objects?
Through the constructor:

@Inject
public MainActivity(LocationManager locationManager) {
// .....
What can be injected?
Arbitrary objects with a zero-arg constructor
Objects with a constructor managed by Roboguice
Views:...
Robo* classes
For DI to work, you have to extend the robo classes:
Use them instead of the standard Android classes
RoboAc...
Injecting providers:
Sometimes, you need more than one object of a class
public class SomeObjectProvider implements Provid...
Injecting injectors
You can also inject an injector
Then, you can get arbitrary objects out of the injector
@Inject
privat...
Configuration
By defining a module, you can configure the objects injected
public class SomeModule extends AbstractModule ...
Integrate Roboguice (1)
Add roboguice to the compile dependencies:
// build.gradle
dependencies {
// ...
compile 'roboguic...
Integrate Roboguice (2)
Configure the module:
public class SomeModule extends AbstractModule {
@Override
protected void co...
Overview
A short introduction
New Android build system
Roboguice
Robolectric
Android testing
in new build system

Based on JUnit3
Requires separate test project
Requires emulator or device for execut...
Can I run tests locally?
No. It's impossible!
Any method of the SDK will throw the following
exception when called:
java.l...
What the heck is Robolectric?
Android SDK wrapper/enabler for local test execution
Just another dependency of your project...
What do I get?
Tests are running on the dev machine
Current version of JUnit 4 is used
Any Mock- or Match-Framework can be...
How do I enable Robolectric?
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.bui...
How do I implement a test?
Just use the RobolectricTestRunner
@RunWith(RobolectricTestRunner.class)
class SomeActivityTest...
Basic concepts
Shadows

TextView textView = (TextView) mainActivity.findViewById(R.id.helloWorld);
final ShadowTextView sh...
Basic concepts

Robolectric builds up a full application context
Activities can be built
activity = Robolectric.buildActiv...
But ...

Android Studio integration is not yet available
Tests can be run via gradle task 'test'
> gradle test

IDE suppor...
Summary

The new build system is a lot more flexible than the old one
Android Studio is a cool new tool for app developmen...
Thank you!

Are there any questions?

andreas.wuerl@tngtech.com, thomas.endres@tngtech.com
[Ultracode Munich #4] Short introduction to the new Android build system including Android Studio, Roboguice and Robolectric
[Ultracode Munich #4] Short introduction to the new Android build system including Android Studio, Roboguice and Robolectric
[Ultracode Munich #4] Short introduction to the new Android build system including Android Studio, Roboguice and Robolectric
[Ultracode Munich #4] Short introduction to the new Android build system including Android Studio, Roboguice and Robolectric
[Ultracode Munich #4] Short introduction to the new Android build system including Android Studio, Roboguice and Robolectric
Upcoming SlideShare
Loading in...5
×

[Ultracode Munich #4] Short introduction to the new Android build system including Android Studio, Roboguice and Robolectric

1,040

Published on

By Thomas Endres & Andres Würl both Senior Consultant from TNG Technology Consulting https://www.tngtech.com

Join the Ultracode Munich meetup: http://www.meetup.com/Ultracode-Munich/

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,040
On Slideshare
0
From Embeds
0
Number of Embeds
7
Actions
Shares
0
Downloads
13
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

[Ultracode Munich #4] Short introduction to the new Android build system including Android Studio, Roboguice and Robolectric

  1. 1. New Android build system Flavored with Roboguice and Robolectric Andreas Würl, Thomas Endres Ultracode Meetup, 2013-11-13
  2. 2. Overview A short introduction New Android build system Roboguice Robolectric
  3. 3. The speakers Andreas Würl is an IT consultant for TNG Technology consulting currently working in Unterföhring. In his free time, he is contributing to the Blitzortung app available for Android and in development for iOS. Thomas Endres is also an IT consultant for TNG Technology consulting. In his free time, he is developing software for controlling drones with bare hands, building apps and contributing to HTML5 frameworks.
  4. 4. Our apps Blitzortung Simple to use map based application visualizing real time lightning data provided by blitzortung.org. The current thunderstorm situation at your fingertips. Be Quiet - The noise alert Whether you work in an office or in a class room, Be Quiet will help you reduce noise. When the volume is too high, it will blink and play a siren sound.
  5. 5. Overview A short introduction New Android build system Roboguice Robolectric
  6. 6. Building Android applications Old school Based on Ant No built-in dependency management Quite inflexible Using old built-in library versions No support for real unit tests Test project needed for instrumentation tests
  7. 7. The build xml file <target name="compile" depends="-resource-src, -aidl" description="Compiles project's .java files into .class files"> <!-- ... --> <javac encoding="ascii" target="1.5" debug="true" extdirs="" destdir="${out.classes.absolute.dir}" bootclasspathref="android.target.classpath" verbose="${verbose}" classpath="${extensible.classpath}" classpathref="android.libraries.jars"> <src path="${source.absolute.dir}" /> <src path="${gen.absolute.dir}" /> <src refid="android.libraries.src" /> <classpath> <fileset dir="${external.libs.absolute.dir}" includes="*.jar" /> <fileset dir="${extensible.libs.classpath}" includes="*.jar" /> </classpath> </javac> </target> Customization is very difficult
  8. 8. Building Android applications The alternative Based on Maven → Maven plugin Allows for dependency management A lot more flexible → But still far from being perfect Real unit tests are possible Still using a test project for instrumentation tests
  9. 9. The POM file <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.tngtech.internal.android</groupId> <artifactId>android-demo</artifactId> <version>1.0-SNAPSHOT</version> <packaging>apk</packaging> <dependencies> <dependency> <groupId>com.google.android</groupId> <artifactId>android</artifactId> <version>${platform.version}</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>com.jayway.maven.plugins.android.generation2</groupId> <artifactId>android-maven-plugin</artifactId> <version>3.7.0</version> <configuration> <androidManifestFile>${project.basedir}/AndroidManifest.xml</androidManifestFile> <assetsDirectory>${project.basedir}/assets</assetsDirectory> <resourceDirectory>${project.basedir}/res</resourceDirectory> <sdk><platform>18</platform></sdk> </configuration> </plugin> </plugins> </build> </project>
  10. 10. Building Android applications The new way Based on Gradle → Gradle-Plugin Built-in dependency management Using common Java patterns → But flexible enough to change that Real unit tests through plugins Instrumentation tests within the same project
  11. 11. The Gradle build file buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.6.+' } } apply plugin: 'android' repositories { mavenCentral() } dependencies { // Put all dependencies here } android { compileSdkVersion 18 buildToolsVersion "18.1.1" defaultConfig { minSdkVersion 18 targetSdkVersion 18 } }
  12. 12. Android Studio
  13. 13. Android Studio The facts Based on IntelliJ Ready to use No additional plugins needed Brings shortcuts for AVD and SDK manager Out of the box support for the new build system Possibility to migrate old projects
  14. 14. Overview A short introduction New Android build system Roboguice Robolectric
  15. 15. What the heck is Roboguice? A dependency injection container An implementation of JSR 330 A fork of the Guice framework for the JDK Easy to configure and to use
  16. 16. Dependency injection Instead of taking public class MainActivity extends Activity{ private LocationManager locationManager; public void onCreate(Bundle savedInstance) { // ... locationManager = (LocationManager) getSystemService(Activity.LOCATION_SERVICE); } } be given public class MainActivity extends RoboActivity{ @Inject private LocationManager locationManager; public void onCreate(Bundle savedInstance) { // ... } }
  17. 17. Principles of DI Don't let a class create objects on its own Instead, pass them the objects they need Then you can exchange them for test purposes You can pass in test doubles But you can also exchange the "real" object easily Loose coupling becomes a reality
  18. 18. How can you inject objects? Through the constructor: @Inject public MainActivity(LocationManager locationManager) { // ... this.locationManager = locationManager; } Into the field itself: @Inject private LocationManager locationManager; Into a property: @Inject public void setLocationManager(LocationManager locationManager) { this.locationManager = locationManager; }
  19. 19. What can be injected? Arbitrary objects with a zero-arg constructor Objects with a constructor managed by Roboguice Views: @InjectView(R.id.specialButton) private Button button; Resources: @InjectResource(R.drawable.specialPicture) private Drawable picture; A lot of standard Android objects: LocationManager, AssetManager, ... AlarmManager, NotificationManager, ... Vibrator
  20. 20. Robo* classes For DI to work, you have to extend the robo classes: Use them instead of the standard Android classes RoboActivity instead of Activity RoboListActivity instead of ListActivity RoboService instead of Service RoboFragment instead of Fragment ...
  21. 21. Injecting providers: Sometimes, you need more than one object of a class public class SomeObjectProvider implements Provider<SomeObject> { @Inject private SomeOtherObject someOtherObject; @Override public SomeObject get() { return new SomeObject(someOtherObject); } } private class SomeObjectUser { @Inject private Provider<SomeObject> someObjectProvider; private SomeObject getObject() { return someObjectProvider.get(); } }
  22. 22. Injecting injectors You can also inject an injector Then, you can get arbitrary objects out of the injector @Inject private Injector injector; public <T> T giveMeAnObjectOf(Class<T> clazz) { return injector.getInstance(clazz); }
  23. 23. Configuration By defining a module, you can configure the objects injected public class SomeModule extends AbstractModule { @Override public void configure() { // Bind an interface to a specific class bind(SomeInterface.class).to(SomeImplementation.class); // Bind a standard provider to the class bind(SomeClass.class).toProvider(SomeClassProvider.class); } } Modules are discovered via "roboguice_modules.xml" <?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="roboguice_modules"> <item>com.mypackage.SomeModule</item> </string-array> </resources>
  24. 24. Integrate Roboguice (1) Add roboguice to the compile dependencies: // build.gradle dependencies { // ... compile 'roboguice:roboguice:2.+' } Extend the Robo* classes in your objects: public class SomeActivity extends RoboActivity { // ... } Inject your dependencies: @Inject private SomeObject someObject;
  25. 25. Integrate Roboguice (2) Configure the module: public class SomeModule extends AbstractModule { @Override protected void configure() { bind(SomeClass.class).toProvider(SomeClassProvider.class); // ... } } Register the module: <?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="roboguice_modules"> <item>com.mypackage.SomeModule</item> </string-array> </resources> Write unit tests: public class SomeActivityTest { // How to do that? }
  26. 26. Overview A short introduction New Android build system Roboguice Robolectric
  27. 27. Android testing in new build system Based on JUnit3 Requires separate test project Requires emulator or device for execution Lacks real mocking But initial support for some frameworks
  28. 28. Can I run tests locally? No. It's impossible! Any method of the SDK will throw the following exception when called: java.lang.RuntimeException: Stub! at android.* Why is that? Android SDK jars for development only contain method stubs Is there a solution? Yes! Use Robolectric
  29. 29. What the heck is Robolectric? Android SDK wrapper/enabler for local test execution Just another dependency of your project Sometimes dependency order is important Uses some magic to enable use of the stubbed SDK jars Unfortunately not yet complete
  30. 30. What do I get? Tests are running on the dev machine Current version of JUnit 4 is used Any Mock- or Match-Framework can be used Can be used in parallel with instrumentation tests
  31. 31. How do I enable Robolectric? buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.6.+' classpath 'com.squareup.gradle:gradle-android-test-plugin:0.9.+' } } apply plugin: 'android' apply plugin: 'android-test' ...
  32. 32. How do I implement a test? Just use the RobolectricTestRunner @RunWith(RobolectricTestRunner.class) class SomeActivityTest { @Before public void setUp() { // Preparation for every test } @Test public void testSomething() { // Your test code belongs here assertThat(1, is(not(2)); } }
  33. 33. Basic concepts Shadows TextView textView = (TextView) mainActivity.findViewById(R.id.helloWorld); final ShadowTextView shadowTextView = Robolectric.shadowOf(textView); assertThat(shadowTextView.innerText(), is("Hello World!")); Implementation in Robolectric @Implements(TextView.class) public class ShadowTextView extends ShadowView { @RealObject TextView realTextView; @Override public String innerText() { CharSequence text = realTextView.getText(); return (text == null || realTextView.getVisibility() != View.VISIBLE) ? "" : text.toString(); } @Implementation public void setPaintFlags(int paintFlags) { this.paintFlags = paintFlags; } }
  34. 34. Basic concepts Robolectric builds up a full application context Activities can be built activity = Robolectric.buildActivity(MainActivity.class).create().get(); Testing resource access is possible as well Resources resources = Robolectric.application.getResources(); assertThat(resources.getColor(R.color.Red), is(0xffff0000)); Modify preferences for tests SharedPreferences defaultSharedPreferences = ShadowPreferenceManager.getDefaultSharedPreferences( Robolectric.application); defaultSharedPreferences.edit() .putBoolean("test", true).putFloat("limit", 1.0f).apply();
  35. 35. But ... Android Studio integration is not yet available Tests can be run via gradle task 'test' > gradle test IDE support only through ugly hacks
  36. 36. Summary The new build system is a lot more flexible than the old one Android Studio is a cool new tool for app development It comes bundled with the SDK, you can start development immediately But there are still some issues with it Roboguice makes it possbible to decouple your application Robolectric can be used for local test execution
  37. 37. Thank you! Are there any questions? andreas.wuerl@tngtech.com, thomas.endres@tngtech.com
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×