in app reviews

This commit is contained in:
Hadrian Burkhardt
2026-05-08 18:41:07 +02:00
parent ad45c7ef27
commit 01922c16e7
5 changed files with 33 additions and 70 deletions
+2
View File
@@ -87,6 +87,8 @@ dependencies {
implementation("androidx.camera:camera-view:1.5.3") implementation("androidx.camera:camera-view:1.5.3")
implementation("com.google.mlkit:barcode-scanning:17.3.0") implementation("com.google.mlkit:barcode-scanning:17.3.0")
implementation("com.google.android.play:review:2.0.2")
implementation("com.google.android.play:review-ktx:2.0.2")
implementation("com.github.bitfireAT:vcard4android:main-SNAPSHOT") implementation("com.github.bitfireAT:vcard4android:main-SNAPSHOT")
implementation("androidx.room:room-runtime:2.8.4") implementation("androidx.room:room-runtime:2.8.4")
@@ -1,6 +1,5 @@
package de.softwareapp_hb.privateqrscanner.ui.screens package de.softwareapp_hb.privateqrscanner.ui.screens
import android.widget.Toast
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
@@ -9,7 +8,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Switch import androidx.compose.material3.Switch
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
@@ -22,7 +20,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import de.softwareapp_hb.privateqrscanner.R import de.softwareapp_hb.privateqrscanner.R
import de.softwareapp_hb.privateqrscanner.ui.UseCaseView import de.softwareapp_hb.privateqrscanner.ui.UseCaseView
import de.softwareapp_hb.privateqrscanner.util.Intents import de.softwareapp_hb.privateqrscanner.util.InAppReviewRequester
@Composable @Composable
fun SettingsScreen( fun SettingsScreen(
@@ -37,9 +35,7 @@ fun SettingsScreen(
) { ) {
val context = LocalContext.current val context = LocalContext.current
val showDeleteConfirm = remember { mutableStateOf(false) } val showDeleteConfirm = remember { mutableStateOf(false) }
val showFeatureRequestForm = remember { mutableStateOf(false) }
val showUseCasePicker = remember { mutableStateOf(false) } val showUseCasePicker = remember { mutableStateOf(false) }
val requesterNeed = remember { mutableStateOf("") }
if (showDeleteConfirm.value) { if (showDeleteConfirm.value) {
AlertDialog( AlertDialog(
@@ -61,51 +57,6 @@ fun SettingsScreen(
) )
} }
if (showFeatureRequestForm.value) {
AlertDialog(
onDismissRequest = { showFeatureRequestForm.value = false },
title = { Text(stringResource(R.string.feature_request_title)) },
text = {
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
OutlinedTextField(
value = requesterNeed.value,
onValueChange = { requesterNeed.value = it },
label = { Text(stringResource(R.string.feature_request_details)) }
)
}
},
confirmButton = {
TextButton(
onClick = {
val body = buildString {
appendLine("Request:")
append(requesterNeed.value.trim())
}
Intents.sendEmail(
context = context,
email = context.getString(R.string.support_email),
subject = context.getString(R.string.feature_request_subject),
body = body
)
showFeatureRequestForm.value = false
requesterNeed.value = ""
Toast.makeText(
context,
context.getString(R.string.feature_request_sent),
Toast.LENGTH_SHORT
).show()
},
enabled = requesterNeed.value.isNotBlank()
) { Text(stringResource(R.string.send_request)) }
},
dismissButton = {
TextButton(onClick = { showFeatureRequestForm.value = false }) {
Text(stringResource(R.string.cancel))
}
}
)
}
if (showUseCasePicker.value) { if (showUseCasePicker.value) {
AlertDialog( AlertDialog(
onDismissRequest = { showUseCasePicker.value = false }, onDismissRequest = { showUseCasePicker.value = false },
@@ -176,8 +127,8 @@ fun SettingsScreen(
Text(text = stringResource(R.string.licenses)) Text(text = stringResource(R.string.licenses))
Text(text = stringResource(R.string.contact)) Text(text = stringResource(R.string.contact))
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))
TextButton(onClick = { showFeatureRequestForm.value = true }) { TextButton(onClick = { InAppReviewRequester.requestReview(context) }) {
Text(text = stringResource(R.string.feature_request)) Text(text = stringResource(R.string.review_app))
} }
} }
} }
@@ -0,0 +1,26 @@
package de.softwareapp_hb.privateqrscanner.util
import android.app.Activity
import android.content.Context
import android.content.ContextWrapper
import com.google.android.play.core.review.ReviewManagerFactory
object InAppReviewRequester {
fun requestReview(context: Context) {
val activity = context.findActivity() ?: return
val manager = ReviewManagerFactory.create(activity)
manager.requestReviewFlow().addOnCompleteListener { request ->
if (request.isSuccessful) {
manager.launchReviewFlow(activity, request.result)
}
}
}
private tailrec fun Context.findActivity(): Activity? {
return when (this) {
is Activity -> this
is ContextWrapper -> baseContext.findActivity()
else -> null
}
}
}
+1 -9
View File
@@ -67,15 +67,7 @@
<string name="open_wifi_settings">WLAN-Einstellungen öffnen</string> <string name="open_wifi_settings">WLAN-Einstellungen öffnen</string>
<string name="add_contact">Kontakt hinzufügen</string> <string name="add_contact">Kontakt hinzufügen</string>
<string name="add_calendar_event">Kalendereintrag hinzufügen</string> <string name="add_calendar_event">Kalendereintrag hinzufügen</string>
<string name="support_email">softwareapp.hb@gmail.com</string> <string name="review_app">Bei Google Play bewerten</string>
<string name="feature_request">Feature-Request-Formular</string>
<string name="feature_request_title">Feature-Request</string>
<string name="feature_request_name">Dein Name</string>
<string name="feature_request_email">Deine E-Mail</string>
<string name="feature_request_details">Was brauchst du?</string>
<string name="feature_request_subject">Feature-Request von App-Nutzer</string>
<string name="send_request">Anfrage senden</string>
<string name="feature_request_sent">E-Mail-App wird geöffnet...</string>
<string name="active_use_case_view">Aktive Use-Case-Ansicht</string> <string name="active_use_case_view">Aktive Use-Case-Ansicht</string>
<string name="select_use_case_view">Use-Case-Ansicht wählen</string> <string name="select_use_case_view">Use-Case-Ansicht wählen</string>
<string name="use_case_everyday_personal">Alltägliche private Nutzung</string> <string name="use_case_everyday_personal">Alltägliche private Nutzung</string>
+1 -9
View File
@@ -67,15 +67,7 @@
<string name="open_wifi_settings">Open Wi-Fi settings</string> <string name="open_wifi_settings">Open Wi-Fi settings</string>
<string name="add_contact">Add contact</string> <string name="add_contact">Add contact</string>
<string name="add_calendar_event">Add calendar event</string> <string name="add_calendar_event">Add calendar event</string>
<string name="support_email">support@example.com</string> <string name="review_app">Review on Google Play</string>
<string name="feature_request">Feature request form</string>
<string name="feature_request_title">Feature request</string>
<string name="feature_request_name">Your name</string>
<string name="feature_request_email">Your email</string>
<string name="feature_request_details">What do you need?</string>
<string name="feature_request_subject">Feature request from app user</string>
<string name="send_request">Send request</string>
<string name="feature_request_sent">Opening email app...</string>
<string name="active_use_case_view">Active use-case view</string> <string name="active_use_case_view">Active use-case view</string>
<string name="select_use_case_view">Select use-case view</string> <string name="select_use_case_view">Select use-case view</string>
<string name="use_case_everyday_personal">Everyday personal use</string> <string name="use_case_everyday_personal">Everyday personal use</string>