Droidcon UK – day 2

9.00 What’s new in Android

Company: Google, Speaker: Chet Haase

New Nexus 6 and 9 devices. Android Studio 1.0 Beta.

Material design: Tangible surface, easy ways of branding, meaningful motion, adaptive design. Also see the design documentation.

UI toolkit: New theme (material), theme colours (all assets are greyscale and can be tinted), dynamic colors (pallet API). New (material) widgets: RecyclerView, (Stacker)GridView, CardView.

Graphics: Real-time shadows relative to light source (60fps), outlines for Views. Render thread.

Material animations: Activity and Fragment transitions. Animation curves. Animated reveal. Animated vector Drawable.

System changes: Document-centric apps, new (material) Notifications, heads-up Notifications. Notifications on lock-screen.

Media: OpenGL ES 3.0, Android extension pack, Camera & Audio: raw input, MediaSession, MediaBrowser.

ART is now the runtime for L.

Project Volta: optimising battery usage. New service: BatteryStats. Use Historian (on Github) to analyse results.

10.00 Papercraft

Company: Google, Speakers: Chris Banes, Nick Butcher, Slides on G+.

Reasons behind Material Design:

  • Providing a coherent cross-platform experience.
  • A more flexible design system for Android.
  • A rational approach to visual, interaction and motion design.

Tangible surfaces
UI as digital paper. Adding z-depth, signifying UI element importance.

Z = Elevation + TranslationZ.
New “stateListAnimator” XML-attribute.

Extend the ViewOutlineProvider class to create any clipping.

Print-like design
Refined typography, using typography to provide the app structure. Typographic scale provides the standard scales.
There is a new TextAppearance.AppCompat style.

Using bold colours, take the brand colour and use the complementary as accent.
Styling using:

  • colorPrimary
  • colorPrimaryDark
  • colorAccent

Theme.AppCompat provides the tinting as well (API 7+).

Content can provide colours. To generate the colours, use the Palette class:

  1. Palette.generate(bitmap)

The palette generation takes roughly 30ms, so run it on a separate thread.

Meaningful motion
To enable Activity transitions, add “android:windowContentTranstion” attribute to your theme. Next, Define a shared element. And finally, start the Activity.

Asymmetric motion, user initiates motion. To create this, use the RippleDrawable (“ripple” XML-tag).
Circular Reveal, use ViewAminationUtils.createCircularReveal(…).

Adaptive design
Making apps looks good on various screen sizes.
Think in Keylines, Increments, blocks.

New more flexible Toolbar (based off Actionbar).
Add “Toolbar” XML-tag in your layouts. Also available in AppCompat.

12.00 How to Build a One Man Band

Speaker: Nicoll Hunt

You’ll need: Time, money, skillz.

Stop wasting time on unrelated things. Use self-funding and/or crowd funding (like kickstarter). Work with your limitations, accept them, don’t try to fight them. Learn to deal with criticism.

13.45 Graphical Magic – Styling Android

Speaker: Mark Allison, Blog: blog.stylingandroid.com

Increasing performance by reducing GPU overdraw. Turn “GPU Overdraw” on in device developer settings to see trouble areas. Flatten any Views with transparent backgrounds. Hook into the “onPreDraw” method.

Use the ColorMatrix class to manipulate colour information. Use a paint Shader to apply effects on text, the same way you can create outlines (a.k.a image masks).

Applying blur effects with RenderScript. To avoid artefacts, add a margin and crop it off later.

Don’t forget to recycle() any temp Bitmaps.

14.35 Rx-Fy all the things!

Company: Novoda, Speaker: Benjamin Augustin

Reactive Extensions Java project: RxJava on Github.

Important Operators/methods to remember:

  • map
  • flatMap
  • onErrorResumeNext()

To perform multiple operations / create a pipeline, chain multiple of the above Operators.

Novoda working on a set of RxJava tools for Android.

RxAndroid – Collection of tools for Android created by SoundCloud.

For a quick intro into RxJava, have a look at the RxJava workshop in the Novoda workshops repo.

