diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b075b1d..7b5fa4f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -20,6 +20,17 @@ + + + + diff --git a/app/src/main/java/cash/z/ecc/android/feedback/FeedbackFile.kt b/app/src/main/java/cash/z/ecc/android/feedback/FeedbackFile.kt index 339c019..8f31fde 100644 --- a/app/src/main/java/cash/z/ecc/android/feedback/FeedbackFile.kt +++ b/app/src/main/java/cash/z/ecc/android/feedback/FeedbackFile.kt @@ -5,12 +5,15 @@ import okio.Okio import java.io.File import java.text.SimpleDateFormat -class FeedbackFile(fileName: String = "feedback.log") : +class FeedbackFile(fileName: String = "user_log.txt") : FeedbackCoordinator.FeedbackObserver { - val file = File(ZcashWalletApp.instance.noBackupFilesDir, fileName) + val file = File("${ZcashWalletApp.instance.filesDir}/logs", fileName) private val format = SimpleDateFormat("MM-dd HH:mm:ss.SSS") + init { + if (!file.parentFile.exists()) file.parentFile.mkdirs() + } override fun onMetric(metric: Feedback.Metric) { appendToFile(metric.toString()) diff --git a/app/src/main/java/cash/z/ecc/android/ui/profile/ProfileFragment.kt b/app/src/main/java/cash/z/ecc/android/ui/profile/ProfileFragment.kt index 529005f..e59fa5b 100644 --- a/app/src/main/java/cash/z/ecc/android/ui/profile/ProfileFragment.kt +++ b/app/src/main/java/cash/z/ecc/android/ui/profile/ProfileFragment.kt @@ -1,23 +1,34 @@ package cash.z.ecc.android.ui.profile +import android.content.Context import android.content.Intent +import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.View +import androidx.core.content.FileProvider.getUriForFile import cash.z.ecc.android.BuildConfig import cash.z.ecc.android.R +import cash.z.ecc.android.ZcashWalletApp import cash.z.ecc.android.databinding.FragmentProfileBinding import cash.z.ecc.android.di.viewmodel.viewModel import cash.z.ecc.android.ext.onClick import cash.z.ecc.android.ext.onClickNavBack import cash.z.ecc.android.ext.onClickNavTo import cash.z.ecc.android.feedback.FeedbackFile +import cash.z.ecc.android.feedback.Report +import cash.z.ecc.android.feedback.Report.Tap.* import cash.z.ecc.android.ui.base.BaseFragment import cash.z.wallet.sdk.ext.toAbbreviatedAddress +import cash.z.wallet.sdk.ext.twig import kotlinx.coroutines.launch import okio.Okio +import java.io.File +import java.io.IOException + class ProfileFragment : BaseFragment() { + override val screen = Report.Screen.PROFILE private val viewModel: ProfileViewModel by viewModel() @@ -26,13 +37,20 @@ class ProfileFragment : BaseFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - binding.hitAreaClose.onClickNavBack() - binding.buttonBackup.onClickNavTo(R.id.action_nav_profile_to_nav_backup) + binding.hitAreaClose.onClickNavBack() { tapped(PROFILE_CLOSE) } + binding.buttonBackup.onClickNavTo(R.id.action_nav_profile_to_nav_backup) { tapped(PROFILE_BACKUP) } binding.textVersion.text = BuildConfig.VERSION_NAME onClick(binding.buttonLogs) { + tapped(PROFILE_VIEW_USER_LOGS) onViewLogs() } + binding.buttonLogs.setOnLongClickListener { + tapped(PROFILE_VIEW_DEV_LOGS) + onViewDevLogs() + true + } onClick(binding.buttonFeedback) { + tapped(PROFILE_SEND_FEEDBACK) onSendFeedback() } } @@ -45,31 +63,63 @@ class ProfileFragment : BaseFragment() { } private fun onViewLogs() { - loadLogFileAsText().let { logText -> - if (logText == null) { - mainActivity?.showSnackbar("Log file not found!") - } else { - val sendIntent: Intent = Intent().apply { - action = Intent.ACTION_SEND - putExtra(Intent.EXTRA_TEXT, logText) - type = "text/plain" - } + shareFile(userLogFile()) + } - val shareIntent = Intent.createChooser(sendIntent, "Share Log File") - startActivity(shareIntent) + private fun onViewDevLogs() { + shareFile(writeLogcat()) + } + + private fun shareFiles(vararg files: File?) { + val uris = arrayListOf().apply { + files.filterNotNull().mapNotNull { + getUriForFile(ZcashWalletApp.instance, "${BuildConfig.APPLICATION_ID}.fileprovider", it) + }.forEach { + add(it) } } + val intent = Intent(Intent.ACTION_SEND_MULTIPLE).apply { + putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris) + type = "text/*" + } + startActivity(Intent.createChooser(intent, "Share Log Files")) + } + + fun shareFile(file: File?) { + file ?: return + val uri = getUriForFile(ZcashWalletApp.instance, "${BuildConfig.APPLICATION_ID}.fileprovider", file) + val intent = Intent(Intent.ACTION_SEND).apply { + putExtra(Intent.EXTRA_STREAM, uri) + type = "text/plain" + } + startActivity(Intent.createChooser(intent, "Share Log File")) } private fun onSendFeedback() { mainActivity?.showSnackbar("Feedback feature coming soon!") } + private fun userLogFile(): File? { + return mainActivity?.feedbackCoordinator?.findObserver()?.file + } + private fun loadLogFileAsText(): String? { - val feedbackFile: FeedbackFile = - mainActivity?.feedbackCoordinator?.findObserver() ?: return null - Okio.buffer(Okio.source(feedbackFile.file)).use { + val feedbackFile: File = userLogFile() ?: return null + Okio.buffer(Okio.source(feedbackFile)).use { return it.readUtf8() } } + + private fun writeLogcat(): File? { + try { + val outputFile = File("${ZcashWalletApp.instance.filesDir}/logs", "developer_log.txt") + val cmd = arrayOf("/bin/sh", "-c", "logcat -v time -d | grep \"@TWIG\" > ${outputFile.absolutePath}") + Runtime.getRuntime().exec(cmd) + return outputFile + } catch (e: IOException) { + e.printStackTrace() + twig("Failed to create log") + } + return null + } } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_profile.xml b/app/src/main/res/layout/fragment_profile.xml index 863d2fb..d49117a 100644 --- a/app/src/main/res/layout/fragment_profile.xml +++ b/app/src/main/res/layout/fragment_profile.xml @@ -161,7 +161,7 @@ android:layout_marginTop="16dp" style="@style/TextAppearance.AppCompat.Body1" android:textSize="16sp" - android:text="See Application Log" + android:text="See Application Logs" android:textColor="@color/selector_button_text_light_dimmed" app:layout_constraintTop_toBottomOf="@id/button_backup" app:layout_constraintEnd_toEndOf="parent" diff --git a/app/src/main/res/xml/file_paths.xml b/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000..c66b0a5 --- /dev/null +++ b/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file