Droidcon Online 2020

Almost all Droidcon events have been cancelled for 2020 due to COVID-19 and the measures the various countries have taken to battle the outbreak. To be able to continue learning in the Android field, the organizers of Droidcon have set up Droidcon Online.

Through droidcon Online, a new virtual community event series, we intend to keep on doing what we do best, which is creating a safe and fun space for the community to interact and exchange ideas and information.

online.droidcon.com

There are four topics and each will be covered extensively in a series of online talks (roughly) every other week.

  • Jetpack series
  • Multi-platform series
  • Advanced Kotlin series
  • Hands-on & in-depth series

Videos of the talks will be published after they have been presented. Below is a link to each VOD.

Jetpack Series part 1 of 3

April 23

Advanced Kotlin Series part 1 of 3

April 30

Multi Platform Series part 1 of 3

May 14

  • A Hitchhikers Guide to Kotlin Muliplatform
  • Building Multiplatform Mobile Apps in Kotlin

Cucumber & Android

A while ago, the agile/scrum team I was part of was looking for a way to record functional requirements for the app we were working on. After looking around for a bit, we came across Behaviour-Driven Development (BDD) and Cucumber.

Although documentation and automated tests are produced by a BDD team, you can think of them as nice side-effects. The real goal is valuable, working software, and the fastest way to get there is through conversations between the people who are involved in imagining and delivering that software.

Cucumber.io on BDD

Since we wanted to test the Android and iOS using the same Gherkin scenarios, we set up Cucumber together with Appium. Personally I find working with Appium too cumbersome. In a private project I’ve therefore set up Cucumber with Android and left Appium out of the equation.

In this article I’ll explain how to set up Cucumber for Android.

Set up cucumber-android

Add the “cucumber-android” library to your project:

androidTestImplementation "io.cucumber:cucumber-android:$cucumberVersion"

Custom TestRunner

To configure Cucumber we’ll create a custom “TestRunner‘:

private const val PLUGIN_KEY = "plugin"
private const val REPORTS_DIR = "reports/cucumber"

private const val REPORTER_PLUGIN_PATTERN =
    "junit:%s/cucumber-junit.xml--" +
    "html:%s/cucumber-html--" +
    "json:%s/cucumber.json"

/**
 * The CucumberOptions annotation is mandatory for exactly one of the classes in the test project.
 * Creating a custom test Runner seems the simplest way to achieve that.
 */
@CucumberOptions(
    features = ["cucumber/features"],
    glue = ["nl.ansuz.android.test"]
)
class CucumberRunner : CucumberAndroidJUnitRunner() {

    override fun onCreate(bundle: Bundle?) {
        bundle?.putString(PLUGIN_KEY, getPluginConfiguration())
        super.onCreate(bundle)
    }

    private fun getPluginConfiguration(): String {
        val path = getReportsPath()
        return REPORTER_PLUGIN_PATTERN.format(path, path, path)
    }

    private fun getReportsPath(): String =
        File(targetContext.getExternalFilesDir(null), REPORTS_DIR).absolutePath
}

Permissions

To make reporting work, we need to give our app permission to write to the external storage. Since Cucumber will run under the “androidTest” flavor, you can add the extra permissions in “src/androidTest/AndroidManifest.xml” to avoid polluting your production app with unnecessary permissions.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Now Cucumber can save test reports on the external storage.

Writing Gherkin

The next step is to write some scenarios so there is something for Cucumber to test.
The cucumber.io website comes with plenty of examples, so I’ll leave this as an exercise for the reader.

Note: The “cucumber-android” plugin expects all feature files to be created under “app/src/androidTest/assets“. You can tweak the base path by changing the “features” property of the “CucumberOptions” annotation in the custom “TestRunner” we created earlier.

Running tests

Now that everything is set up and we have a first test, we can run it. Because of the custom test runner, I had to create a Gradle task that will run instrumentation tests with it.

task runCucumberInstrumentationTests(type: Exec) {
     description 'Runs instrumentation tests with Cucumber'
     group 'verification'
     dependsOn 'installDebug', 'installDebugAndroidTest'
     commandLine 'adb', 'shell', 'am', 'instrument', '-w', 'nl.ansuz.android.test/nl.ansuz.android.test.CucumberRunner'
 }