15.45 “Project Volta”
Or “Getting By With Less Than 1.21 Gigawatts”

Company: Commonsware, Speaker: Mark Murphy

Discussing the new JobScheduler class. All slides can be found at commonsware.com/presos/droidconUK2014.

BatteryHistorian is a python script hosted on the Google Github.

16.35 Deep Dive into the Gradle-based Android Build System

Company: Gradleware, Speaker: Etienne Studer

The Gradle DSL configuration is mapped to the AppExtension object.

When creating your own tasks, make sure to define inputs and outputs so the task can be skipped when there is no change.

Enable Gradle daemon on your local machine to cut down VM warm-up times.

17.30 Closing Ceremony

Droidcon UK – Day 1

9.00 Barcamp planning

Getting all sessions in for the day’s talks. At the end of the day there will also be an “Appcamp” to demo applications to the audience.

10.30 AIDE – Android Wear app with AIDE

Company: appfour GmbH, Speakers: Hans Kratz, Dr. Dennis Strein, Website: www.android-ide.com.

AIDE = Android Integrated Development Environment.

Applications that are “Wear enabled” contain the Wear APK inside the phone APK.

AIDE uses Gradle to package Wear. To enable Wear, add the following to your build dependencies:

  1. wearApp project(':wearable')

Google also has a lot of information on how to create wearable apps.

The presentation was followed by a live demo of how to use AIDE on a device.

11.10 Modern Testing Technologies

(or how to avoid getting murdered in your sleep by a death goblin.)

Speaker: Mr Death Goblin a.k.a. Zan Markan

Follow SOLID principles to increase your chances to catch a goblin.

Good tools for this include: Dagger (DI/IoC), Mockito (mocking), Calabash, Robotium, etc. Start using the tools before you write a single line of code.

When your project grows, allow for refactoring. Split up too big methods, classes, etc. The tests should be there to help you achieve that and keep things working.

Use CI tools, like Travis, to automatically test / build your project.

How to deal with legacy projects? Start by covering new features with tests. Cover any code related to bug fixing with tests. Little by little the coverage will get better and better.

12.05 TDD Coverage

Tools: GUnit (Unit tests), Robolectric, Mockito (Mocking), Emma (for coverage).

Performance testing with a monkey that visits every Activity, combine this with TraceView for profiling to measure memory usage, CPU, etc.

Testing the manifest: Use Robolectric to get a shadow application, fetch the package manager, check what service, receivers, etc are registered and verify that they exist.

12.45 Simple persistence with cupboard

Company: LittleRobots, Speaker: Hugo Visser, Project home: bitbucket.org/qbusict/cupboard

SQLite powered, using field names (from Models) to match columns. Simple usage example 

  1. cupboard().withDatabase(db).put(person)

14.20 Calligraphy – Fonts in styling

Company: YoYo, Speaker: Chris Jenkins, Project home: github.com/chrisjenx/Calligraphy

Simplifying using custom fonts on Android.

Example usage:

  1. <TextView ... fontPath="fonts/your_font.ttf">

15.55 Y U No craftsman!?

Company: Novoda, Speakers: Paul Blundell and Xavi Rieau

Ways to create better code / be a better craftsman.

Pair programming, best coding practices, code reviews. Care about CI, show build status (i.e. on a big screen in the office). Run static analysis reports. Test!

To make things more fun: CI Game (Jenkins plugin), creates a monthly leaderboard.

Use the latest tools with your work.

Be “agile”, build features the way they make sense. Believe in YAGNI (you ain’t gonna need it), don’t over-engineer.

Make your app awesome:

  • Get off the main thread.
  • Use Strict Mode (both in code and dev options).
  • Use “GPU Profiling” (under dev options).
  • Use “Show Overdraw”
  • Polish the app. (Lots of tips in the Android docs.)
  • Animate all the things.
  • Listen to (user) feedback.
  • Measure the data.
  • Follow the guidelines.
  • Add debug screen(s) for QA and yourself.
  • Proper versioning.
  • Hexagonal architecture.

16.30 Democamp

