Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions app/src/main/java/org/radarcns/detail/SettingsActivity.kt
Original file line number Diff line number Diff line change
@@ -1,19 +1,37 @@
package org.radarcns.detail

import android.app.AlertDialog
import android.content.ActivityNotFoundException
import android.content.DialogInterface
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.View
import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SwitchCompat
import androidx.appcompat.widget.Toolbar
import androidx.core.content.FileProvider
import androidx.lifecycle.lifecycleScope
import com.google.android.material.button.MaterialButton
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.radarbase.android.RadarApplication.Companion.radarConfig
import org.radarbase.android.RadarConfiguration
import org.radarbase.android.storage.extract.DatabaseToCSVExtractor
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.File

class SettingsActivity : AppCompatActivity() {
private lateinit var config: RadarConfiguration
private lateinit var progressOverlay: FrameLayout
private val csvExtractor: DatabaseToCSVExtractor = DatabaseToCSVExtractor()
private var responsiveOnTouch: Boolean = true

override fun onCreate(bundle: Bundle?) {
super.onCreate(bundle)
Expand Down Expand Up @@ -55,6 +73,14 @@ class SettingsActivity : AppCompatActivity() {
}

findViewById<MaterialButton>(R.id.reset_settings_button).setOnClickListener { v -> startReset(v) }
findViewById<MaterialButton>(R.id.share_app_status).setOnClickListener {
lifecycleScope.launch {
showSharingOptions()
}
}
progressOverlay = findViewById(R.id.progress_overlay)

let(csvExtractor::initialize)
}

private fun startReset(@Suppress("UNUSED_PARAMETER") view: View) {
Expand All @@ -71,10 +97,134 @@ class SettingsActivity : AppCompatActivity() {
}.show()
}

private fun emailSourceStatuses() {
val authority = "${packageName}.provider"
val file = File(filesDir, SOURCE_STATUS_FILE_PATH)
val fileUri: Uri = FileProvider.getUriForFile(this, authority, file)

val emailIntent = Intent(Intent.ACTION_SEND).apply {
type = TEXT_CSV
putExtra(Intent.EXTRA_EMAIL, arrayOf("rb-test@kcl.ac.uk"))
putExtra(Intent.EXTRA_SUBJECT, DEBUG_PAYLOAD_SUBJECT)
putExtra(Intent.EXTRA_TEXT, DEBUG_PAYLOAD_BODY)
putExtra(Intent.EXTRA_STREAM, fileUri)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}

val gmailIntent = Intent(emailIntent).apply {
setPackage("com.google.android.gm")
}

try {
startActivity(gmailIntent)
} catch (e: ActivityNotFoundException) {
startActivity(Intent.createChooser(emailIntent, "Send email via:"))
}
}

private fun emailNetworkStatuses() {
val authority = "${packageName}.provider"
val file = File(filesDir, NETWORK_STATUS_FILE_PATH)
val fileUri: Uri = FileProvider.getUriForFile(this, authority, file)

val emailIntent = Intent(Intent.ACTION_SEND).apply {
type = TEXT_CSV
putExtra(Intent.EXTRA_EMAIL, arrayOf("rb-test@kcl.ac.uk"))
putExtra(Intent.EXTRA_SUBJECT, DEBUG_PAYLOAD_SUBJECT)
putExtra(Intent.EXTRA_TEXT, DEBUG_PAYLOAD_BODY)
putExtra(Intent.EXTRA_STREAM, fileUri)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}

val gmailIntent = Intent(emailIntent).apply {
setPackage("com.google.android.gm")
}

try {
startActivity(gmailIntent)
} catch (e: ActivityNotFoundException) {
startActivity(Intent.createChooser(emailIntent, "Send email via:"))
}
}

private fun showSharingOptions() {
MaterialAlertDialogBuilder(
this,
com.google.android.material.R.style.ThemeOverlay_Material3_Dialog_Alert
)
.setIcon(R.drawable.baseline_share_files)
.setTitle("Select the entity you want to share")
.setMessage("Would you like to share data for Source Status or Network Status?")
.setPositiveButton("Sources") { dialogue: DialogInterface, _: Int ->
dialogue.dismiss()
lifecycleScope.launch(Dispatchers.Default) {
processSharing {
csvExtractor.exportSourceEntities()
}
emailSourceStatuses()
}
}
.setNegativeButton("Network") { dialogue: DialogInterface, _: Int ->
dialogue.dismiss()
lifecycleScope.launch(Dispatchers.Default) {
processSharing {
csvExtractor.exportNetworkEntities()
}
emailNetworkStatuses()
}
}.show()
}

private suspend fun processSharing(block: suspend () -> Unit) {
try {
enableProcessingUI()
block()
} catch (ex: IllegalStateException) {
logger.error("Failed to send debug payload files: {}", ex.message)
Toast.makeText(this, "Failed to share the files", Toast.LENGTH_LONG).show()
} finally {
disableProcessingUI()
}
}

private suspend fun enableProcessingUI() {
withContext(Dispatchers.Main) {
progressOverlay.visibility = View.VISIBLE
if (responsiveOnTouch) {
window.setFlags(
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
)
responsiveOnTouch = false
}
}
}

private suspend fun disableProcessingUI() {
withContext(Dispatchers.Main) {
progressOverlay.visibility = View.GONE
if (!responsiveOnTouch) {
window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
responsiveOnTouch = true
}
}
}

companion object {
private val logger: Logger = LoggerFactory.getLogger(SettingsActivity::class.java)

private val MANAGED_SETTINGS = arrayOf(
RadarConfiguration.SEND_ONLY_WITH_WIFI,
RadarConfiguration.SEND_OVER_DATA_HIGH_PRIORITY,
)

private const val TEXT_CSV = "text/csv"
private const val FILE_NAME_PREFIX = "application_status_"
private const val FILE_EXTENSION = ".csv"
private const val APPLICATION_PLUGIN_EXPORT_PATH = "org.radarbase.monitor.application.exports"
private const val NETWORK_STATUS_FILE_PATH = "${APPLICATION_PLUGIN_EXPORT_PATH}/${FILE_NAME_PREFIX}network${FILE_EXTENSION}"
private const val SOURCE_STATUS_FILE_PATH = "${APPLICATION_PLUGIN_EXPORT_PATH}/${FILE_NAME_PREFIX}source${FILE_EXTENSION}"
private const val DEBUG_PAYLOAD_SUBJECT = "RADAR pRMT Application Status Data"
private const val DEBUG_PAYLOAD_BODY = "Please find attached the exported CSV data for plugins and network status."
}
}
37 changes: 37 additions & 0 deletions app/src/main/res/layout/activity_settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@
android:layout_marginTop="@dimen/size_medium"
android:text="@string/button_reset" />