When you run this new task, no tests pass, but the Cucumber reports are generated anyway. To make the tests pass,we have to create some “glue”.

Writing the glue

In the custom “TestRunner” we’ve also defined where the “cucumber-android” library can find the “glue” to match scenarios with step definitions.

The easiest way to write your step definitions is to annotate the appropriate methods in your Espresso tests with Cucumber annotations, e.g.

@When("the Maker starts a game")
fun startGame() {
  ...
}

Pulling Cucumber reports

Now that you have written some tests, can run them and they pass, you want to be able to have a look at the Cucumber report(s) as well. Pulling the reports is fairly simple, all we need to do is add a Gradle task that uses “adb pull” to do this for us.

task pullCucumberReports(type: Exec) {
    description 'Pulls the Cucumber reports from the emulator.'
    group 'verification'
    dependsOn 'runCucumberInstrumentationTests'

    workingDir buildDir
    commandLine 'mkdir', '-p', 'reports'
    commandLine 'adb', 'pull', '/mnt/sdcard/Android/data/nl.ansuz.android/files/reports/cucumber', 'reports'
}

The reports path is set in the “REPORTS_DIR” constant in the custom “TestRunner” from earlier. Make sure that the paths in the test runner and the Gradle task match.

Cleaning up

So far we are able to run Cucumber tests and pull the reports from the device. What is missing is a way to clean up after testing has finished. Again we’ll add a new Gradle task to do this for us.

task uninstallCucumberTest() {
    description 'Uninstalls the debug and debugAndroidTest apps.'
    group 'install'
    dependsOn 'uninstallDebug', 'uninstallDebugAndroidTest'
}

Tying it all together

Because we are good developers and we are lazy, we don’t want to execute three different Gradle tasks to run tests, pull reports and clean up. Let’s introduce one last Gradle task to make our lives even easier.

task cucumberCheck() {
    description 'Installs regular and instrumentation apps, runs Cucumber tests, pulls reports ' +
            'and then uninstall both apps.'
    group 'verification'
    dependsOn 'pullCucumberReports'
}

cucumberCheck.finalizedBy uninstallCucumberTest

I hope this helps you to get you started on using BDD for your Android project with Cucumber.

Bonus: IntelliJ / Android Studio plugins

To make working with Cucumber and Gherkin easier, you can install the following plugins for IntelliJ or Android Studio:

  • “Gherkin” which provides support for the Gherkin language.
  • “Cucumber for Kotlin” which enables Cucumber support with step definitions in Kotlin.
  • “Cucumber for Java” which enables Cucumber support with step definitions in Java.

Further reading

If you want to learn more about Cucumber, I can highly recommend reading “The Cucumber Book” by Matt Wynne and Aslak Hellesøy, with Steve Tooke.

For an introduction into BDD and Gherkin, the cucumber.io website offers a lot of documentation:

Notes

Software versions used at the time of writing:

  • Gradle: 5.2.1
  • cucumber-android version: 4.2.5

Google I/0 2019 keynote

10.00 Sundar Pichai

Keep making magic

Goal: Building a more helpful Google for everyone.
Google News “full coverage” will become a standard result for Google Search.

  • Helpful

10.10 Search

Adding camera & AR to search results. Placing 3D models in your own environment.
Google Lens now part of Assistant, Photos and Camera.

New Lens features:

  • Find menu recommendations in restaurants.
  • Text to speech.
  • Translations in situ.

10.20 Sundar Pichai

Duplex now available in 44 states in the USA.
Adding tasks on the web:

  • Rental car reservations. (Gets context information from GMail.)

10.25 Scott Huffmann – Google Assistant

Google Assistant data on your device. Process requests in near real-time.
Move AI models to the phone, data was reduced from 100 GB to 0.5 GB.
This new assistant will be available on the new Pixel phones later this year.

You are in control of your data in Google Assistant.

New feature: Driving mode. Available this summer.

10.40 Sudar Pichai – Privacy & Security

Building AI for everyone. How to make sure AI models don’t confirm bias? TCAV

Google Privacy controls enhancements

  • Accessible from profile photo. (One tab access to Google Account)
  • Manageable from search.
  • Incognito mode in Maps & Search

Use your Android phone as a security key.

Federated learning, no longer sending data to the cloud, just the model updates. So no user data is being sent.