Showcasing the following applications

  • SkyScanner
  • DoneDeal
  • VelociCaptor
  • ???
  • Clue
  • See Speak
  • Hey Order
  • Islamic prayer times
  • Kites
  • Stay.com
  • ???
  • E-reader Open Source app

17.30 Practicing Practical Best Practices – for Software Development Practitioners

Company: Google, Speaker: Chet Haase – Process Methodologist

“Practices Make Perfection”

Traditional best practices: Code comments, Naming conventions, Simplicity, Portability. Continuous Integration, Testing, Process.

Laws of software quality:

  1. errors = (more code)^2 = e = mc^2
  2. The more bugs, the less quality.

The path to better quality software: higher quality, less bugs, fewer code.

Android reverse engineering

Often I am quite curious to see how an app is built and what tools the use under the hood. What libraries do they use, what clever tricks are used, etc, etc. Some companies will blog about this on their corporate site, others don’t. An easy way to figure things out is by reverse engineering the application.

Getting data off the phone
The first thing you need to do is get the application from your phone to your computer.

To do this, you can use the APK Extractor app.

“This application will extracts APK which is installed on android device and copy to SD card.”

From there it is a matter getting the data from the SD card. I normally just use adb pull. Have a look at the adb documentation for more details.

Decompiling
Once you have de application on your computer, there are various tools you can use to reverse engineer it.

The first step though, is to unpack the APK. Luckily this is really easy, as an APK is just a ZIP file. Extract it with your favorite ZIP-tool.

At this point all extracted data is mostly represented in binary form. Opening the AndroidManifest.xml for instance, won’t give you much information yet. This is where the various tools come in.

To “decode resources to nearly original form” you can use apktool. To decompile an application using apktool, run:

  1. apktool d name_of_apk.apk

For any additional options, have a look at the apktool documentation.

Decompiling using apktool will result in a new folder with the same name as the APK. This folder will contain all decoded data. If you open up the AndroidManifest.xml file from there, you’ll see it is now in a human-readable format. All code is decompiled to smali. Smali is disassembled code from the dex format used by Dalvik. It seems to follow the same package and class naming as the original Java code. If you want to learn more about smali, have a look at the links in the answer to “What’s the best way to learn Smali” on Stackoverflow.

If you don’t want to change any code and just want to learn about the application’s inner workings, you can make your life a little easier by using a combination of two other tools: dex2jar and jd-gui.

As the name says, dex2jar will convert a .dex file to a jar. This, again, is a fairly simple process. Running the command below will generate name_of_apk.jar. 

  1. d2j-dex2jar name_of_apk.apk

To explore the jar, open it in JD GUI. The dex2jar process does not guarantee to be able to convert everything. Sometimes you will find conversion errors in the exported code. These are indicated by a line starting with “// ERROR //”, followed by the smali code.

Recompiling
After decompiling, you can make changes to the code, recompile the application and install it on your device.

Make any modifications you want to the code and recompile using

  1. apktool b folder_of_decoded_apk

Next, sign the new application. Google has great instructions on how to sign an application, so I won’t repeat that here.

To install the new application on your phone, run

  1. adb install -r name_of_apk.apk

You will have to uninstall the original version first before you can install your modified one. This is because the version you created is signed with a different certificate.

Word to the wise

Make sure you are not breaking any laws when using reverse engineering. In some countries it is legal, in others it is illegal.

When reverse engineering is legal in the country you live in, make sure the software’s (or application’s) Terms and Conditions don’t explicitly forbid you to reverse engineer.

Even when the above hurdles are overcome, make sure to not blatantly copy and paste someone else’s code.

Android swipe to reveal

More and more Android apps seem to use a swipe-to-reveal or swipe-for-action UX pattern with ListViews. This is a nice way to give (power) users fast access to certain actions. One of the downsides is that these swipe gestures are often hard to discover.

If you want to use this technique, have a look at 47 degree’s android-swipelistview library.

I ran into a small issue when trying it out. When I was building my project, I got the following error:

  1. error: Attribute "***" has already been defined

