09 July 2015

Android Wear - A week with a smartwatch

Thus far, I've not been impressed with smartwatches, I like new toys but even Android Wear has yet to impress me. The watches are just too big, I don’t buy into the charging every day thing and frankly I'm just not excited about the benefits. I've had a Casio watch which I've worn every day for about fifteen years and I've never charged it. Not once!

Roughly a week ago my work bought an Asus Zenwatch running Android Wear for testing and developing on. Not one to look a gift horse in the mouth and always up for some new programming and tinkering I was quite looking forward to having a play. I've previously written a test app but I used an emulator for this: http://webdeveloperpadawan.blogspot.co.uk/2014/07/android-wearables-first-go.html

My first impression of the Zen Watch was actually very good. It’s not nearly as fat as the LG Moto 360 which a few of my colleagues have and both the leather strap and the face have a nice look and feel. It is square but I can’t imagine that would bear any consequence to anyone.

It is too big, my tiny girl wrists are very twig like and the watch doesn't fit well and looks huge. There are huge gaps in the corners where the watch overlaps the flat bit of my wrist. That said it is comfortable and easy to get used to.

Turn on and set-up are a breeze and you can play with the watch faces on the play store which is fun for a few minutes.

Then it hits you….what now? You can’t really do anything with it! This is what is quite funny, people spot it on your wrist quite quickly and you honestly can’t show them much. It’s a passive device, you can’t play games on it, you can’t type on it, it just responds.

Sure you can use OK Google which is impressive, but I don’t talk to my phone and I’m unlikely to talk to this. It does work well and you can send messages and such by talking. Word to the wise, don’t try this after half a bottle of wine as I ended up sending all sorts of random messages to various people.

The beauty of the watch, and where I'm finally coming to actually really like it, is when you need to react to something. For example when one of the millions of spam messages comes to my phone, I don’t actually need to get my phone out to check it. I can immediately check and prioritise what’s important. The other thing that really stands out is the vibrate on your wrist, this is great as I often miss a call or message on my phone. The wrist vibrate is subtle but also unmissable. The ability to not get your phone out of your pocket sounds unbelievably lazy, but the watch works. For example in meetings or when you’re busy doing something, you can prioritise at a glance. Is this just another meaningless message from some inane whatsapp group or is it a message from Nest saying my house is on fire?

The battery is much less of a big deal than I thought, I'm getting two or three days of use out of it (I turn it off at night) and can just chuck it on its gradle for a bit while I'm working on it. Will it get tired….possibly, but so far its really not bothered me.

The Oatmeal have a fantastic post about the watch, all be it the apple one…. and it’s got funnier pictures than I do:

So to summarize, I'm impressed, very impressed. It can be surprisingly useful and does make life much easier. Million dollar question, would I buy one? No. They’re too big, when technology advances and the size comes way down, yes I will.

16 June 2015

Android integration with Chrome Custom Tabs


Announced at Google IO 2015 was the ability to integrate custom tabs in Android. Much like Facebook has been using it’s own browser like tab to open links, this ability is now available in Android with Chrome. This is great news as it allows developers to integrate a web link and maintain some of the look and feel of their app. You can add toolbar colors, animations and even a button.


Before going any further as of June 2015 you need to install Chrome from the dev channel:
Version 45 has this feature, they say it’ll take about twelve weeks to roll through to release.

This works in any version of Android, so don’t worry about M or any of that. It degrades really nicely, so if your client has the feature in Chrome, it’ll slide in and out beautifully. If not, then it’ll open like a regular intent. Although your custom in animation will probably show.

First you need to create four standard in and out animations, left in, left out, right in, right out.
Then you need to define some final constants which will be used in the intent extras:
private static final String EXTRA_CUSTOM_TABS_SESSION_ID = "android.support.CUSTOM_TABS:session_id";
public static final String EXTRA_CUSTOM_TABS_EXIT_ANIMATION_BUNDLE = "android.support.CUSTOM_TABS:exit_animation_bundle";
private static final String EXTRA_CUSTOM_TABS_TOOLBAR_COLOR = "android.support.CUSTOM_TABS:toolbar_color";

Then you can launch like this from your activity:

String url = "http://www.google.com/";
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.putExtra(EXTRA_CUSTOM_TABS_SESSION_ID, -1);
intent.putExtra(EXTRA_CUSTOM_TABS_TOOLBAR_COLOR, getResources().getColor(R.color.colorPrimary));