New feature: Live caption. Runs entirely on device.

New technology: Live Relay.

New research: Project Euphonia. Voice recognition for people with a speech impediment.

11.00 Stephanie – Android

Android Q

  • Innovation
  • Security & Privacy

Innovation

Foldables from multible manufactures. Fold from phone to tablet screen. Screen continuity.

5G supported natively.

Live Captions: Instantly create captions from audio in real-time. Entirely done on device. OS wide feature.

Smart reply: Suggested replies / actions. Works for all messaging apps in Android.

Dark Theme!

Security & Privacy

Google Play Protect.

Privacy settings. All privacy settings in one place.

New location controls (in settings).

Faster security updates. OTA security updates for separate OS modules.

Android OS Framework

Last year: Wind down

Focus mode: disable apps that distract you. Coming in fall on P and Q devices.

Parental controls built into device.

11.10 Rick – Google Home

Putting people first.

Nest – The helpful home

  • Easy for everyone
  • Personal for everyone
  • Works together
  • Respects your privacy

New display: Nest Hub Max. $229

  • Camera + 10″ display.
  • Physical mic + cam off switch.
  • Face match.
  • Google Photos integration.
  • Gesture recognition.

Nest Hub: $129 and also available in NL.

Google Pixel

Pixel 3a and 3a XL, starting at $399.

11.20 Sabrina Ellis – Pixel 3a

The Pixel 3a includes a headphone jack. :p

Maps AR available today on Pixel phones.

11.30 Jeff Dean – Google AI

Building a more helpful Google for everyone.

BERT models to help understand language.

Research & Engineering: Flood forecasting.

Building the ecosystem: Google AI Impact Challenge. Announcing the 20 winners today.

11.35 Lily Peng

Applying deep learning to oncology: Lung cancer.

Google I/O keynote 2018

Pre-keynote game: g.co/worlddraw

10.00 Sundar Pichai

Recap of 2017 and looking ahead.

Opening of Google AI centres around the world. Keeping on developing machine learning and AI:

  • Publishing a paper on medical use of machine learning later in the day.
  • GBoard morse code available later today too.
  • Introducing GMail “smart compose”, rolling out this month.
  • Photos: “Suggested actions.”
  • Using T(ensor) PU 3.0, 8x more powerful than 2.0 from last year.
  • Wavenet: adding 6 new voices.

10.30 Scott Huffman – Google Assistant

Google Assistant on over 500M devices. Supports 30 languages. The aim to get more natural conversations.

  • No need to say “Hey Google” with every query: Continued conversation.
  • Multiple actions.
  • Improving family experience: Pretty please.

10.35 Lilian Rincon

Visual conversation with Google Assistant.

  • Smart displays
  • Food pick-up & delivery
  • Assistant in Navigation in Google Maps.

10.40 Sundar Pichai

AI to help set up a booking system, e.g. making an hair appointment. Google Assistant will call an actual salon and make the appointment for you. Google Duplex.

Working hard to give users back time.

Android Dashboard: Show you where (which app) you spend your time.

New Google news.

10.50 Trystan Upstill – Google News

Keep up with the news you care about

  • Briefing: top stories for you. The more you use it, the better it gets.
    • Switch to “headlines” for news from around the globe.
  • Google Material Theme.
  • Newscasts

Understand the full story

  • Full coverage: Using temporal co-locality. Everyone has access to the same information. Using trusted resources.

Enjoy and support the sources you love.

  • Newsstand
  • Subscribe with Google: Access paid content everywhere. Rolling out in the coming weeks.

Rolling out Google News on Android this week.

11.00 Dave Burke – Android

Ten years since the first Android phone.

Android P

  • AI at the core of the OS
    • Intelligence
    • Simplicity
      • M(achine) L(earning) Kit in FireBase: cross-platform.
      • Navigation update.
      • Simplified volume control
      • Rotation: New rotation button on tab bar.
    • Digital wellbeing – Sameer Samat
      • Dashboard
      • App Timer: Set time limits on apps.
      • Do Not Disturb improvements: Hide notifications.
        • Shush: Turn over phone to enter DND
      • Starred contacts
      • Wind Down

Android P Beta available today: android.com/beta.

