diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c748c9a..588926d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -31,6 +31,10 @@ android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> + @@ -39,5 +43,24 @@ + + + + + + - \ No newline at end of file + + + + + + + + + + + + + + diff --git a/app/src/main/java/de/jadehs/strassenschadenpro2/LocationService.kt b/app/src/main/java/de/jadehs/strassenschadenpro2/LocationService.kt new file mode 100644 index 0000000..ac05288 --- /dev/null +++ b/app/src/main/java/de/jadehs/strassenschadenpro2/LocationService.kt @@ -0,0 +1,86 @@ +package de.jadehs.strassenschadenpro2 + +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.Service +import android.content.Intent +import android.os.Build +import android.os.IBinder +import android.os.Looper +import android.util.Log +import androidx.core.app.NotificationCompat +import com.google.android.gms.location.FusedLocationProviderClient +import com.google.android.gms.location.LocationCallback +import com.google.android.gms.location.LocationRequest +import com.google.android.gms.location.LocationResult +import com.google.android.gms.location.LocationServices +import com.google.android.gms.location.Priority + +class LocationService: Service() { + + private lateinit var fusedLocationClient: FusedLocationProviderClient + private lateinit var locationCallback: LocationCallback + + private val channelID = "1" + private val notificationID = 1 + + override fun onBind(p0: Intent?): IBinder? { + return null + } + + override fun onCreate() { + super.onCreate() + fusedLocationClient = LocationServices.getFusedLocationProviderClient(this) + locationCallback = object: LocationCallback() { + override fun onLocationResult(locationResult: LocationResult){ + for (location in locationResult.locations){ + val latitude = location.latitude + val longitude = location.longitude + Log.e("LocationService", "Location: $latitude, $longitude") + } + } + } + } + + override fun onStartCommand(intent: Intent?,flags: Int,startId: Int): Int { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ + val serviceChannel = NotificationChannel( + channelID, + "Location Service Channel", + NotificationManager.IMPORTANCE_DEFAULT + ) + val manager = getSystemService(NotificationManager::class.java) + manager?.createNotificationChannel(serviceChannel) + } + val notification = NotificationCompat.Builder(this, channelID) + .setContentTitle("Location Service") + .setContentText("Running...") + .setPriority(NotificationCompat.PRIORITY_DEFAULT) + .build() + startForeground(notificationID, notification) + val locationRequest = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY,60000).apply { + setMinUpdateIntervalMillis(30000) + }.build() + fusedLocationClient.requestLocationUpdates(locationRequest,locationCallback, Looper.getMainLooper()) + + return START_STICKY + } +} + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/java/de/jadehs/strassenschadenpro2/MainActivity.kt b/app/src/main/java/de/jadehs/strassenschadenpro2/MainActivity.kt index f2cdebb..f6e6b93 100644 --- a/app/src/main/java/de/jadehs/strassenschadenpro2/MainActivity.kt +++ b/app/src/main/java/de/jadehs/strassenschadenpro2/MainActivity.kt @@ -1,10 +1,17 @@ package de.jadehs.strassenschadenpro2 +import android.Manifest +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager import android.os.Bundle import android.util.Log +import android.widget.Toast import androidx.activity.ComponentActivity +import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -17,9 +24,11 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment @@ -28,7 +37,9 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.modifier.modifierLocalConsumer import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.core.content.ContextCompat import de.jadehs.strassenschadenpro2.ui.theme.StrassenSchadenPro2Theme +import kotlinx.coroutines.launch class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -36,9 +47,77 @@ class MainActivity : ComponentActivity() { enableEdgeToEdge() setContent { + if (checkPermissions(this)) { + startForegroundService(Intent(this, LocationService::class.java)) + } else { + RequestPermissions( + context = this, + onPermissionsGranted = { + startForegroundService(Intent(this, LocationService::class.java)) + } + ) + } StrassenSchadenPro2Theme { MainScreen(application=application) } } + + + + } } + + +fun checkPermissions(context: Context): Boolean { + // Check permissions to see if both permissions are granted. + // Coarse location permission. + val permissionCheckCoarseLocation = ContextCompat.checkSelfPermission( + context, + Manifest.permission.ACCESS_COARSE_LOCATION + ) == PackageManager.PERMISSION_GRANTED + // Fine location permission. + val permissionCheckFineLocation = ContextCompat.checkSelfPermission( + context, + Manifest.permission.ACCESS_FINE_LOCATION + ) == PackageManager.PERMISSION_GRANTED + //Notification permission + val permissionNotification = ContextCompat.checkSelfPermission( + context, + Manifest.permission.POST_NOTIFICATIONS + ) == PackageManager.PERMISSION_GRANTED + return permissionCheckCoarseLocation && permissionCheckFineLocation && permissionNotification +} + +fun showError(context: Context, message: String) { + Toast.makeText(context, message, Toast.LENGTH_LONG).show() +} + +@Composable +fun RequestPermissions(context: Context, onPermissionsGranted: () -> Unit) { + + // Create an activity result launcher using permissions contract and handle the result. + val activityResultLauncher = rememberLauncherForActivityResult( + ActivityResultContracts.RequestMultiplePermissions() + ) { permissions -> + // Check if both fine & coarse location permissions are true. + if (permissions.all { it.value }) { + onPermissionsGranted() + } else { + showError(context, "Location permissions were denied") + } + } + + LaunchedEffect(Unit) { + activityResultLauncher.launch( + // Request both fine and coarse location permissions. + arrayOf( + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.POST_NOTIFICATIONS + ) + ) + } + + +} \ No newline at end of file