AndroidPub
Published in

AndroidPub

A Kotlin Cryptocurrency Tracker App (to some degree).

HODL

So…A few weeks ago I read this nifty article by Indrek Lasn.
He created a very basic cryptocurrency tracker using React Native.

It was a pretty good read. In fact, it was so good that it inspired me to do an article of my own…about creating a very basic…cryptocurrency tracker? (uh, yea), but this time using Kotlin (accompanying GitHub repo).

Finished product (for now at least)

I started this in Java originally, but I figured for the article I’d go the Kotlin route (it being the new kid on the block and all).

To get things started there are a few things to note:

  1. Android Studio 3.0 and greater is recommended; Kotlin comes bundled with version 3.0.
    To install Kotlin on a pre 3.0 version Android studio (why haven’t you updated yet? shame on you!) follow these steps:
    - Go to File | Settings | Plugins | Install JetBrains plugin… and then search for and install Kotlin. If you are looking at the “Welcome to Android Studio” screen, choose Configure | Plugins | Install JetBrains plugin… You’ll need to restart the IDE after this completes.
  2. I’ll be using the CoinMarketCap API, (and I’ll also be assuming that you are familiar with API endpoints and how to use them).
  3. I’ve stumbled upon this really nice set of CryptoCurrency icons.
  4. I’ll be using Cloudinary for hosting aforementioned icons.

Great, Let’s begin!

Here’s a quick run through of the setup:

From the “Welcome to Android Studio window click on “Start a new Android Studio project”.
Tick “Include Kotlin support”
For the remaining steps, I’ve kept the default values(choose Empty Activity if it isn’t your default option).

After about a minute or so, you should be greeted by the MainActivity.kt file.

First Order of Business

We’re going to add a few libraries:

  1. OKHttp to handle the REST-API requests.
  2. GSon for easy JSON parsing and conversion.
  3. Picasso for async image fetching and caching (essentially making this project doable in under 30 minutes).

In order to use these libraries, we must add a permission to our AndroidManifest.xml.

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

Head to the app/gradle.build file, within the dependencies, add these 3 lines and then click Sync Now:

compile 'com.squareup.okhttp3:okhttp:3.9.1'
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.google.code.gson:gson:2.8.2'

Second Order of Business

The layouts:

  1. Go to activity_main.xml, and copy & paste into yours.
    As you may have noticed we’re using a RecyclerView, so we must now create a layout for the RecyclerView Item.
  2. Create a new layout resource file. I’ve called mine crypto_layout.xml; copy & paste into yours.

The missing string resources can be found here.
For the layout files, I’ve opted to use the new ConstraintLayout .

Third Order of Business

Coding:
Go back to MainActivity.kt and declare the following variable at the top of the class:

private lateinit var llm: LinearLayoutManager

then within the onCreate() function, add these lines after the call to setContentView:

llm = LinearLayoutManager(this)
crypto_rv.layoutManager = llm
getCoins()

You may see some red lines under the crypto_rv declaration and Android Studio prompting you to import kotlinx.android.synthetic.main.activity_main.*; do so and it will go away.

For an in-depth explanation of what’s taking place, check out the official documentation (because, who doesn’t love documentation…right?…right?!).

The red lines under the getCoins() function call will prompt you to create the function, lets handle that now. Copy & paste the following:

fun getCoins(){

var client = OkHttpClient()
var apiUrl = "https://api.coinmarketcap.com/v1/ticker/?limit=10"
val request = Request.Builder().url(apiUrl).build()


client.newCall(request).enqueue(object: Callback {
override fun onFailure(call: Call?, e: IOException?) {
println("Failed"+e?.toString())
}
override fun onResponse(call: Call?, response: Response?) {
val body = response?.body()?.string()
println("Body :"+body)
}

})

}

llm — Initialization of a LinearLayoutManager() which is required for a RecyclerView. It handles positioning item views and determines when to reuse ones that are no longer visible to the user.

client — declares and initializes an OkHttpClient().

apiUrl — holds the REST endpoint to query, with the “limit=10” parameter passed. This will list the top 10 coins.

request — takes in the url and returns an object (what ever the endpoint sends, in this case a JSONArray).

The client call must be done with enqueue to ensure that it does not occur on the Main UI Thread (more info on threading). Data is downloaded on a worker thread and gets called back after the response headers are ready, with either an HTTP response or a failure exception.

