In this part of the Android development tutorial series we are going to connect the app to the app backend so the user can spend their Kin securely. Like with the earns, we will create a button that the user can click on to buy something for 5 Kin. The result of the spend will then be displayed on the screen for demo purposes (either that the spend is valid or some error message).

When the user clicks the spend button, three things need to happen:

Get a token from the app backend by requesting a spend

Send the correct amount of Kin

Verify the app transaction and show the result to the user

We will go over this step by step.

Creating the spend button

The first step is to create the spend button. We can do this exactly the same way as how we created the earn button. Just drag and drop the button, name it and attach a function to the onClick event. We can call the onClick function spendButtonClicked, defined as the following in the MainActivity.java file:

public void spendButtonClicked(View view) {

Log.i("main", "Clicked spend button");

NYBus.get().post("x", Channel.THREE);

}

Note that we use channel three for this, as we already use one and two for earns. I created it like this:

To test if the button works, open the device emulator and the logging, then run the app. Click the button and see if the message “Clicked spend button” pops up in the logs.

If so, we can continue to add some logic to the spend button.

Sending the spend request

The spend request needs to be sent from the Kin class. Just as with the earns, we can listen to a new channel (channel 3) and do the API request when something comes in on that channel. As you already know how to send requests to the app backend, this is actually quite simple. Just add the following method to the Kin.java file:

@Subscribe(channelId = Channel.THREE)

public void onEventSpend(String clicked) {

String androidId = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);



okhttp3.Request request = new okhttp3.Request.Builder()

.url(String.format(URL_SPEND_REQUEST, androidId))

.get()

.build();



okHttpClient.newCall(request)

.enqueue(new okhttp3.Callback() {

@Override

public void onFailure(@NonNull Call call, @NonNull IOException e) {

Log.i("main", "Something went wrong");

Log.i("main", e.toString());

}



@Override

public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {

String body = response.body().string();

Log.i("main", "Token: " + body);

}

});

}

Also add the URL_SPEND_REQUEST at the top, just like the other urls:

private String URL_SPEND_REQUEST = "http://YOUR-SERVER-IP:8001/spend_request?device_id=%s";

And we need to listen to channel 3 as well as 2, so in the onCreate function change the NYBus line to:

NYBus.get().register(this, Channel.TWO, Channel.THREE);

Now run the app and click the spend button again (make sure the app backend is running as well). After clicking the button it should show the token in the logs, like this:

Sending Kin from the app

Now that we have the token, we can send the required amount of 5 Kin to the operational wallet. Let’s do that, and then log the transaction ID that we need for the last step.

First, add some imports that we are going to need and define some private variables at the top of the class (where the other private variables are also located):

// Add imports

import java.math.BigDecimal;

import kin.sdk.Transaction;

import kin.sdk.TransactionId; // Add private vars at the top of the class

private Request<Transaction> buildTransactionRequest;

private Request<TransactionId> sendTransactionRequest;

Create the sendTransaction method:

private void sendTransaction(Double requestAmount, String memo, String to) {

Log.i("main", "Sending transaction");

BigDecimal amount = new BigDecimal(requestAmount);

final KinAccount currentAccount = this.kinAccount;



buildTransactionRequest = currentAccount.buildTransaction(to, amount, 100, memo);

buildTransactionRequest.run(new ResultCallback<Transaction>() {

@Override

public void onResult(Transaction transaction) {

sendTransactionRequest = currentAccount.sendTransaction(transaction);

sendTransactionRequest.run(new ResultCallback<TransactionId>() {

@Override

public void onResult(TransactionId id) {

Log.i("main", "Transaction sent. ID: " + id.id());

}



@Override

public void onError(Exception e) {

Log.i("main", "Something went wrong");

Log.i("main", e.toString());

}

});

}



@Override

public void onError(Exception e) {

Log.i("main", "Something went wrong");

Log.i("main", e.toString());

}

});



}

This function first builds a transaction request and then does the actual transaction. When successful, we log the transaction ID. We can now send transactions from the user’s wallet by invoking the method like this:

sendTransaction(amount, memo, to);

In our example, the amount will be 5, the memo will be the token we got back from the backend and the “to” address will be the operational wallet address. Note that the “to” address here must be the same as the “receiving” address in the backend verification function, otherwise you will get an error that the destination address is incorrect when doing the validation.

In the “onEventSpend” function we just created, we can now call the “sendTransaction” function after it is successful. In the “onResponse” of the “onEventSpend”, add the following line:

public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {

String body = response.body().string();

Log.i("main", "Token: " + body);

sendTransaction(5.0, body, KIN_WALLET_ADDRESS);

}

Then, add the KIN_WALLET_ADDRESS as a private var at the top of the file as well. That should contain the operational wallet address where the users will send their Kin.

Now run the app and press the spend button. You should see something like this:

You can copy/paste the transaction ID from your console and check in the block explorer that the transaction is there.

Verify the spend

The last step is to verify the spend. At this point it becomes pretty straightforward. Add the endpoint at the private vars:

private String URL_VERIFY_REQUEST = "http://YOUR-SERVER-IP:8001/spend_validate?transaction_id=%s";

Add the function that calls the app backend:

private void verifySpend(String tx) {

okhttp3.Request request = new okhttp3.Request.Builder()

.url(String.format(URL_VERIFY_REQUEST, tx))

.get()

.build();



okHttpClient.newCall(request)

.enqueue(new okhttp3.Callback() {

@Override

public void onFailure(@NonNull Call call, @NonNull IOException e) {

Log.i("main", "Something went wrong");

Log.i("main", e.toString());

}



@Override

public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {

String body = response.body().string();

Log.i("main", "Result: " + body);

getBalance();

NYBus.get().post(body, Channel.FOUR);

}

});



}

Note that if successful, we log the body, update the balance and then post the body on channel 4, so we can add the result on the device screen in the next step.

Now we just have to call this method after sendTransaction was successful, by changing the onResult method of sendTransaction to:

public void onResult(TransactionId id) {

Log.i("main", "Transaction sent. ID: " + id.id());

verifySpend(id.id());

}

Rerun the app and click the spend button again. In the logs, you should see something like this:

In the middle you see “Result: Spend is valid”. Great! If you see an error there, you have to look for what is wrong with the request, as the backend is always correct. Let me know if you have issues in the comments.

Showing a spend result to the user

Lastly, we can show the result of the spend button to the user. We already post the result on channel 4, so we can update the MainActivity.java file to update a text to that result.

To do this, first create a new text object in activity_main.xml by dragging and dropping it in the screen (it’s under the “text” palette), like this:

Note the ID of the text object, it’s “textView2”. You can rename it to something more verbose, just remember to update the below code in that case, too.

We need to update the MainActivity.java file so that it also listens to channel 4 by changing the NYBus line in the onCreate function to:

NYBus.get().register(this, Channel.ONE, Channel.FOUR);

Create the function that updates the text of textView2 when something is posted on channel 4:

@Subscribe(channelId = Channel.FOUR)

public void onEventResult(String result) {

TextView txtView = findViewById(R.id.textView2);

txtView.setText(result);

}

Now rerun the app and click on the spend button. If everything went right, you should see the browser result on the screen! To show intermediate steps of what is happening you can post some more information to channel 4, like these:

private void sendTransaction(Double requestAmount, String memo, String to) {

NYBus.get().post("Sending transaction", Channel.FOUR);

Log.i("main", "Sending transaction");

... private void verifySpend(String tx) {

NYBus.get().post("Verifying transaction", Channel.FOUR);

okhttp3.Request request = new okhttp3.Request.Builder()

... public void onEventSpend(String clicked) {

NYBus.get().post("Requesting transaction", Channel.FOUR);

String androidId = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);

...

Now if you rerun again, you’ll see that the text is updated with whatever function is running at the moment. Here’s a small video:

Wrapup

Congratulations! You now have an earn and a spend in your app! This was the end goal of the tutorial series. There will be one last part that explains a couple of points to wrap it up.