11.20 Jen Fitzpatrick – Google Maps

  • ML to extract new addresses from Street View + satellite images.
  • New tab: “For you”, personal recommendations.
  • “Your match” score: ML to help analyse your ratings and comparing to the new recommended place.
  • Create a shortlist.

11.30 Aparna Chennapraganda – AI in camera

Walking navigation AR using VPS: Visual Positioning System.

Google Lens

  • Recognise images.
  • Integrated directly into the camera app.
  • 3 new features:
    • Smart text selections: Recognise words
    • Style match
    • Real-time results

11.40 John Krafcik – Waymo

Fully self-driving cars. Driverless transportation service, starting in Phoenix, AZ this year.

Mission: Building a better driver.

Dmitri Dolgov

Explaining where AI can help self-driving cars. Using TensorFlow and TPUs to train neural networks.

  • Perception: Using deepnet (ML) to classify objects.
  • Prediction: Behaviour prediction, e.g. a car running a red light.
  • Learn new skills: Apply a filter to drive in snow.

11.50 Jen Fitzpatrick

Closing notes:

Keep building good things (for everyone).

Separating Domain Model and Application Model

Let’s take a simple retail app as an example. The app has the following (partial) domain model:

It can be quite tempting to use a domain model as an application model (as in the “M” in MVC). Your application obviously needs to use the data presented in the domain model. At first, it may seem logical to access this data directly, e.g. for showing a product name on a product details page. There are several problems with this approach though.

The domain model may be too verbose for your application’s needs. Let’s say you don’t care about the image details, but only want the URL. The app may also want to check to see if a product has an image associated with it before trying to display it. To solve this, the Product and Image objects above can be combined into one, like below.

Another benefit is that you keep things DRY. The validation logic is not repeated in various classes (think different Presenters in the MVP pattern).

To facilitate the conversion from domain model to app model, you could introduce a converter class. Something like the below.

  1. public class ModelConverter {
  2.     public AppProduct convertProduct(DomainProduct product) {
  3.         // Imagine a nice implementation here...
  4.         return appProduct;
  5.     }
  6. }

During conversion you can also do some more data validation to make sure your app doesn’t break when back-end data is incomplete. In this example, for instance, you shouldn’t rely on the image always being populated in the Product object.

All in all, separating your domain model from your application model will help you build a more stable app, trim data floating around and reduce code duplication (by centralising data validation).

Certificate pinning with OkHttp

A while back I wrote about “Using SSL right on Android“. If you are using OkHttp and/or Retrofit, this should be quite simple to implement. You can use the CertificatePinner class when building your OkHttpClient instance.

Example:

  1. CertificatePinner certificatePinner = new CertificatePinner.Builder()
  2.   .add("example.com", "your_pin")
  3.   .build();
  4.  
  5. new OkHttpClient.Builder()
  6.   .certificatePinner(certificatePinner)
  7.   .build();

More details about HTTPS and certificate pinning with OkHttp can be found on their Wiki, as well as a full example.

DroidCon UK 2015 day 2

9.00 Keynote – Android for Java Developers
Speaker: Chet Haase

Or “Avoiding the Tragedy of the Commons”.

Ten articles on medium.com with tips for developing Android apps when coming from a Java backend background. First in the series: “Developing for Android: Introduction“.

Allocations, Android performance workshops.
“… dive deep into graphics and UI performance topics.”

IntDef
“Denotes that the annotated element of integer type, represents a logical type and that its value should be one of the explicitly named constants.”
Alternative for enums.

10.00 Staying alive, online and offline
Speaker: Erik Hellman

Tips about handling offline in your app.
Slides will be posted online later.

11.00 Beautiful Typography on Android
Speaker Lisa Wray
Video: YouTube

Fontbinding
A full example of custom fonts in XML using data binding and including font caching.

Use spans, when using HTML text consider replacing default spans with your own.

Audience suggestion: Java Ropes.
“A rope is a high performance replacement for Strings.”

12.00 Prototyping your Android app, the (U)X-factor
Speaker: Wiebe Elsinga
Video: YouTube

Prototype definition: Visualisation of an idea.

Uses of prototypes

  • Raise new questions OR answer existing ones.
  • Explore alternatives.
  • Fail early and cheaply.

“Fake it until you make it.”

Who will make the prototype? Create it with the whole team.

Good prototypes are Quick, Cheap, Minimal and Testable.