In my case this was caused by ActionBarSherlock using the same library as the android-swipelistview project. Adding an exclusion to my Gradle build script solved this.

  1. compile ('com.fortysevendeg.swipelistview:swipelistview:1.0-SNAPSHOT@aar') {
  2.  
  3.     transitive = true
  4.     exclude group: "com.android.support", module: "appcompat-v7"
  5. }

Usage in combination with SwipeRefreshLayout

If you want this swipe library in combination with the new SwipeRefreshLayout class, there is a little more work you need to do. To facilitate this, I have forked the original project and added the functionality as suggested by Keith Thompson in the issue he opened on the project site.

I ran into another issue where both the swipe-to-reveal as the pull-to-refresh actions were performed. This would happen when the ListView was at the top, the user would swipe horizontally and then pulled down. This has been fixed in my fork too.

An example of how to hook up this functionality can be found in Keith’s fork of the android-swipelistview project. The key classes to look at are “CustomSwipeRefreshLayout” in the sample project and “RefreshSwipeListView” in the library.

Other issues

The original android-swipelistview project has some other issues too:

The fixes for these issues have been committed to my fork of android-swipelistview too.

Coveralls with Cobertura

If you want to keep track of your test coverage and/or give others insight of the test coverage you can use Coveralls.io. Assuming you have already set up Cobertura, it is quite easy to get Coveralls integrated. There is an existing Gradle plugin to convert and send Cobertura reports to Coveralls. Have a look at “Robolectric and Cobertura with Gradle“, if you want to know how to set up Robolectric and Cobertura.

Gradle setup
First add a dependency to “org.kt3k.gradle.plugin:coveralls-gradle-plugin:0.3.0″.
Apply the “coveralls” plugin.
After that make sure that the cobertura plugin generates an XML report as well. In the Cobertura configuration, add the following:

  1. coverageFormats = ["html", "xml"]

If you’re not running on Travis (pro) you may need to add a service name by specifying “service” in the coveralls plugin configuration.

Environment setup
Add a “COVERALLS_REPO_TOKEN” environment variable containing your coveralls token.

Now that everything is set up, all you need to do is run the below to send a coverage report to Coveralls.

  1. gradle coveralls

If you want to look into the Gradle Coveralls plugin in more detail, have a look at the coveralls-gradle-plugin project page.

Robolectric and Cobertura with Gradle

Recently I have been working to set up code coverage reports for an Android project using Cobertura. I had already set up Robolectric manually and there is a working Cobertura Gradle plugin available. This left me with figuring out how to hook up the two. In general the following steps are needed to use Cobertura with any testing framework:

  • Make sure you fork the JVM.
  • Point the “net.sourceforge.cobertura.datafile” system property to your “cobertura.ser” file location.
  • Add the instrumented classes to the front of the class path.
  • Add cobertura classes to the class path.

You can read more about Cobertura setup in the “Ant Task Reference” on the Cobertura Wiki.

My first problem was that the Cobertura plugin automatically adds the Java plugin. The Android plugin doesn’t play nice with the Java plugin, so that had to be solved. The solution was to put all Coberture related configuration in its own Gradle build file without the Android Gradle plugin applied. All the Cobertura plugin needs to do after all is inspect compiled (and instrumented) code.

After this it was a matter of configuring the Cobertura and Robolectric plugins correctly and running tasks in the right order.

Cobertura Gradle configuration
To be able to instrument all classes, I pointed the “coverageDirs” property to a list of build folders from my project and subprojects.
NOTE: You may need to set up the “auxiliaryClasspath” if you get some “ClassNotFoundException” errors.

If you want the source code to show up correctly in your reports, make sure to configure the “coverageSourceDirs” property.

Cobertura will inspect all classes you point to in the “coverageDirs” property. To exclude any classes generated by the Android framework, add the following to the “coverageExcludes” property:

  • “.*\\.package-info.*” for package-info files,
  • “.*\\.R.*” for generated R classes and
  • “.*BuildConfig.*” for any BuildConfig classes.

Robolectric Gradle configuration
Add the following to you Gradle build file so the instrumented classes are able to write their reports:

  1. systemProperties["net.sourceforge.cobertura.datafile"] = "your_cobertura_ser"

