diff --git a/app/src/main/java/net/thauvin/erik/android/tesremoteprogrammer/App.kt b/app/src/main/java/net/thauvin/erik/android/tesremoteprogrammer/App.kt new file mode 100644 index 0000000..00d6567 --- /dev/null +++ b/app/src/main/java/net/thauvin/erik/android/tesremoteprogrammer/App.kt @@ -0,0 +1,39 @@ +/* + * App.kt + * + * Copyright 2016-2017 Erik C. Thauvin (erik@thauvin.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.thauvin.erik.android.tesremoteprogrammer + +import android.app.Application +import android.content.Context +import net.thauvin.erik.android.tesremoteprogrammer.reporting.CrashEmailFactory +import net.thauvin.erik.android.tesremoteprogrammer.reporting.CrashReportActivity +import org.acra.ACRA +import org.acra.ReportingInteractionMode +import org.acra.annotation.ReportsCrashes + + +@ReportsCrashes(mailTo = "erik@thauvin.net", + mode = ReportingInteractionMode.DIALOG, + reportSenderFactoryClasses = arrayOf(CrashEmailFactory::class), + reportDialogClass = CrashReportActivity::class) + +open class App : Application() { + override fun attachBaseContext(base: Context) { + super.attachBaseContext(base) + ACRA.init(this) + } +} \ No newline at end of file diff --git a/app/src/main/java/net/thauvin/erik/android/tesremoteprogrammer/reporting/CrashEmail.kt b/app/src/main/java/net/thauvin/erik/android/tesremoteprogrammer/reporting/CrashEmail.kt new file mode 100644 index 0000000..0446b08 --- /dev/null +++ b/app/src/main/java/net/thauvin/erik/android/tesremoteprogrammer/reporting/CrashEmail.kt @@ -0,0 +1,70 @@ +/* + * CrashEmail.kt + * + * Copyright 2016-2017 Erik C. Thauvin (erik@thauvin.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.thauvin.erik.android.tesremoteprogrammer.reporting + +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.text.TextUtils +import net.thauvin.erik.android.tesremoteprogrammer.R +import org.acra.ACRAConstants +import org.acra.ReportField +import org.acra.collections.ImmutableSet +import org.acra.collector.CrashReportData +import org.acra.config.ACRAConfiguration +import org.acra.sender.ReportSender +import org.acra.sender.ReportSenderException + +class CrashEmail(private val config: ACRAConfiguration) : ReportSender { + + @Throws(ReportSenderException::class) + override fun send(context: Context, errorContent: CrashReportData) { + + val subject = context.getString(R.string.crash_report_subject, + context.getString(R.string.app_name)) + val body = buildBody(errorContent) + + val emailIntent = Intent(android.content.Intent.ACTION_SENDTO) + emailIntent.data = Uri.fromParts("mailto", config.mailTo(), null) + emailIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject) + emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, body) + context.startActivity(emailIntent) + } + + private fun buildBody(errorContent: CrashReportData): String { + var fields: Set = config.reportFields + if (fields.isEmpty()) { + fields = ImmutableSet(*ACRAConstants.DEFAULT_MAIL_REPORT_FIELDS) + } + val builder = StringBuilder() + for (field in fields) { + if (field == ReportField.USER_COMMENT || field == ReportField.STACK_TRACE) { + builder.append("-- ").append(field.toString()).append(" --\n") + } else { + builder.append(field.toString()).append('=') + } + val value = errorContent[field] + if (value != null) { + builder.append(TextUtils.join("\n\t", value.flatten())) + } + builder.append('\n') + } + return builder.toString() + } +} \ No newline at end of file diff --git a/app/src/main/java/net/thauvin/erik/android/tesremoteprogrammer/reporting/CrashEmailFactory.kt b/app/src/main/java/net/thauvin/erik/android/tesremoteprogrammer/reporting/CrashEmailFactory.kt new file mode 100644 index 0000000..78f622c --- /dev/null +++ b/app/src/main/java/net/thauvin/erik/android/tesremoteprogrammer/reporting/CrashEmailFactory.kt @@ -0,0 +1,28 @@ +/* + * CrashEmailFactory.kt + * + * Copyright 2016-2017 Erik C. Thauvin (erik@thauvin.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.thauvin.erik.android.tesremoteprogrammer.reporting + +import android.content.Context +import org.acra.config.ACRAConfiguration +import org.acra.sender.ReportSender +import org.acra.sender.ReportSenderFactory + +class CrashEmailFactory : ReportSenderFactory { + override fun create(context: Context, config: ACRAConfiguration): ReportSender = + CrashEmail(config) +} \ No newline at end of file diff --git a/app/src/main/java/net/thauvin/erik/android/tesremoteprogrammer/reporting/CrashReportActivity.kt b/app/src/main/java/net/thauvin/erik/android/tesremoteprogrammer/reporting/CrashReportActivity.kt new file mode 100644 index 0000000..f5f7f2d --- /dev/null +++ b/app/src/main/java/net/thauvin/erik/android/tesremoteprogrammer/reporting/CrashReportActivity.kt @@ -0,0 +1,75 @@ +/* + * CrashReportActivity.kt + * + * Copyright 2016-2017 Erik C. Thauvin (erik@thauvin.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.thauvin.erik.android.tesremoteprogrammer.reporting + +import android.content.DialogInterface +import android.os.Bundle +import android.support.v7.app.AlertDialog +import android.widget.EditText + +import net.thauvin.erik.android.tesremoteprogrammer.R + +import org.acra.dialog.BaseCrashReportDialog +import org.jetbrains.anko.find + +class CrashReportActivity : BaseCrashReportDialog(), DialogInterface.OnDismissListener, + DialogInterface.OnClickListener { + private var comment: EditText? = null + + companion object { + private val STATE_USER_COMMENT = "comment" + } + + override fun init(savedInstanceState: Bundle?) { + super.init(savedInstanceState) + + val dialog = AlertDialog.Builder(this) + .setTitle(getString(R.string.crash_dialog_title, getString(R.string.app_name))) + .setView(R.layout.crash_report_dialog) + .setPositiveButton(R.string.ok, this) + .setNegativeButton(R.string.cancel, this) + .create() + + dialog.setCanceledOnTouchOutside(false) + dialog.setOnDismissListener(this) + dialog.show() + + comment = dialog.find(android.R.id.input) + if (savedInstanceState != null) { + comment!!.setText(savedInstanceState.getString(STATE_USER_COMMENT)) + } + } + + override fun onDismiss(dialog: DialogInterface) { + finish() + } + + override fun onClick(dialog: DialogInterface, which: Int) { + if (which == DialogInterface.BUTTON_POSITIVE) { + sendCrash(comment!!.text.toString(), "") + } else { + cancelReports() + } + finish() + } + + override fun onSaveInstanceState(outState: Bundle) { + outState.putString(STATE_USER_COMMENT, comment!!.text.toString()) + super.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/crash_report_dialog.xml b/app/src/main/res/layout/crash_report_dialog.xml new file mode 100644 index 0000000..2fb2801 --- /dev/null +++ b/app/src/main/res/layout/crash_report_dialog.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + \ No newline at end of file