How to create a prototype?
1. Plan

  • Define user stories (1 or 2 sentences each).
  • Identify tasks.
  • Create user flow diagram.
  • Sketch rough interface screens.

2. Build

  • Using UI stencils or
  • Showing paper or
  • Templates (Sketch, Adobe Illustrator, etc) or
  • In the cloud (Marvel app) or
  • With motion

3. Test

  • Several prototypes
  • Choose the right users

4. Refine

  • Discuss results
  • Integrate findings

5. Repeat.

13.45 Meaningful motion
Speakers: Nick Butcher and Benjamin Weiss

View Property Animator
Simple animations, since API 16. Use ViewCompat for backward compatibility.

  1. someView.animate().alpha(1f)

ObjectAnimator
Animate all the things, since Honeycomb. Choreographed animations.
When no getter/setter exist, use the Property class.
For colors, set the evaluator to ArgbEvaluator.

Interpolators
Easing in and out.

  1. AnimationUtils.loadInterpolator()

Circular reveal

  1. Animator reveal = ViewAnimationsUtils.createCircularReveal();

Transitions
Move from scene A to scene B.
Transition and TransitionManager classes.

  • ChangeBounds: Animate size and position of an object.
  • Fade
  • AutoTransition: Fade in, ChangeBound and Fade out.

Window content transitions
Entering and exiting (Activities).

  • Slide
  • Explode

Can be added programmatically or declared in XML.

  1. Bundle bundle = ActivityOptionsCompat.makeScenTransitionAnimation().toBumdle();
  2. ActivityCompat.startActivity(... bundle);

Use android:transitionGroup=”true” to treat the View as a single animation target.

Shared element transitions
Since Lollipop, use AppCompat.

Animated Vector Drawables
“This class uses ObjectAnimator and AnimatorSet to animate the properties of a VectorDrawable to create an animated drawable.”
https://developer.android.com/reference/android/graphics/drawable/AnimatedVectorDrawable.html

Sample Apps

14.45 Physics UI
Speakers: Filipe Abrantes and Will Bailey

Slides: https://github.com/fabrantes/physicsui

Help making animations consistent.

Rebound
“Rebound is a java library that models spring dynamics. Rebound spring models can be used to create animations that feel natural by introducing real world physics to your application.”

An interesting paper from Microsoft “The Magic of UI Physics“.

15.45 Microservices is our BFF: why SoundCloud stopped using its own public API for its mobile clients
Speaker: Duana Stanley

Public API development is slowed down because it needs consensus. Some parts of a private API are not needed or wanted in the public API. A public API needs to be future-proof.

To overcome the issue create a “presentation” API, which is another layer. Break API up in micro services.

The result was BFF: Backend For Frontend. Provide a framework to make it like “scripting”.

“App+backend together build better APIs”

16.45 Make Believe
Speaker: Shanee Nishry

VR Hardware

  • Morpheus – Sony
  • Oculus Rift – Facebook
  • GearVR – Samsung
  • Vive – Valve
  • Etc…

Cardboard devices as cheap alternative.

Loads of interesting peripherals.

Own section for Cardboard in the Google Playstore.

How does VR work?

  • Visual immersion
  • Tracking
  • Input (Interaction)

Challenges in VR

  • Latency and performance.
  • Tracking.
  • Comfort and design.

Technical requirements

  • High resolution.
  • Wide field of view.
  • No motion blur.
  • Low motion-to-photon latency.
  • Stable high frame rate, 90, 120+.

Vulkan: Low overhead graphics and compute API.

Beware of people’s real-life fears, think about vertigo, claustrophobia, etc.

Project Tango: “Project Tango technology gives a mobile device the ability to navigate the physical world similar to how we do as humans.”

  • Motion tracking
  • Depth perception
  • Area learning

Other
Facebook Infer: “A static analyzer for Java, C and Objective-C”.

DroidCon UK 2015 day 1

9.00 Keynote: The long road
Speaker: Sandro Mancuso

Inspirational talk about how to find the job that will be the next step in your career.
Your personal career goals can be very different from a career within a company.

10.30 RxJava – Get Reactive
Speakers: Pascal Welsch and Wolfram Rittmeyer

RxJava
Beware of backpressure (items emitted too fast) discussed on Wiki as well. Possible solutions:

  • Throttle
  • Buffer
  • Request(n) upstream items