if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    Bundle finishBundle = ActivityOptions.makeCustomAnimation(MainActivity.this, R.anim.slide_in_left, R.anim.slide_out_right).toBundle();
    intent.putExtra(EXTRA_CUSTOM_TABS_EXIT_ANIMATION_BUNDLE, finishBundle);
    Bundle startBundle = ActivityOptions.makeCustomAnimation(MainActivity.this, R.anim.slide_in_right, R.anim.slide_out_left).toBundle();
    startActivity(intent, startBundle);
}else{
    startActivity(intent);
}


Note that basically all we are doing is launch an intent.ACTION_VIEW but we’re tweaking it with extras so Chrome can interpret this request, slightly differently.
That’s it!

31 May 2015

Android Design Support Library Collapsing Toolbar


Following Google IO I'm always that much more inspired to try a few new things with Android.
Shortly after IO I noticed this new post on the devlopers blog:
http://android-developers.blogspot.co.uk/2015/05/android-design-support-library.html

I immediately loved the CollapsingToolbarLayout as I've had to make something similar myself and never quite got it perfect. The fact that Google are releasing quick and easy ways to implement these design elements is absolutely fantastic. Long may it continue!

When I saw Ian Lake's post on this collapsing toolbar I was super keen to give them a go:
https://plus.google.com/+IanLake/posts/QGR5XNcPPeG

I didn't get especially far until this example from Chris Banes:
https://github.com/chrisbanes/cheesesquare

I decided (as usual) to make mine as simple as possible, stripping out as much of the superfluous stuff as I could.

First we need the support and design libraries:
    compile 'com.android.support:appcompat-v7:22.2.0'
    compile 'com.android.support:design:22.2.0'
    compile 'com.android.support:recyclerview-v7:22.2.0'

First thing we'll do is the xml for our main activity
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_scrollFlags="scroll|enterAlways" />

        <TextView
            android:text="@string/hello_world"
            android:padding="20dp"
            android:layout_width="match_parent"
            android:textColor="#00FF00"
            android:layout_height="wrap_content"/>
    </android.support.design.widget.AppBarLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/activity_main_listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>

The important bit here is the AppBarLayout which contains the Toolbar and a TextView which I want to hover over the top of the listview.

Second you'll notice we're using a RecyclerView which is new to me but looks to be more powerful than Listview.

Our ActivityMain just passes an ArrayList of Strings too the Recycler View
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.activity_main_listview);
recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
recyclerView.setAdapter(new MyRecyclerView(this, players));

Oh and of course don't forget to make sure your Activity uses AppCompatActivity and your manifest has a theme which overrides or implements Theme.AppCompat.Light.NoActionBar
You'll need the MyRecylcerView class but that's fairly boring and I borrowed most of it from Chris Banes, so I'll let you look at that in the git repo (bottom).

Now we need to look at the detail page where we use CollapsingToolbarLayout. First the xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:theme="@style/ActionBarPopupThemeOverlay"
        android:fitsSystemWindows="true">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            android:fitsSystemWindows="true"
            app:contentScrim="@color/colorPrimary"
            app:expandedTitleMarginStart="48dp"
            app:expandedTitleMarginEnd="64dp">

            <ImageView
                android:id="@+id/backdrop"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                android:fitsSystemWindows="true"
                app:layout_collapseMode="parallax" />

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:theme="@style/ActionBarPopupThemeOverlay"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_collapseMode="pin" />
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:paddingTop="24dp">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="20dp"
                android:text="All your base are belong to me." />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="20dp"
                android:text="All your base are belong to me." />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="20dp"
                android:text="All your base are belong to me." />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="20dp"
                android:text="All your base are belong to me." />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="20dp"
                android:text="All your base are belong to me." />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="20dp"
                android:text="All your base are belong to me." />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="20dp"
                android:text="All your base are belong to me." />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="20dp"
                android:text="All your base are belong to me." />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="20dp"
                android:textColor="@color/colorAccent"
                android:text="All your base are belong to me." />
        </LinearLayout>
    </android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>

Here we use a NestedScrollView instead of a RecyclerView, hence the big list of TextViews

The Activity is even simpler here, we read in the extra and setup the toolbar title and background image, then setup the action bar so it's an up navaigation and set the title:
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);

CollapsingToolbarLayout collapsingToolbar = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
collapsingToolbar.setTitle(muppetName);

That's basically it, a few new concepts and tools here but its super easy.

