Implemented sending message log directly to a new backend service that either creates a new OsTicket ticket for us or sends message log to a codinux e-mail address. TODO: Sending it in BankingPresenter with Ktor did not work

This commit is contained in:
dankito 2020-12-20 21:44:58 +01:00
parent 0fbf376a89
commit 7170856f7e
9 changed files with 169 additions and 20 deletions

View File

@ -11,7 +11,7 @@ ext {
kotlinCoroutinesVersion = "1.3.7"
ktorVersion = "1.3.2"
ktorVersion = "1.4.2"
javaUtilsVersion = '1.0.16'

View File

@ -2,6 +2,7 @@ package net.dankito.banking.ui.android.dialogs
import android.content.ActivityNotFoundException
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@ -15,6 +16,15 @@ import net.dankito.banking.ui.android.di.BankingComponent
import net.dankito.banking.ui.presenter.BankingPresenter
import net.dankito.utils.android.extensions.hide
import net.dankito.utils.android.extensions.show
import net.dankito.utils.multiplatform.getInnerExceptionMessage
import net.dankito.utils.multiplatform.os.DeviceInfo
import net.dankito.banking.ui.model.issues.CreateTicketRequestDto
import net.dankito.banking.ui.model.issues.IssueDescriptionFormat
import net.dankito.utils.android.extensions.asActivity
import net.dankito.utils.serialization.JacksonJsonSerializer
import net.dankito.utils.web.client.OkHttpWebClient
import net.dankito.utils.web.client.RequestParameters
import net.dankito.utils.web.client.WebClientResponse
import javax.inject.Inject
@ -63,12 +73,15 @@ open class SendMessageLogDialog : DialogFragment() {
rootView.edtxtMessageLog.setText(context?.getString(R.string.dialog_send_message_courteously_add_error_description, messageLog))
}
rootView.btnSendMessageLog.setOnClickListener { sendMessageLog(rootView.edtxtMessageLog.text.toString()) }
rootView.btnSendMessageLogDirectly.setOnClickListener { sendMessageLogDirectly(rootView.edtxtMessageLog.text.toString()) }
rootView.btnSendMessageLogViaEMail.setOnClickListener { sendMessageLogViaEMail(rootView.edtxtMessageLog.text.toString()) }
rootView.btnCancel.setOnClickListener { dismiss() }
}
protected open fun sendMessageLog(messageLog: String) {
protected open fun sendMessageLogViaEMail(messageLog: String) {
// TODO: check if message log exceeds 120.000 characters
val sendMailActivity = Intent(Intent.ACTION_SEND)
sendMailActivity.type = "message/rfc822"
sendMailActivity.putExtra(Intent.EXTRA_EMAIL, arrayOf("panta.rhei@dankito.net"))
@ -78,12 +91,43 @@ open class SendMessageLogDialog : DialogFragment() {
try {
startActivity(Intent.createChooser(sendMailActivity, context?.getString(R.string.dialog_send_message_log_action_send_chooser_title)))
Toast.makeText(context, context?.getString(R.string.dialog_send_message_log_thanks_for_helping_making_app_better), Toast.LENGTH_LONG).show()
dismiss()
showSuccessfullySentMessageLog()
} catch (e: ActivityNotFoundException) {
Toast.makeText(context, context?.getString(R.string.dialog_send_message_log_error_no_app_to_send_message_found), Toast.LENGTH_LONG).show()
}
}
protected open fun sendMessageLogDirectly(messageLog: String) {
val deviceInfo = DeviceInfo(Build.MANUFACTURER.capitalize(), Build.MODEL, "Android", Build.VERSION.RELEASE, System.getProperty("os.arch") ?: "")
// TODO: sending with Ktor did not work
//presenter.sendMessageLogDirectly(messageLog, deviceInfo)
val requestBodyDto = CreateTicketRequestDto(messageLog, "Bankmeister", IssueDescriptionFormat.PlainText,
deviceInfo.osName, deviceInfo.osVersion, deviceInfo.manufacturer, deviceInfo.deviceModel)
val requestBody = JacksonJsonSerializer().serializeObject(requestBodyDto)
OkHttpWebClient().postAsync(RequestParameters("https://codinux.uber.space/issues", requestBody, "application/json")) { response ->
context?.asActivity()?.runOnUiThread {
handleSendMessageLogDirectlyResponseOnUiThread(response)
}
}
}
protected open fun handleSendMessageLogDirectlyResponseOnUiThread(response: WebClientResponse) {
if (response.isSuccessResponse) {
showSuccessfullySentMessageLog()
}
else {
Toast.makeText(context, context?.getString(R.string.dialog_send_message_log_error_could_not_sent_message_log, response.error?.getInnerExceptionMessage()),
Toast.LENGTH_LONG).show()
}
}
protected open fun showSuccessfullySentMessageLog() {
Toast.makeText(context, context?.getString(R.string.dialog_send_message_log_thanks_for_helping_making_app_better), Toast.LENGTH_LONG).show()
dismiss()
}
}

View File

@ -54,23 +54,33 @@
>
<Button
android:id="@+id/btnSendMessageLog"
android:id="@+id/btnCancel"
android:layout_width="@dimen/dialog_send_message_log_buttons_width"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/btnSendMessageLogViaEMail"
android:layout_toStartOf="@+id/btnSendMessageLogViaEMail"
style="?android:attr/buttonBarButtonStyle"
android:text="@string/cancel"
/>
<Button
android:id="@+id/btnSendMessageLogViaEMail"
android:layout_width="@dimen/dialog_send_message_log_buttons_width"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/btnSendMessageLogDirectly"
android:layout_toStartOf="@+id/btnSendMessageLogDirectly"
style="?android:attr/buttonBarButtonStyle"
android:text="@string/dialog_send_message_log_send_via_e_mail"
/>
<Button
android:id="@+id/btnSendMessageLogDirectly"
android:layout_width="@dimen/dialog_send_message_log_buttons_width"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
style="?android:attr/buttonBarButtonStyle"
android:text="@string/dialog_send_message_log_send"
/>
<Button
android:id="@+id/btnCancel"
android:layout_width="@dimen/dialog_send_message_log_buttons_width"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/btnSendMessageLog"
android:layout_toStartOf="@+id/btnSendMessageLog"
style="?android:attr/buttonBarButtonStyle"
android:text="@string/cancel"
android:text="@string/dialog_send_message_log_send_directly"
/>
</RelativeLayout>

View File

@ -222,12 +222,14 @@
<string name="dialog_send_message_log_message_log_label">Message Log</string>
<string name="dialog_send_message_log_send">Senden</string>
<string name="dialog_send_message_log_send_via_e_mail">Per E-Mail</string>
<string name="dialog_send_message_log_send_directly">Direkt senden</string>
<string name="dialog_send_message_log_info_no_message_log_entries_yet">Noch keine Message Log Einträge vorhanden. Führen Sie erst ein paar Aktionen durch, z. B. Abholen der Umsätze.</string>
<string name="dialog_send_message_courteously_add_error_description">Könnten Sie noch eine kurze Beschreibung des aufgetretenen Fehlers hinzufügen (z. B. was Sie zuvor in der App gemacht haben oder welches TAN Verfahren Sie verwendet haben)?\n\n\n%s</string>
<string name="dialog_send_message_log_mail_subject">Message Log</string>
<string name="dialog_send_message_log_action_send_chooser_title">Message Log senden …</string>
<string name="dialog_send_message_log_thanks_for_helping_making_app_better">Vielen Dank, dass sie uns dabei helfen die App besser zu machen!</string>
<string name="dialog_send_message_log_error_could_not_sent_message_log">Message Log konnte nicht gesendet werden:\n%s</string>
<string name="dialog_send_message_log_error_no_app_to_send_message_found">Keine E-Mail App zum Senden des Message Logs gefunden.</string>
</resources>

View File

@ -223,12 +223,14 @@
<string name="dialog_send_message_log_message_log_label">Message log</string>
<string name="dialog_send_message_log_send">Send</string>
<string name="dialog_send_message_log_send_via_e_mail">E-mail</string>
<string name="dialog_send_message_log_send_directly">Send directly</string>
<string name="dialog_send_message_log_info_no_message_log_entries_yet">No message log entries yet. First do some actions like requesting account transactions from bank.</string>
<string name="dialog_send_message_courteously_add_error_description">Could you courteously add a short description of the occurred error?\n\n\n%s</string>
<string name="dialog_send_message_log_mail_subject">Message Log</string>
<string name="dialog_send_message_log_action_send_chooser_title">Send message log…</string>
<string name="dialog_send_message_log_thanks_for_helping_making_app_better">Thanks a lot for helping us make the app better!</string>
<string name="dialog_send_message_log_error_could_not_sent_message_log">Message log could not be sent:\n%s</string>
<string name="dialog_send_message_log_error_no_app_to_send_message_found">There are no email clients to send message installed.</string>
</resources>

View File

@ -42,6 +42,13 @@ kotlin {
api project(":BankFinder")
api project(":EpcQrCodeParser")
// Ktor
api "io.ktor:ktor-client-core:$ktorVersion"
api "io.ktor:ktor-client-cio:$ktorVersion"
api "io.ktor:ktor-client-serialization:$ktorVersion"
api "io.ktor:ktor-client-logging:$ktorVersion"
api "org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1"
}
}

