First Contact: Android

PeercoinDown

Preface

I have not done Android native development before, and neither have I really done that much Java development in general (I’m counting my high school’s Computer Science courses here, so take that with a grain of salt). That said, I have developed a few mobile-minded applications in my time at the Emergent Media Center. Unfortunately, the work I do there tends towards iOS and after a little native development on iOS, the team switched to Titanium which has a JavaScript API for cross-platform development. In general, I’m not too keen on Java for various completely opinionated reasons, but its language syntax is C-derived so it looks at least a little bit like home.

Goals

So the goals of the project were twofold:

  • Create a (working) native Android application
  • Familiarize myself with the tools of Android development (ADT, Java, Android API)

The former is complete, though my application is fairly basic. I wanted to do something with cryptocurrencies such as Bitcoin or Peercoin. In no way was it possible to make an application to, say, hold bitcoin addresses or send or anything like that. Attempting to do so would be akin to attempting to learn how to fly by jumping off a cliff and hoping you genetically mutate before you suddenly stop.

The latter portion of this project went fairly well. Once you’ve learned various other APIs for programming languages, it becomes easier to guess function names and class responsibilities. Though some truth lies in the previous statement, it’s important to remember that the key word there is guess. I often times found myself recoiling to Google when just about anything went wrong in the application.

One slight annoyance I keep running into is that I’m far too used to Visual Studio for IDEs, and Eclipse’s method for doing code completion is actually quite tedious to get going; it won’t do any code completion hinting if I start typing too quickly, which is precisely when I want it to do completion.

CoinTraq

Setting my sights a little lower, I decided on an application that I call Cointraq (which is precisely the same idea and name as this website called cointraq, I’ve come to find; I swear I chose the name and concept independently). Cointraq simply gives you a list of some 260 cryptocurrencies, including known behemoths such as Bitcoin or Litecoin and other up-and-coming coins such as DarkCoin. Clicking on it will bring you to a page where you can see its current price in USD, its price change in the past 24 hours, and a field to enter the amount you own so that you can see your worth increase over time. All of this information is pulled from a cool site called CoinMarketCap via a CoinMarketCap JSON API service found here.

Let’s get technical

There are a few aspects to the core functionality of CoinTraq that needed to be tackled:

  • Understand Activities and how to navigate them
  • Understand how to make REST network calls and consequently, threading
  • Cache, Cache, Cache ( Generics? )
  • JSON
  • Populate a ListView without using the tutorial’s Cursors concept (Yay really old android test device!)
  • Understanding Android’s User Preferences system for storing data between sessions
  • Toast is good

I won’t cover Activities as they’re really simple, but what I will mention is that android:layout_below=”@+id/some_view” is really important when you want some sort of order to an Activity.

Making network calls is quite simple, but making it run in a separate thread was oddly different as compared to, say, C or C++. The network library for making REST calls reminded me a lot of how it’s handled in C#/.NET which I’ve had a little bit of experience in thanks to my Game Networking class. Unfortunately, HttpURLConnections in Java are blocking operations, so you must spin it off to another thread if you want your UI to be responsive. To make things run in separate threads, you spawn them off to an AsyncTask<T1, T2, T3> class. In my case, I created a private class within an activity that extends from AsyncTask. Without going over the entire documentation, the AsyncTask requires three types, the first being your input, the second being the progress return type, and the third being whatever you will return from the thread. In addition, your subclass needs to override (why not just make ‘override’ a keyword?) two functions: T3 doInBackground(T1… param) and void onPostExecute(T3 result). In my case, I took in a String for a URL and return a JSONObject which is my entire response.

private class DownloadWebpageTask extends AsyncTask<String, Void, JSONObject> {
    @Override
    protected JSONObject doInBackground(String... urls) {

    	// params comes from the execute() call: params[0] is the url.
    	try {
    	    return downloadUrl(urls[0]);
    	} catch (IOException e) {
    	    return null;
    	} catch (JSONException e) {
	        e.printStackTrace();
	        return null;
        }
    }
    // onPostExecute displays the results of the AsyncTask.
    @Override
    protected void onPostExecute(JSONObject result) {
    	JSONArray markets;

    	if(result == null)
    	{
    		Toast.makeText(MainActivity.this, "Using cached data", Toast.LENGTH_SHORT).show();
    		markets = jsonCache.get();
    	}
    	else
    	{
    		try {
        		markets = result.getJSONArray("markets");
        	} catch (JSONException e) {
        		e.printStackTrace();
        		return;
        	}

        	jsonCache.set(markets);
    	}

    	try {
	        ArrayList stringArray = new ArrayList();

	        for(int i = 0; i &lt; markets.length(); i++)
	        {
		        stringArray.add(markets.getJSONObject(i).getString("name"));
	        }

	        ArrayAdapter adapter = new ArrayAdapter(activity,
				android.R.layout.simple_list_item_1,
				stringArray);

	        ListView lv = (ListView) findViewById(R.id.list_view);

	        lv.setAdapter(adapter);

        } catch (JSONException e) {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
	        return;
        }
    }
}