Here's the GitHub repo of all of this:
https://github.com/jimbo1299/androiddesigntest


12 May 2015

Android Auto First Play

Sadly I'm not lucky enough to have an Android Auto headset in my car, nor will my current car support one. However, I am desperately keen to have Android Auto in my car, to me it make so much sense as most proprietary systems really are awful. So in lieu of an actual system to play with, I thought I’d give Android Auto app creation a go, and see how it worked.

First of all read the dev guide:

There are currently limitations, meaning only Audio and Messaging apps are available, so I thought I’d have a crack at creating an Audio app. I’m really not looking at a shiny well designed app here, I just want to get a proof of concept type app out the door.

  1. Setup
    1. Create a new project selecting Android 5.0 (Api 21) or newer as the target
    2. Import support library (22.1.1 or better) in gradle
compile 'com.android.support:appcompat-v7:22.1.1'
    1. Open SDK manager and install “Android Auto API Simulators” from the Extras branch

  1. Update Android Project to use Auto
We need to tell Android Studio we’re creating an Auto project, so create an xml folder in the res directory and add a file named
automotive_app_desc.xml
With the following contents

<automotiveApp>
    <uses name="media" />
</automotiveApp>

Now tell the manifest where to find this file by adding inside the application tag:

<meta-data android:name="com.google.android.gms.car.application" android:resource="@xml/automotive_app_desc"/>

You can also give yourself an icon for your app

<meta-data android:name="com.google.android.gms.car.notification.SmallIcon" android:resource="@mipmap/ic_launcher" />

  1. Install the simulator
This is explained here:
You basically need to use adb to install an app which is supplied in the auto simulator downloaded in step 2. You can find the apk here:
<sdk>/extras/google/simulators/media-browser-simulator.apk
This isn’t what I expected at all. I was expecting a virtual device, but instead you get a simulator that runs on your actual phone or device and simulates the two types of android auto app. It’s a bit odd, but I guess it works.
If you’re setup you should find an app on your phone named “Media Sim”, run this and you should see the Google Play App running and working fine.

Code!

OK Now we’re ready to write some code. Don’t forget, I’m just creating a proof of concept Audio app here. So instead of streaming music I’ve copied an mp3 to res/raw and I’m going to try and play this file.

Create a service in the Manifest:

<service android:name=".MusicService" android:exported="true">
    <intent-filter>
        <action android:name="android.media.browse.MediaBrowserService"/>
    </intent-filter>
</service>

Create a class in your package and make it extend MediaBrowserService. This will mean you’ve got to implement the method onLoadChildren() and onGetRoot(). Now as you will see if you walk through the Google example this is how we create a tree structure of bands, albums and songs. Meaning you can traverse your music library. I was simply looking for the quickest route through all this to display one file, so I’ve created an array list of one mediaItem which is loaded with my mp3 and returned.
If you’re struggling to figure what to do here I advise to download the Google sample:

I’ve also created a MediaSessionCallback class which extends MediaSession.Callback. As you can see by the implemented methods, this is just a callback class for the play, pause, skip etc buttons. My version is pretty quick and dirty. Google provides a standard button interface for audio apps and in order to interface with these buttons we’re going to use the MediaSession callback.

Here’s the manifest:


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.wunelli.android.autotest" >

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

        <meta-data android:name="com.google.android.gms.car.application"
                   android:resource="@xml/automotive_app_desc"/>

        <meta-data android:name="com.google.android.gms.car.notification.SmallIcon"
                   android:resource="@mipmap/ic_launcher" />

        <activity
            android:name=".ActivityMain"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".MusicService" android:exported="true">
            <intent-filter>
                <action android:name="android.media.browse.MediaBrowserService"/>
            </intent-filter>
        </service>
    </application>
</manifest>



Here’s the code for the service:

package com.wunelli.android.autotest;

import android.media.MediaMetadata;
import android.media.MediaPlayer;
import android.media.browse.MediaBrowser;
import android.media.session.MediaSession;
import android.os.Bundle;
import android.service.media.MediaBrowserService;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

public class MusicService extends MediaBrowserService{

    private MediaSession mSession;
    MediaPlayer mPlayer;

    private static final String TAG = MusicService.class.getSimpleName();
    public static final String CUSTOM_METADATA_TRACK_SOURCE = "__SOURCE__";

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate");

        initMedia();