<com.google.android.material.button.MaterialButton
android:id="@+id/share_app_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="@dimen/size_xxlarge"
android:layout_marginTop="@dimen/size_medium"
android:text="@string/share_application_status" />

</LinearLayout>

</com.google.android.material.card.MaterialCardView>
Expand All @@ -73,4 +81,33 @@
app:popupTheme="@style/AppTheme.PopupOverlay"
app:title="RADAR pRMT" />
</com.google.android.material.appbar.AppBarLayout>

<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone"
android:id="@+id/progress_overlay">

<ProgressBar
android:id="@+id/pb_sharing"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:indeterminateTint="?attr/colorPrimary" />

<TextView
android:id="@+id/tv_sharing_progress_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/size_small"
android:text="@string/logout_progress_message"
android:textStyle="bold"
android:textColor="?attr/colorPrimary"
android:textAppearance="?android:attr/textAppearanceMedium"
android:visibility="gone" />
</FrameLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>
4 changes: 3 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
<string name="enable_data_high_priority_only">Use data plan for high priority data only.</string>
<string name="button_apply">Apply</string>
<string name="button_reset">Reset Settings</string>
<string name="share_application_status">Share App Status</string>
<string name="logout">Logout</string>
<string name="settings">Settings</string>
<string name="network_settings_header">Network settings</string>
Expand Down Expand Up @@ -153,6 +154,7 @@
<string name="reject_privacy_policy_button">Reject</string>
<string name="consent">Consent</string>
<string name="filter_split_regex">,</string>
<string name="logout_progress_message">Syncing sources...</string>
<string name="logout_progress_message">Syncing sources…</string>
<string name="sharing_progress_message">Processing……</string>
<string name="special_fgs_explanation">RadarService operates with plugins and modules that may need permissions beyond standard foreground service types. Defining a special use subtype ensures compliance with Android’s requirements for permissions that may vary dynamically based on active plugins</string>
</resources>