View File

@ -0,0 +1,15 @@
package net.dankito.banking.ui.model.issues
import kotlinx.serialization.Serializable
@Serializable
class CreateTicketRequestDto(
val issueDescription: String,
val applicationName: String,
val format: IssueDescriptionFormat = IssueDescriptionFormat.PlainText,
val osName: String? = null,
val osVersion: String? = null,
val deviceManufacturer: String? = null,
val deviceModel: String? = null
)

View File

@ -0,0 +1,10 @@
package net.dankito.banking.ui.model.issues
enum class IssueDescriptionFormat {
PlainText,
Html
}

View File

@ -35,8 +35,22 @@ import net.dankito.banking.util.extraction.NoOpTextExtractorRegistry
import net.codinux.banking.tools.epcqrcode.*
import net.dankito.banking.service.testaccess.TestAccessBankingClientCreator
import net.dankito.utils.multiplatform.*
import net.dankito.utils.multiplatform.getInnerExceptionMessage
import net.dankito.utils.multiplatform.log.LoggerFactory
import net.dankito.utils.multiplatform.os.DeviceInfo
import net.dankito.utils.multiplatform.os.DeviceInfoRetriever
import kotlin.collections.ArrayList
import io.ktor.client.*
import io.ktor.client.engine.cio.*
import io.ktor.client.features.json.*
import io.ktor.client.features.json.serializer.*
import io.ktor.client.request.*
import io.ktor.http.cio.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import net.dankito.banking.ui.model.issues.CreateTicketRequestDto
import net.dankito.banking.ui.model.issues.IssueDescriptionFormat
open class BankingPresenter(
@ -85,6 +99,18 @@ open class BankingPresenter(
protected set
protected val httpClient = HttpClient(CIO) {
install(JsonFeature) {
serializer = KotlinxSerializer(kotlinx.serialization.json.Json {
isLenient = true
ignoreUnknownKeys = true
allowSpecialFloatingPointValues = true
useArrayPolymorphism = false
})
}
}
protected val bankingClientsForBanks = mutableMapOf<TypedBankData, IBankingClient>()
protected val messageLogsOfFailedAccountAdditions = mutableListOf<MessageLogEntry>()
@ -813,6 +839,39 @@ open class BankingPresenter(
}
open fun sendMessageLogDirectly(messageLog: String) {
return sendMessageLogDirectly(messageLog, DeviceInfoRetriever().getDeviceInfo())
}
open fun sendMessageLogDirectly(messageLog: String, deviceInfo: DeviceInfo) {
// TODO: serialization with @Serializable does not work
//val requestBody = CreateTicketRequestDto(messageLog, "Bankmeister", IssueDescriptionFormat.PlainText,
//deviceInfo.osName, deviceInfo.osVersion, deviceInfo.manufacturer, deviceInfo.deviceModel)
val requestBody = """{
"applicationName": "Bankmeister",
"osName": "Android",
"issueDescription": "Test"
}""".trimIndent()
log.info("testBody: $requestBody")
GlobalScope.launch(Dispatchers.Main) {
try {
// TODO: sending with Ktor does not work. Sends request body in a way that it's not deserializable for Jackson
val response = httpClient.post<Response>("https://codinux.uber.space/issues") {
header("Content-Type", "application/json")
body = requestBody
}
log.info("Response: $response")
} catch (e: Exception) {
log.error("Could not create ticket directly: ${e.getInnerExceptionMessage()}", e)
}
}
}
open fun showAddAccountDialog() {
router.showAddAccountDialog(this)
}