        // Start a new MediaSession
        mSession = new MediaSession(this, "MusicService");
        setSessionToken(mSession.getSessionToken());
        mSession.setCallback(new MediaSessionCallback());
        mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
    }

    @Override
    public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
        Log.d(TAG, "OnGetRoot: clientPackageName=" + clientPackageName + "; clientUid=" + clientUid + " ; rootHints=" + rootHints);

        return new BrowserRoot("__ROOT__", null);
    }

    private void initMedia(){
        mPlayer = MediaPlayer.create(this, R.raw.roboto);
    }

    @Override
    public void onLoadChildren(String parentId, Result<List<MediaBrowser.MediaItem>> result) {

        List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>();

        MediaMetadata item = new MediaMetadata.Builder()
                .putString(MediaMetadata.METADATA_KEY_MEDIA_ID, "1")
                .putString(CUSTOM_METADATA_TRACK_SOURCE, "roboto.mp3")
                .putString(MediaMetadata.METADATA_KEY_ALBUM, "Kilroy Was Here")
                .putString(MediaMetadata.METADATA_KEY_ARTIST, "Styx")
                .putLong(MediaMetadata.METADATA_KEY_DURATION, 330000)
                .putString(MediaMetadata.METADATA_KEY_GENRE, "rock")
                .putString(MediaMetadata.METADATA_KEY_ALBUM_ART_URI, "album_art.jpg")
                .putString(MediaMetadata.METADATA_KEY_TITLE, "Roboto")
                .putLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER, 1)
                .putLong(MediaMetadata.METADATA_KEY_NUM_TRACKS, 1)
                .build();
        String musicId = item.getString(MediaMetadata.METADATA_KEY_MEDIA_ID);

        String hierarchyAwareMediaID = "rock|" + musicId;
        MediaMetadata trackCopy = new MediaMetadata.Builder(item)
                .putString(MediaMetadata.METADATA_KEY_MEDIA_ID, hierarchyAwareMediaID)
                .build();
        MediaBrowser.MediaItem bItem = new MediaBrowser.MediaItem(trackCopy.getDescription(), MediaBrowser.MediaItem.FLAG_PLAYABLE);
        mediaItems.add(bItem);

        result.sendResult(mediaItems);
    }

    private final class MediaSessionCallback extends MediaSession.Callback {
        @Override
        public void onPlay() {
            Log.d(TAG, "play");
            mPlayer.start();
        }

        @Override
        public void onSkipToQueueItem(long queueId) {
            Log.d(TAG, "OnSkipToQueueItem:" + queueId);
        }

        @Override
        public void onSeekTo(long position) {
            Log.d(TAG, "onSeekTo:" + position);
        }

        @Override
        public void onPlayFromMediaId(String mediaId, Bundle extras) {
            Log.d(TAG, "playFromMediaId mediaId:" + mediaId + "  extras=" + extras);
            mPlayer.start();
        }

        @Override
        public void onPause() {
            Log.d(TAG, "pause.");
            mPlayer.start();
        }

        @Override
        public void onStop() {
            Log.d(TAG, "stop.");
            mPlayer.reset();
            initMedia();
        }

        @Override
        public void onSkipToNext() {
            Log.d(TAG, "skipToNext");
        }

        @Override
        public void onSkipToPrevious() {
            Log.d(TAG, "skipToPrevious");
        }

        @Override
        public void onCustomAction(String action, Bundle extras) {
            Log.i(TAG, "Unsupported action: " + action);
        }

        @Override
        public void onPlayFromSearch(String query, Bundle extras) {
            Log.d(TAG, "playFromSearch  query=" + query);
        }
    }
}















01 March 2015

Security isn't a dirty word Blackadder

Hopefully we all understand the concepts behind asymmetric (Public / Private key) encryption. It’s something we use all the time (https, SSL etc) but I've never actually put code to screen and tried to implement it. I've always relied on standard symmetric-key algorithm. So I thought I’d give it a go in Java / Android and along the way I learned a lot. In this blog article I thought I’d outline a few things I've learned. I’ll put some code up as I go, but I’d like to try and focus a bit more on the lessons.
All security is equal, except some more equal than others
We all know in symmetric encryption DES is bad, right?
DES is now considered to be insecure for many applications
http://en.wikipedia.org/wiki/Data_Encryption_Standard#Brute_force_attack


Well in theory public / private key encryption is infinitely better as long as you never give out your private key. Easy peasy, so we choose one of these and away we go:
  • RSA
  • EIGamal
  • Diffie-Helman