Testing: Use TestSubscriber.

RxAndroid
RxJava bindings for Android.

RxBinding
RxJava binding APIs for Android’s UI widgets.

Type and make network request handling, i.e. type and search. Add the following:

  • .throttleLast(100, MS) – Emit the most recent items emitted by an Observable within periodic time intervals.
  • .debounce(200, MS) – Only emit an item from the source Observable after a particular timespan has passed without the Observable emitting any other items.
  • .onBackPressureLatest() – Is there are still too many, take latest input.

RxLifecycle
Lifecycle handling APIs for Android apps using RxJava.

Other recommendations

  • Mosby – A Model-View-Presenter library for modern Android apps.
  • Nucleus – Nucleus is a simple Android library, which utilizes the Model-View-Presenter pattern to properly connect background tasks with visual parts of an application.

11.30 Gradle (performance)
Speaker: Etienne Studer

Gradle is more than just building. It can also be used for releasing, documentation, etc.

  1. gradle build --rerun-tasks

Rerun tasks even if they are up to date.

Performance improvements:

  • Incremental build feature. Define inputs and outputs for custom tasks.
  • Continuous build feature, faster compilation.
  1. gradle test -t

(Relies on inputs and outputs being defined.)

MOOC: Gradle for Android and Java.

12.30 Land’s End: Creating the flagship mobile VR adventure
Speaker: Peter Pashley

Getting started: Install Unity! and the Oculus SDK.

Nausea

  • Frame rate
  • Texture
  • Don’t highlight lack of positional tracking (Don’t put objects close to user so they won’t try to step / look around it.)
  • Acceleration is bad!

Input

  • Gamepad (Reminds user of the world they are not in.)
  • Gear VR
  • “Gaze” (Look points)

Things that didn’t work

  • Moving things on rails or predefined paths. Limits the user’s freedom.
  • Buttons. Too easy, too little player reward.
  • Unconstrained exploration. Take a wrong route, takes a long time to get back.
  • Path hinting. Focus becomes on following the path and not exploring.
  • Levitating huge objects. Obstructs points of reference and makes players motion sick.

Lookpoints

  • Focussing, aim and hold.
  • Motion, knowing where you’re going to stop moving.
  • Placement, not too many near each other.

14.15 ClassyShark Attack
Speaker: Boris Farber

Fast decompiling/debugging for Android APKs.

Ctrl + s – Save Java file.

Supports 5 binary formats

  • Jar
  • Dex
  • APK
  • Manifest
  • Java class

Project site: https://github.com/googlesamples/android-classyshark

15.15 $N tips for building better apps.
Speaker: Wojtek Kalicinski

Stop running your code
Don’t cram too much into Application.onCreate(). ContentProviders and BroadcastReceivers can cause the method to be invoked.
Solutions:

  • Defer work, lazy load.
  • Stop Services.
  • Disable BroadcastReceivers.

Permissions

  • Use ContentProviders to share files and/or get rid of permissions.
  • Use Intents to get rid of even more.
  • Runtime permissions. <uses-permission-sdk23>
  • AccountPicker.newChooseAccountIntent()

Low memory devices
ActivityManager.isLowRamDevice(), available in M, use

  1. android:extractNativeLibs="false"

Native library cannot be compressed and need to be zipaligned (zipalign -p). Write a small bash script to repackage .so when APK is built.

Accessibility
Accessibility is important, you get a bonus for it.

  • Settings > Accessibility -> Talkback
  • Add android:contentDescription tags. Set it to something meaningful. (For decorative elements, set to @null.)
  • onTouchListener, don’t insert click logic, use View.performClick()

Bonus: No extra work when integrating with the accessibility assistent.

16.15 Democamp Community Demos

  • Lumi Social News – Tinder for news.
  • SendTo – Send messages, text, links, etc to your own devices.
  • Myntra – Fashion / Shopping app. Preloading content for fast user experience.
  • Infinity Loop – Game
  • Sharp SVG lib
  • Lunchbreak (Belgium only) – Order lunch online
  • UI testing in your browser – ??
  • Frisbee GDG – All GDG content in one place.

17.15 Keynote: Managing Expectations: A Manager’s Guide for Managing to Manage Unmanageable Teams Manageably
Speaker: Chet Haase

