Sending App Feedbacks directly to Slack Channel

Aravinth Velusamy
Criar Solutions
Published in
3 min readMay 6, 2020

--

Feedbacks are more important for any product because it helps us make the product better by hearing customer needs. Last week I had to build a feedback feature into an existing project which I’m working. After getting this task, I went to GitHub searched feedback libraries. Most of the libraries were email based, I integrated a library. After integrating the library, I found that to submit a feedback, the user had to navigate to the Mail app (from the mail app, the user has to send the feedback to developer’s email). The time taken to submit a feedback using this method is not user friendly, so I came up with another plan to replace mail with Slack webhooks.

My requirement was simple, when the user click the ‘Send feedback’ button, the dialog should show up, the user has to enter their feedback and when ‘Send’ button is clicked, the feedback should come straight to Slack channel.

In this blog, I’ll be explaining How to integrate slack channel and your android app.

Step: 1 — Setup Incoming webhook URL for your slack app

Follow the link to the setup Incoming webhooks URL for your slack app. We’re going to send the feedback from the app to slack channel via this webhook URL.

Step: 2 — Test the webhook URL in postman

After generating the webhook URL for your app, the next step is to test if it’s working. You can use postman to test this URL. Refer the below image. I’m sending a JSON data in the request body. The feedback should be the value to the key “text”.

Postman

Step: 3 — Android Integration

Set-up Feedback dialog

val view: View = layoutInflater.inflate(R.layout.fragment_feedback, null)
MaterialAlertDialogBuilder(context)
.setView(view)
.setTitle("Compose feedback")
.setNegativeButton("CANCEL") { dialog, _ ->
dialog.dismiss()
}
.setPositiveButton("SEND") { dialog, _ ->
hideKeyboard()
dialog.dismiss()
val editText = view.findViewById<TextInputEditText>(R.id.edit_text_feedback)
val feedback = editText.text.toString()
val slackBody = SlackBody(feedback)
val parser = JsonParser();
val json = parser.parse(Gson().toJson(slackBody)) as JsonObject
sendFeedbackToSlack(json)
}
.show()

XML

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>

</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.feedback.FeedbackFragment">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edit_text_feedback"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="e.g. I found a bug in News section"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="16dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"/>


</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

Sending feedback to slack channel

private fun sendFeedbackToSlack(json: JsonObject) {
if (AppStatus.getInstance(context).isOnline) {
viewModel.uploadFeedback(json).observe(viewLifecycleOwner, Observer {
when (it.status) {
Status.SUCCESS -> {
if (it.data == "ok") {
displaySnackBar("Feedback sent successfully")
}
}
Status.ERROR -> {
displaySnackBar("Error sending feedback")
}
Status.LOADING -> {

}
}
})
} else {
displaySnackBar("Not connected to network")
}
}

Repository Code

I’m using Retrofit library

fun uploadFeedback(body: JsonObject): LiveData<Resource<String>> {

return object : NetworkBoundResource<String, String>(appExecutors) {
var result = ""
override fun saveCallResult(item: String) {
Timber.d(item)
result = item
}

override fun shouldFetch(data: String?): Boolean {
return true
}

override fun loadFromDb(): LiveData<String> {
return object : LiveData<String>() {
override fun onActive() {
super.onActive()
value = result
}
}
}

override fun createCall(): LiveData<ApiResponse<String>> {
return apiInterface.uploadFeedback("application/json",body)
}

override fun onFetchFailed(message: String) {
Timber.d(message)
super.onFetchFailed(message)
}
}.asLiveData()
}

Result

Feedback Dialog

Receiving feedback in slack channel

Android + Slack
Slack

That’s all! Feels like learnt something interesting ? Share with your friends too. Stay tuned to be notified about my new articles, Follow me on Medium & Twitter.

--

--