So I want to take a basic string “All your base are belong to me” and I want to encrypt it using a public key and decrypt it using a private key.
Rush to code

Impatient as I am I rush to get some code in and find this code to try out:
byte[] data = readBytesFromfile(“mypublickey”);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(data); 
KeyFactory kf = KeyFactory.getInstance("RSA");
pubKey = kf.generatePublic(keySpec);

Great, now I need a public and private key to test my amazing new code.

I learn a few bits about encryption

I’d heard of PGP and apparently this has no known weaknesses, perfect, I want this! So away I go and find a tool to generate my PGP public and private key. I throw these into my java code and straight away get an error. Hmmm. Something doesn't feel right here. Plus I'm not too sure about PGP and OpenPGP. OK back to wikipedia. Apparently PGP is a protocol, not an algorithm and for its asymmetric files it uses RSA anyway! Doh! So I resort to RSA and now I need to generate an RSA key.


So I've already got puttyGen installed and it I don’t know why it says SSH but it definitely says RSA right there with a big button saying “Generate”. Boom, surely this will work, nothing can stop me now!
Now I get a java error InvalidKeySpecException
Hmm, after some serious time googling I ask stack overflow
http://stackoverflow.com/questions/28218636/invalidkeyspecexception-using-public-key
Although it doesn't solve my problem, Maarten alerts me to the fact that in java I need to use the X509 format.
Hang on SSH is a protocol isn't it? (Back to wikipedia). Right ok so PGP and SSH are protocols that implement asymmetric encryption using the RSA algorithm. I don’t want a protocol, I want to just generate an encrypted string.


To do that I need a public key which java can read. So all I need is to generate a key in the right format….That makes sense.

Using KeyTool and OpenSSL to generate a 509 certificate


This doesn't take me long using java keytool and openssl to generate an x509 certificate.
keytool -genkey -keyalg RSA -keysize 1024 -keystore C:\temp\hello.keystore

keytool -importkeystore -srckeystore C:/temp/hello.keystore -destkeystore C:/temp/hello.p12 -deststoretype PKCS12

openssl pkcs12 -in C:/temp/hello.p12 -out C:/temp/hellonew.pem -nodes

openssl x509 -in C:/temp/hellonew.pem -inform PEM -out C:/temp/hellodernew.der -outform DER

Reading an X509 certificate
Now we need to adapt our code to read the key in the new format.
public static PublicKey getPublicKey(byte[] keyBytes){
    PublicKey publicKey = null;

    if(keyBytes != null) {

        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
        KeyFactory kf = null;
        try {
            kf = KeyFactory.getInstance("RSA");
            publicKey = kf.generatePublic(spec);
        } catch (NoSuchAlgorithmException e) {
            Log.e(TAG, "NoSuchAlgorithmException");
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            Log.e(TAG, "InvalidKeySpecException " + e.getMessage());
            e.printStackTrace();
        }
    }

    return publicKey;
}

This means we can now use our PublicKey to encrypt our message! Wohoo


Decryption

To decrypt we use a similar function

    public static PrivateKey getPrivateKey(byte[] keyBytes){
        PrivateKey privatekey = null;

         if(keyBytes != null) {
            PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory kf = null;
            try {
                kf = KeyFactory.getInstance("RSA");
                privatekey = kf.generatePrivate(spec);
            } catch (NoSuchAlgorithmException e) {
                Log.e(TAG, "NoSuchAlgorithmException");
                e.printStackTrace();
            } catch (InvalidKeySpecException e) {
                Log.e(TAG, "InvalidKeySpecException");
                e.printStackTrace();
            }
        }

         return privatekey;
    }


Encrypting a large file

For various reasons I've also learned you can’t just encrypt a file with your public key. This guy gives an excellent description of what you should be doing:


The basic idea is as such:
  1. Create a session key using symmetric encryption, AES for example.
  2. Then encrypt the file using this session key
  3. Using your public key encrypt the session key
  4. Send the AES encrypted file and the public key encrypted session key together
  5. Your server / recipient uses the private key they have and decrypts the session key then using that decrypts the file.


This method allows for fast encryption and secure transmission. If anyone brute forces the session key, they've only ever got one file. They need to start again for every single new file!

Anyway, that’s about what I've learned on this particular journey. I hope its of some help.

25 February 2015

Unit Tests, wonderful Unit tests


