Creating a Android Todo App With Rio Android SDK
Published: 2022-11-19 15:16:01

Rio SDK Docs -> https://docs.retter.io/docs/sdks
Project Git-> https://github.com/retterio/rio-android-todo
Backend Git -> https://github.com/retterio/simple_todo_example

In this article we will create a todo app with rio android sdk. Im not going to go so deep into android app creation, we will mostly focus on how to use SDK. If you want to see how ui things done, go to [github](https://github.com/retterio/rio-android-todo). So let's begin.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/plkm2tvg5ye0gay5tl6l.png)

## Installation

First we need to install SDK to our project. To do so, go to [link](https://docs.retter.io/docs/sdks) and follow instructions. You can add maven into settings.gradle like this.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m90wetbvme79ndqish01.png)

## Initialization
Create class `App` and paste code below to it. We will init SDK here. Change `projectId` with yours. If you are using a custom domain, you need to set it like below. If necessary you can set region too. Inside `AndroidManifest` under application tag add `android:name=".App"`.

```kotlin
import android.app.Application
import com.rettermobile.rio.Rio
import com.rettermobile.rio.service.RioNetworkConfig

class App : Application() {
    companion object {
        lateinit var rio: Rio
    }

    override fun onCreate() {
        super.onCreate()
        rio = Rio(
            applicationContext = applicationContext,
            projectId = "2g8eht73b",
            culture= "en",
            config = RioNetworkConfig.build {
                //region = RioRegion.EU_WEST_1
                //customDomain = "yourDomain"
            }
        )
    }
}
```
# Main Activity
Now let's do simplest authentication. There is a function in my backend that returns a customToken. This function is inside  class `Authenticate`.

## Authentication
As you can see our function returns a custom token when we called.
```typescript
export async function generateCustomToken(data: Data): Promise<StepResponse> {
  const { userId } = data.request.body
  data.response = {
    statusCode: 200,
    body: await rdk.generateCustomToken({
      userId,
      identity: 'enduser'
    })
  }
  return data
}

```
We will call this function under `onCreate`. Let's do so. We get classes from backend like below.
```kotlin
rio.getCloudObject(RioCloudObjectOptions(
    classId = "Authenticate",
    instanceId = "01gj4yxz2ax9txgsxjnxd4rhrf"
), onSuccess = { cloudObj ->
    cloudObj.call()
}, onError = { throwable ->
    Log.d("TAG", throwable!!.message.toString())
})
```
                    
Inside `onSuccess` we can call our functions like below. 
```kotlin
cloudObj.call<AuthResponse>(
    RioCallMethodOptions("generateCustomToken",body = AuthRequest()),
    onSuccess = {
        //Authenticating with `rio.authenticateWithCustomToken()`.
        rio.authenticateWithCustomToken(it.body!!.data!!.customToken.toString())
    },
    onError = {
        Log.e("", "")
    })
```
`AuthResponse` and `AuthRequest` are like models.

**Auth.kt**
```kotlin
data class AuthRequest (
    var userId: String = "userId",
    var identity: String? = "enduser"
)

data class AuthResponse(val data: Token? = null)
data class Token(val customToken: String?)
```
## Get Todos
Now we are doing authentication. Let's get Todos. We will get todos inside onCreate.
```kotlin
// Get class
rio.getCloudObject(RioCloudObjectOptions(
    classId = "TodoProject",
    instanceId = "01gj501gb69yse4sbt0jp61vdq"
),
    onSuccess = { cloudObj ->
        //cloudObj.public.subscribe()
}, onError = { throwable ->
    Log.d("TAG", throwable!!.message.toString())
})

```
Subscibe is for listening live changes. Here we are listening public state changes.
```kotlin
cloudObj.public.subscribe( eventFired = { event ->
     // cloudObj.call()

}, errorFired = { fThrowable ->
    Log.d("TAG", fThrowable!!.message.toString() )
})

```
When public state changes we get todos from backend.
```kotlin
cloudObj.call<GetTodosResponse>(RioCallMethodOptions(
    method = "GetTodos"
), onSuccess = { response ->
    val todos = response.body!!.todos
    val listView: ListView = findViewById<View>(R.id.todosListView) as ListView
    listView.adapter = listViewAdapter(this, todos)
}, onError = {
    Log.d("TAG", it!!.message.toString() )
})

```

```kotlin
// app/src/main/java/com/retter/rettersdk/network/GetTodos.kt

data class GetTodosResponse(val success: Boolean, val todos: ArrayList<Todos>)
data class Todos(val todo: String, val id: Number)

```

## Adding Todo

For my app I added a button to action bar. When this button is clicked it shows an alert dialog. Alert dialog has an input. When add is clicked we call our function.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oit2s0a0zhw703dee33i.jpeg)
```kotlin
// app/src/main/java/com/retter/rettersdk/MainActivity.kt

rio.getCloudObject(RioCloudObjectOptions(
    classId = "TodoProject",
    instanceId = "01gj501gb69yse4sbt0jp61vdq"
),
    onSuccess = { cloudObj ->
        cloudObj.call<UpsertTodoResponse>(RioCallMethodOptions(
            method = "UpsertTodo",
            body = UpsertTodoRequest(input.text.toString())
        ), onSuccess = { response ->
            Log.d("TAG", "succesfully added" )
        }, onError = {
            Log.d("TAG", "fError" + it!!.message.toString())
        })
    }, onError = { throwable ->
        Log.d("TAG", throwable!!.message.toString())
    })
```
```kotlin
// app/src/main/java/com/retter/rettersdk/network/UpsertTodo.kt
data class UpsertTodoRequest (
    var todo: String
)
data class UpsertTodoResponse(
    val success: Boolean, 
    val newTodo: ArrayList<Todos>, 
    val error: String
)
```
## Edit and Remove Todo

I added button for every item in list view. To achieve this created a custom layout and custom adapter for list view. Editing and removing is done inside adapter class. You can find it on GitHub repository.

### Editing Todo
To edit todos we don't have a separate function. In `UpsertTodo`, if todo with given id exists its changes todo. 

Every item in list view has todo and id. We get selected id from list view inside adapter. We use alert dialog to edit todos. There is an input in alert dialog. `input.text.toString()` is the value of that input.

```kotlin
rio.getCloudObject(RioCloudObjectOptions(
    classId = "TodoProject",
    instanceId = "01gj501gb69yse4sbt0jp61vdq"
), onSuccess = { cloudObj ->
    cloudObj.call<UpsertTodoResponse>(
        RioCallMethodOptions(
            method = "UpsertTodo",
            body = EditTodoRequest(selectedId, input.text.toString())
        ), onSuccess = { response ->
            Log.d("TAG", "Succesfully edited." )
        }, onError = {
            Log.d("TAG", "fError" + it!!.message.toString())
        })
}, onError = { throwable ->
    Log.d("TAG", throwable!!.message.toString())
})
```
EditTodoRequest is inside UpsertTodo.kt like this.
```kotlin
class EditTodoRequest (
    var id: Number,
    var todo: String
)

```
### Removing Todo
To remove we get id from list view as well. Then simply calling function that removes todos with id of todo will be removed.
```kotlin
rio.getCloudObject(RioCloudObjectOptions(
    classId = "TodoProject",
    instanceId = "01gj501gb69yse4sbt0jp61vdq"
), onSuccess = { cloudObj ->
    cloudObj.call<RemoveTodoResponse>(
        RioCallMethodOptions(
            method = "RemoveTodo",
            body = RemoveTodoRequest(selectedId)
        ), onSuccess = { response ->
            Log.d("TAG", "Succesfully removed." )
        }, onError = {
            Log.d("TAG", "fError" + it!!.message.toString())
        })
}, onError = { throwable ->
    Log.d("TAG", throwable!!.message.toString())
})

```
```kotlin
// app/src/main/java/com/retter/rettersdk/network/RemoveTodo.kt

data class RemoveTodoRequest (
    var id: Number
)
data class RemoveTodoResponse(val success: Boolean, val message: String)

```
Now you know how to create a simple todo application with Rio android SDK. 

Here is the [entire code](https://github.com/retterio/rio-android-todo) for our project. 

Thanks.