Hilarious talk about management.

Other

  • Lands of Ruin – Lands of Ruin is a tabletop game where tablets replace classic rulebooks, character cards, stat sheets, and pen-and-paper calculations.
  • Land’s End – Mobile VR game.
  • Vysor – Lets you view and control your Android on your computer. Easy peasy.

Using SSL right on Android

General information
There is no out of the box solution from Google to use stronger encryption for the communication between your Android client and a server.

Google provides some information on how to use SSL on the Android developer website titled “Security with HTTPS and SSL“. This site contains two warnings you should not forget.

  1. Do not use a TrustManager that does nothing.
  2. Replacing the HostnameVerifier can be very dangerous.

A reason to use a TrustManager that does nothing could be for local or Alpha testing where you don’t have a valid SSL certificate on the server. Another could be to give QA the option to debug network traffic. If for some reason you do use a TrustManager that does nothing, make sure this implementation can never make it to a production version of the application. One way to do that is only include the empty TrustManager in one of the (testing) application flavors.

If you do want to use a custom HostnameVerifier, use composition to reuse the system’s default HostnameVerifier. This way you can add your own verification and still benefit from the default verification. You should apply the same when building your own TrustManager, that way your validation is never worse than the default system validation.

Pinning certificates
One way to make the encryption stronger is by using pinned certificates. This will help your application protect itself from fraudulently issued certificates. I will explore two ways of pinning a certificate. One is including the actual certificate, the other is to use SPKI or Subject Public Key Info.

Getting the server certificate
Before getting started with either method for pinning a certificate, you need to get hold of the server certificate. The easiest way to optain that would be to ask your system administrator. If that is not possible, you could use OpenSSL or FireFox to just save it from the browser. For more details, see “How to save a remote server SSL certificate locally as a file” on SuperUser.com.

Including the certificate
Start by including the certificate file (as raw resource) in your APK.
After this, implement your own TrustManager that uses the following pseudo-code to analyse the received certificate.

Get the key from the bundled certificate.

  1. FileInputStream fis = new FileInputStream("path_to_pem");
  2. CertificateFactory cf = CertificateFactory.getInstance("X.509");
  3. java.security.cert.Certificate c = cf.generateCertificate(fis);
  4. System.out.println(c.toString());
  5.  
  6. // will get you the public key object you can compare against.
  7. RSAPublicKey pk = (RSAPublicKey) c.getPublicKey();
  8.  
  9. System.out.println(pk.toString());
  10. String s = new BigInteger(1, pk.getEncoded()).toString(16);
  11. System.out.println(s);

Get the server key.

  1. // that gets the public key provided by the server out of the chain.
  2. RSAPublicKey pubkey = (RSAPublicKey) chain[0].getPublicKey();

Compare the two keys.

  1. // Where pk is the one loaded from your app file space.
  2. pubkey.equals(pk);

SPKI
An alternative approach to bundling the certificate with your application is to use the Subject Public Key Info method. This will just store the certificate’s fingerprint instead of a whole file.

To generate the fingerprint for your certificate, follow the instructions in “Appendix A” of the “Public Key Pinning Extension for HTTP” document, example:

  1. openssl x509 -noout -in certificate.pem -pubkey | \
  2.     openssl asn1parse -noout -inform pem -out public.key
  3. openssl dgst -sha256 -binary public.key | openssl enc -base64

You can calculate the same fingerprint in Java using the snippet below:

  1. // Assume the 'certificate' is a X509Certificate.
  2. MessageDigest digest = MessageDigest.getInstance("SHA-256");
  3. byte[] encodedKey = certificate.getPublicKey().getEncoded();
  4. byte[] hash = digest.digest(encodedKey);
  5. String fingerprint = Base64.encodeToString(hash, Base64.NO_WRAP);

Notes
SSL certificates can be invalidated for various reasons (they expire, get compromised, etc). Because of this you should consider showing a message to the user when pinning a certificate fails.

To avoid your app breaking when a certificate gets invalidated, you can keep a list of valid public keys. Start with the first in the list, if that doesn’t work fall back to the next public key in the list.

Update or change a certificate before the previous one expires. Unless the certificate is compromised, the public key will most likely stay the same. (If you use the same private key/CSR.)