As I've mentioned before, I quite like unit tests. At the hands of Adam I've learnt to love and respect them. So when I had to write a simple function to ensure a password:

  • Is at least eight characters
  • Contains an upper-case character
  • Contains a lower-case character
  • Contains a digit
  • Contains a special character
I thought this would be a great reason to add some new unit tests in. Plus I'll be damned if I'm going to do all the typing on a phone to test and register all the various cases I can think of. As it happens this turned out to be a great idea because there was at least one case I'd missed.

Kids, unit tests work!

I thought I'd turn this into a challenge, how would you write the desired function? I'll provide the unit tests and you can impress me with your regex or your clever functions! Feel free to use any language you so desire. Winner gets the glory!

    @SmallTest
    public void testBlank(){
        String password = "";
        assertFalse(Utils.isPasswordValid(password));
    }

    @SmallTest
    public void testLower(){
        String password = "a";
        assertFalse(Utils.isPasswordValid(password));
    }

    @SmallTest
    public void testUpper(){
        String password = "A";
        assertFalse(Utils.isPasswordValid(password));
    }

    @SmallTest
    public void testNumber(){
        String password = "123";
        assertFalse(Utils.isPasswordValid(password));
    }

    @SmallTest
    public void testPadded(){
        String password = "     ";
        assertFalse(Utils.isPasswordValid(password));
    }

    @SmallTest
    public void testWhite(){
        String password = "\t\t";
        assertFalse(Utils.isPasswordValid(password));
    }

    @SmallTest
    public void testGood(){
        String password = "ab12CD*!";
        assertTrue(Utils.isPasswordValid(password));
    }

    @SmallTest
    public void testNoUpper(){
        String password = "ab12cd*!";
        assertFalse(Utils.isPasswordValid(password));
    }

    @SmallTest
    public void testNoLower(){
        String password = "AB12CD*!";
        assertFalse(Utils.isPasswordValid(password));
    }

    @SmallTest
    public void testNoNumber(){
        String password = "abcdCD*!";
        assertFalse(Utils.isPasswordValid(password));
    }

    @SmallTest
    public void testNoSymbol(){
        String password = "abcdCD12";
        assertFalse(Utils.isPasswordValid(password));
    }

    @SmallTest
    public void testGoodLong(){
        String password = "abcdCD12*&asdbbs167672HGSAHGAS!&^";
        assertTrue(Utils.isPasswordValid(password));
    }

    @SmallTest
    public void testGoodOne(){
        String password = "aaaaaA1\"";
        assertTrue(Utils.isPasswordValid(password));
    }

19 February 2015

Android Studio Build Types

Android Studio, somewhat predictably, allows two deployment modes debug and release. Configuring this in gradle allows you to configure certain options like if we should use proguard or not and what signing config to use. However this can be taken further to allow customization of certain java files based on release or debug build.


I’m not talking here about flavours, which is something slightly different. What I want to do is use one java class for debug and a different one for a release build. This allows me to suppress some debugging functions on a release build.

1. Create a Simple Project

First I create a new project and quickly setup a simple MainActivity with a button to launch a SecondActivity. I’m going to keep these activities very simple just to prove the concept. Don’t create the SecondActivity yet, we’ll do it in the next step.

2. Create Build Types

First update your app/build.gradle file to reflect the following, note the buildTypes:


apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "com.example.android.myapplication"
        minSdkVersion 10
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }

    signingConfigs {
        debug {
            storeFile file("--path-to-debug-keystore--")
        }
        release {
            storeFile file("--path-to-release-keystore--")
            storePassword "--password--"
            keyAlias "--alias--"
            keyPassword "--password--"
        }
    }

    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            signingConfig signingConfigs.release
        }
        debug {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            signingConfig signingConfigs.debug
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'
}

Note I’ve included a release keystore here with password and alias password. This is obviously not recommended for a real app. You would ideally release using the “Generate Signed APK…” However I’ve done it in this example as it allows me to quickly release using the build button.

3. Create folder structure

Create release and debug folders inside src. Inside both create a java folder, one (normally debug) will go blue and allow you to create a package. Create a new package matching your default package. In the other (normally release) you’ll have to just create folders instead of a package. Now create a SecondActivity.java in both. As the image below shows, you'll never get both release and debug to be correctly marked as a package. However when you switch using the build variants tab, you'll see the currently selected one change.



4. Test

Now you’re setup to configure your second activity as you wish, in my example I had each update a textview to say debug or release. Open the Build Variants tab in Android Studio and switch between build variants. This allows you to toggle the modes and release as such.