In the Robolectric test compile dependencies, make sure you add the path to the instrumented classes in front of everything else.

Don’t forget to add “net.sourceforge.cobertura:cobertura:2.0.3″ to your test compile dependencies as well.

Putting it all together
Now all plugin configuration is done, you can run tests and have the coverage reports generated by executing the following commands. Note that this depends on a previous “gradle assembleDebug” run.

  1. gradle clean cobertura -x generateCoberturaReport
  2. gradle robolectricTest
  3. gradle cobertura -x instrument -x copyCoberturaDatafile

The first Cobertura run will instrument all the classes, but not generate any reports. After that all Robolectric tests are run. Finally, the second Cobertura run will generate the coverage report.

I hope this helps you setting up Cobertura for your Android projects.

Privileged Aspects

When you are using Aspect-Oriented Programming with AspectJ and you want to get around Java restrictions in your Aspect, you can declare the Aspect “privileged“.

Say you perform some logging from your Aspect, but the member you want to access has no (public) accessor method. You could create a public getter method and use that. Better would be to make the Aspect privileged so it can access the member even though it is declared private. This scenario is demonstrated in the snippets below.

Given the following class “Foo”.

  1. ppublic class Foo {
  2.     private String bar;
  3.  
  4.     private void doSomething() {
  5.         bar = "bar";
  6.     }
  7. }

The Aspect would look something like this.

  1. public privileged aspect FooLogging {
  2.     protected pointcut myClass(): within(Foo);
  3.     private pointcut doSomethingMethod(): myClass()
  4.             && execution(doSomething());
  5.  
  6.     after(): doSomethingMethod() {
  7.         String value = ((Foo) (thisJoinPoint.getThis())).bar;
  8.         // Logging goes here.
  9.     }
  10. }

There is one limitation to privileged Aspects though:

Privileged aspects are not supported by the annotation style.

See “Aspect Declarations” in “Chapter 9. An Annotation Based Development Style” of the “The AspectJ 5 Dev Kit Developer’s Notebook“.

Loading Contact photos with Picasso

The Picasso image downloading library has an interesting feature that I just stumbled upon. It can load Contact photos based on a passed in Contact Uri containing the ContactsContract.Contacts.LOOKUP_KEY. It is as simple as:

  1. Uri uri = Uri.withAppendedPath(
  2.     ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
  3. Picasso.load(uri).into(myImageView);

It doesn’t seem to be mentioned on the Picasso website, but it is a very useful feature.

If you want to know exactly how Picasso loads the Contact photo, have a look at the ContactsPhotoBitmapHunter class.

Android RenderScript support library

A while back I wrote about RenderScript and the lack of a support library. Now Google has released the support library for RenderScript, making it a lot more accessible for a lot of developers.
Usage is really simple, just import the correct classes:

  1. import android.support.v8.renderscript.*;

And target Android API 18 when building:

  1. renderscript.target=18
  2. renderscript.support.mode=true
  3. sdk.buildtools=18.1.0

There are unfortunately some limitations, but nothing that’s a real show-stopper.

“Allocation.USAGE_IO_INPUT and Allocation.USAGE_IO_OUTPUT are not currently available in the RenderScript Support Library.”

“Devices running Android 4.2 and earlier will always run their RenderScript applications on the CPU, while devices running Android 4.3 or later will run their RenderScript applications on whatever processors are available on that particular device.”

“Support Library versions have to be precompiled to support all possible platforms, there is a performance hit when running the precompiled scripts compared to runtime compilation on Android 4.3.”

Read the full details in Google’s blog post.

Android fragmentation 2013

At last  year’s DroidCon in London, Robin Puthli’s talked about Device Fragmentation among Android devices. Open Signal has just posted a new visualization of device fragmentation for 2013.

Fragmentation is both a strength and weakness of the Android ecosystem. When comparisons are made between Android and iOS the issue of different API levels, and the vastly different devices running them, is often emphasised. In this report we examine the extent of Android fragmentation and analyse its impact on both users and developers.

Read the full article on opensignal.com.