This code sample shows private class discussed above and the highlighted line shows the types involved in my particular use case. The great thing here is that AsyncTask gives you a Generic way to spin off other threads and as a class that can be extended, you can make derived classes with specific functions.

Mobile applications depend, or at least should depend on caches for data storage. Caches are very powerful for relatively non-changing data and invaluable when it comes to devices whose network connections are volatile. The location I pull data from only updates that data every 5 minutes, so making requests at any faster of a frequency once the first response comes down is wasteful on battery life and on remote server resources. For the purposes of the application, I wrote a very small Generic class called Cache which very basically just stores one of whatever type you give it somewhere in volatile memory. Both AsyncTask and the Cache class introduced me to Generics, which is, from all I can find, a fairly simple version of C++ templates. In any case, the tiny class is as follows and included is a code snippet for where I limit requests to once every five minutes.

//-- Cache.java --\\
package com.mason.cointraq;

public class Cache<T>
{
	public Cache(T objToCache)
	{
		mCachedObj = objToCache;
		mCachedTime = 0;
	}

	public T get()
	{
		return mCachedObj;
	}

	public void set(T newObj)
	{
		mCachedObj = newObj;
		mCachedTime = System.currentTimeMillis();
	}

	public long getCachedTime()
	{
		return mCachedTime;
	}

	private T mCachedObj;
	private long mCachedTime;
}

//-- MainActivity.java --\\

long currentTime = System.currentTimeMillis();

// Cached time + 5 minutes
if(currentTime <= jsonCache.getCachedTime() + 300000)
{
        return null;
}

URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();

JSON in Java feels at home, and I wonder why? It feels very refreshing to have a simple and embedded JSON read / write capacities within an API. I won’t really go over all of the stuff you can do with Java’s JSON libraries, but what I will say is that it is AWESOME and never forget that one of the strongest things about JSON (and XML as well) is that it can be represented as an inflated type in memory and simply as a String. I pass a JSONObject from my main activity to the Currency Information activity so that it has that cryptocurrency’s data via a String because Intent extras don’t have a function overload for JSONObjects.

I don’t like ListViews; neither here nor in Titanium. That said, populating a ListView with data could have been a lot worse. I am in the unfortunate position of owning a really old android device (Android 2.3 Gingerbread for the win!) and thus, some of the stuff mentioned in StackOverflow answers and official guides don’t work by default on my device. Side note: Google’s great at adding new functionality to the Support Library so that it can be used on older devices; that’s just awesome. Anyway, a little bit more diving into the depths of StackOverflow questions and some experimentation on my part later, I figured out that you can use an ArrayAdapter to take an ArrayList full of Strings and then tell a ListView to use that adapter. Code follows, probably don’t use it because it might as well be the wrong way now:

// ...
ArrayList<String> stringArray = new ArrayList<String>();
				
for(int i = 0; i < markets.length(); i++)
{
	stringArray.add(markets.getJSONObject(i).getString("name"));
}
				
ArrayAdapter adapter = new ArrayAdapter<String>(activity,  
        android.R.layout.simple_list_item_1, 
	stringArray);
				
ListView lv = (ListView) findViewById(R.id.list_view);

// THE HOLY GRAIL OF SOLUTIONS
lv.setAdapter(adapter);
// ...

User Preferences are a way to store user data between sessions. Save some prefs, close the app, open it up, if you load from the same place then your data is there! Simple and useful. The system available in Android’s API is practically identical to the ones in Titanium, iOS, and Unity. I utilize this system to save the amount of any particular cryptocurrency a user has entered so that when they come back to the app time and time again, they can see clearly how much money they’re gaining!

As a final note on the things I’ve learned, remember that Toast is good. I utilized Toast often to print important error information and sometimes to ensure that some of my events were actually firing when my brain’s neurons clearly weren’t. The little notifications Toast provide do well into the final app for the exact same reason: small information bubbles. I don’t know how they work in later Android versions, but I hope Toast is still there.

So what does it look like?

So can I get it?

While I don’t know particularly why you would want such a terrible app, and one that apparently doesn’t run on modern devices, but you can download the apk from my site here.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s