feat: add gps
This commit is contained in:
parent
56ec2b4263
commit
c1b2fc181b
7
.idea/copilot.data.migration.agent.xml
generated
7
.idea/copilot.data.migration.agent.xml
generated
@ -24,6 +24,10 @@
|
|||||||
<option value="a20448f7-57cd-4a40-89b1-460451412588" />
|
<option value="a20448f7-57cd-4a40-89b1-460451412588" />
|
||||||
<option value="484561a1-1c08-44cd-bcd3-a53895fc3851" />
|
<option value="484561a1-1c08-44cd-bcd3-a53895fc3851" />
|
||||||
<option value="17ec376a-38fd-48ac-a4e1-52e9f7df3100" />
|
<option value="17ec376a-38fd-48ac-a4e1-52e9f7df3100" />
|
||||||
|
<option value="a0c23b11-ba1e-4275-a3e4-38b3c8fdbe00" />
|
||||||
|
<option value="3ac3800e-363e-4148-86b3-0d4f3b0a8b62" />
|
||||||
|
<option value="5460190d-c8ff-4194-9316-a6298c7cb54b" />
|
||||||
|
<option value="c640b33a-4bc6-4ee0-98ed-6a71e7270331" />
|
||||||
</set>
|
</set>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
@ -84,6 +88,9 @@
|
|||||||
<option value="file://$PROJECT_DIR$/app/build.gradle.kts" />
|
<option value="file://$PROJECT_DIR$/app/build.gradle.kts" />
|
||||||
<option value="file://$PROJECT_DIR$/app/src/main/java/id/ac/ubharajaya/panicbutton/MainActivity.kt" />
|
<option value="file://$PROJECT_DIR$/app/src/main/java/id/ac/ubharajaya/panicbutton/MainActivity.kt" />
|
||||||
<option value="file://$PROJECT_DIR$/app/src/main/java/id/ac/ubharajaya/panicbutton/NotificationSender.kt" />
|
<option value="file://$PROJECT_DIR$/app/src/main/java/id/ac/ubharajaya/panicbutton/NotificationSender.kt" />
|
||||||
|
<option value="file://$PROJECT_DIR$/app/src/main/java/id/ac/ubharajaya/panicbutton/MainViewModel.kt" />
|
||||||
|
<option value="file://$PROJECT_DIR$/app/src/main/java/id/ac/ubharajaya/panicbutton/MainScreen.kt" />
|
||||||
|
<option value="file://$PROJECT_DIR$/app/src/main/AndroidManifest.xml" />
|
||||||
</set>
|
</set>
|
||||||
</entry>
|
</entry>
|
||||||
<entry key="bf5061b4-a1e9-4600-a273-ea8e51b2ce89" />
|
<entry key="bf5061b4-a1e9-4600-a273-ea8e51b2ce89" />
|
||||||
|
|||||||
@ -2,6 +2,10 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
@ -34,5 +38,4 @@
|
|||||||
android:label="Detail Peta" />
|
android:label="Detail Peta" />
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package id.ac.ubharajaya.panicbutton
|
package id.ac.ubharajaya.panicbutton
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@ -11,16 +12,20 @@ import androidx.core.content.ContextCompat
|
|||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import com.google.android.gms.location.LocationServices
|
import com.google.android.gms.location.LocationServices
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
private lateinit var viewModel: MainViewModel
|
private lateinit var viewModel: MainViewModel
|
||||||
|
|
||||||
private val requestPermissionLauncher =
|
private val requestPermissionLauncher =
|
||||||
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
|
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
|
||||||
// result handled inline when requesting
|
// Inform user about permission result
|
||||||
|
if (isGranted) {
|
||||||
|
// User granted permission
|
||||||
|
// Ask user to press the panic button again to include location
|
||||||
|
if (::viewModel.isInitialized) viewModel.dialogMessage = "Izin lokasi diberikan. Tekan kembali untuk menyertakan koordinat."
|
||||||
|
} else {
|
||||||
|
if (::viewModel.isInitialized) viewModel.dialogMessage = "Izin lokasi ditolak. Laporan akan dikirim tanpa koordinat."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@ -33,8 +38,8 @@ class MainActivity : ComponentActivity() {
|
|||||||
startActivity(Intent(this, EvacuationMapsActivity::class.java))
|
startActivity(Intent(this, EvacuationMapsActivity::class.java))
|
||||||
}
|
}
|
||||||
|
|
||||||
// onSendAlert will try to get location (if permission granted) and then call viewModel.sendAlert
|
@SuppressLint("MissingPermission")
|
||||||
val onSendAlert = {
|
fun handleSendAlert() {
|
||||||
// Check permission
|
// Check permission
|
||||||
val fineGranted = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
val fineGranted = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
||||||
val coarseGranted = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
val coarseGranted = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
||||||
@ -44,28 +49,28 @@ class MainActivity : ComponentActivity() {
|
|||||||
requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
|
requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||||
// After permission flow, user will need to press the button again to actually send with location
|
// After permission flow, user will need to press the button again to actually send with location
|
||||||
viewModel.dialogMessage = "Izin lokasi dibutuhkan untuk menyertakan koordinat. Silakan tekan lagi setelah mengizinkan lokasi."
|
viewModel.dialogMessage = "Izin lokasi dibutuhkan untuk menyertakan koordinat. Silakan tekan lagi setelah mengizinkan lokasi."
|
||||||
return@let
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try get last location asynchronously
|
// Try get last location asynchronously via Task listeners
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
fusedClient.lastLocation
|
||||||
try {
|
.addOnSuccessListener { loc ->
|
||||||
val loc = fusedClient.lastLocation.await() // need extension await - we'll handle fallback
|
|
||||||
if (loc != null) {
|
if (loc != null) {
|
||||||
viewModel.sendAlert(loc.latitude, loc.longitude)
|
viewModel.sendAlert(loc.latitude, loc.longitude)
|
||||||
} else {
|
} else {
|
||||||
// fallback: send without coordinates
|
// fallback: send without coordinates
|
||||||
viewModel.sendAlert()
|
viewModel.sendAlert()
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
}
|
||||||
|
.addOnFailureListener {
|
||||||
|
// If obtaining location fails, send without coordinates
|
||||||
viewModel.sendAlert()
|
viewModel.sendAlert()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
MaterialTheme {
|
MaterialTheme {
|
||||||
MainScreen(viewModel = viewModel, onOpenEvacMaps = openEvacMaps)
|
MainScreen(viewModel = viewModel, onOpenEvacMaps = openEvacMaps, onSendAlert = ::handleSendAlert)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import androidx.compose.foundation.clickable
|
|||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
@ -22,9 +22,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.ui.draw.shadow
|
import androidx.compose.ui.draw.shadow
|
||||||
import androidx.compose.ui.draw.clip
|
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.foundation.layout.IntrinsicSize
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@ -91,17 +89,18 @@ fun MainScreen(viewModel: MainViewModel, onOpenEvacMaps: () -> Unit, onSendAlert
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dialog
|
// Dialog
|
||||||
val dialogMessage = viewModel.dialogMessage
|
viewModel.dialogMessage
|
||||||
if (!dialogMessage.isNullOrBlank()) {
|
?.takeIf { it.isNotBlank() }
|
||||||
AlertDialog(
|
?.let { msg ->
|
||||||
onDismissRequest = { viewModel.clearDialog() },
|
AlertDialog(
|
||||||
confirmButton = {
|
onDismissRequest = { viewModel.clearDialog() },
|
||||||
TextButton(onClick = { viewModel.clearDialog() }) { Text("OK") }
|
confirmButton = {
|
||||||
},
|
TextButton(onClick = { viewModel.clearDialog() }) { Text("OK") }
|
||||||
title = { Text("🚨 Notifikasi", style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold)) },
|
},
|
||||||
text = { Text(dialogMessage ?: "") }
|
title = { Text("🚨 Notifikasi", style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold)) },
|
||||||
)
|
text = { Text(msg) }
|
||||||
}
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user