The onFailure() function will be triggered if an error occurred.

The onResponse() function returns the results (a JSONArray that the endpoint sends).

body — takes the result (JSONArray) and converts it to a string.

println(“Body :”+body) — will display the string, allowing us to see what variables the endpoint has.

Based on the println(check logcat), you should see an array of objects which look something like:

{
"id": "iota",
"name": "IOTA",
"symbol": "MIOTA",
"rank": "10",
"price_usd": "1.96153",
"price_btc": "0.00018221",
"24h_volume_usd": "64054500.0",
"market_cap_usd": "5452132036.0",
"available_supply": "2779530283.0",
"total_supply": "2779530283.0",
"max_supply": "2779530283.0",
"percent_change_1h": "-0.65",
"percent_change_24h": "3.12",
"percent_change_7d": "4.43",
"last_updated": "1519805951"
}

With this, we can select the variables to use in our Model object:

class CryptoModel (
val id: String,
val name: String,
val symbol: String,
val price_usd: String,
val percent_change_1h: String,
val percent_change_24h: String,
val percent_change_7d: String
)

Let’s make some adjustments to the onResponse() method:

val gson = Gson()
val cryptoCoins:List<CryptoModel> = gson.fromJson(body, object : TypeToken<List<CryptoModel>>() {}.type)

runOnUiThread {
crypto_rv.adapter = CryptoAdapter(cryptoCoins)
}

gson — an instance of Gson() (with its default configuration), we will use it to take the JSONArray, and deserialize it to a List of CryptoModel objects.

cryptoCoins — is the list of CryptoModel objects (which will be created by gson) mentioned above.

runOnUiThread — if you recall me mentioning the importance of using enqueue earlier (to not carry out a network task on the main thread)…Now that the network task is complete, we must return to the main thread with the data that was obtained, to pass into the last piece of the puzzle, the RecyclerView Adapter.

I’ve called my adapter CryptoAdapter.kt, and there are a few things to note:

  1. It’s constructor, which takes in a list of CryptoModel objects.
    CryptoAdapter(val cryptoCoins: List<CryptoModel>)
  2. The CryptoViewHolder class, which houses the items from the layout file we created earlier(crypto_layout.xml).
  3. The adapter’s onBindViewHolder() function which connects the the CryptoModel to the layout items.

Inside of the onBindViewHolder() function :

val coin = cryptoCoins.get(position)var imageUrl = "https://res.cloudinary.com/dxi90ksom/image/upload/"
holder?.coinName?.text = coin.name
holder?.coinSymbol?.text = coin.symbol
holder?.coinPrice?.text = coin.price_usd
holder?.oneHourChange?.text = coin.percent_change_1h+"%"
holder?.twentyFourHourChange?.text = coin.percent_change_24h+"%"
holder?.sevenDayChange?.text = coin.percent_change_7d+"%"
Picasso.with(holder?.itemView?.context).load(imageUrl+coin.symbol.toLowerCase()+".png").into(holder?.coinIcon)

imgUrl — the url endpoint for the crypto currency icons.

coin — A single CryptoModel object from the list.

holder — the CryptoViewHolder, and its widgets (textviews, imageviews).

Picasso —Image fetching and caching. It uses the imgUrl (which is concatenated with coinSymbol and .png extension) and places the retrieved image into the imageView.

That concludes this tutorial, hopefully it has helped someone perhaps learn the basics of sending HTTP requests and handling the response, or perhaps be the stepping stone for a full crypto currency tracker (feel free to leave a link to what you’ve made in the comments if you found this helpful).
Remember the full repo can be downloaded here.

--

--

--

The (retired) Pub(lication) for Android & Tech, focused on Development

Recommended from Medium

K0s Cluster Without Internet Access

Best Resources For Passing The AWS Developer Associate Exam

Big Data — Hadoop

Why do new programmers quit so quickly?

What

What Architects Need to Know About Networking on AWS

A VPC consists of multiple subnets. The subnets segment the private IP address range of the VPC.

Introduction to RPCs and gRPC

Hello from Python in the Browser!

Design Patterns: Null Object

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Charles E.

Charles E.

The Geeks Shall Inherit The Earth. Software Engineer. Android | iOS.

More from Medium

Practical Jetpack Compose: Get the beta!

Android arch exploration: Compose navigation but ViewModel dictates where to go

Anime App with Kotlin

Android What’s new this week? #1