diff --git a/app/src/main/java/com/example/locationbasedservice/MainActivity.kt b/app/src/main/java/com/example/locationbasedservice/MainActivity.kt index c3aec08..cd70436 100644 --- a/app/src/main/java/com/example/locationbasedservice/MainActivity.kt +++ b/app/src/main/java/com/example/locationbasedservice/MainActivity.kt @@ -14,6 +14,16 @@ import org.osmdroid.tileprovider.tilesource.TileSourceFactory import org.osmdroid.util.GeoPoint import org.osmdroid.views.MapView import org.osmdroid.views.overlay.Marker +import android.location.Geocoder +import android.widget.Toast +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.osmdroid.events.MapEventsReceiver +import org.osmdroid.views.overlay.MapEventsOverlay +import java.util.Locale class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -31,53 +41,111 @@ class MainActivity : ComponentActivity() { @Composable fun OsmMapScreen() { - // State untuk Tipe Peta (Poin 3: Switching Map Views) - // Kita pakai Boolean: True = Normal, False = Topografi/Lainnya + val context = LocalContext.current + val scope = rememberCoroutineScope() // Untuk menjalankan proses background (Geocoding) + + // State var isNormalMode by remember { mutableStateOf(true) } + var selectedAddress by remember { mutableStateOf("Sentuh peta untuk cari alamat...") } + + // Kita simpan referensi MapView agar bisa dimanipulasi (tambah marker) dari luar AndroidView + var mapViewRef by remember { mutableStateOf(null) } Scaffold( + bottomBar = { + // Menampilkan Alamat Hasil Geocoding + Surface( + shadowElevation = 8.dp, + modifier = Modifier.fillMaxWidth() + ) { + Text( + text = selectedAddress, + modifier = Modifier.padding(16.dp), + style = MaterialTheme.typography.bodyLarge + ) + } + }, floatingActionButton = { ExtendedFloatingActionButton( onClick = { isNormalMode = !isNormalMode } ) { - Text(text = if (isNormalMode) "Mode Topografi" else "Mode Normal") + Text(text = if (isNormalMode) "Mode Topo" else "Mode Normal") } } ) { paddingValues -> Box(modifier = Modifier.padding(paddingValues).fillMaxSize()) { - // Poin 1: Menampilkan Peta OSM menggunakan AndroidView AndroidView( modifier = Modifier.fillMaxSize(), - factory = { context -> - // Inisialisasi MapView (Versi OSM) - MapView(context).apply { - setMultiTouchControls(true) // Poin 2: Mengaktifkan Zoom dengan jari (pinch) - - // Set titik awal (Contoh: Monas) - // Beda istilah: Google pakai LatLng, OSM pakai GeoPoint + factory = { ctx -> + MapView(ctx).apply { + setMultiTouchControls(true) val startPoint = GeoPoint(-6.175392, 106.827153) - controller.setZoom(18.0) // Level zoom + controller.setZoom(18.0) controller.setCenter(startPoint) - // Tambahkan Marker sederhana - val marker = Marker(this) - marker.position = startPoint - marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM) - marker.title = "Monas" - overlays.add(marker) + // --- LOGIKA SENTUH PETA (Poin 4) --- + val eventReceiver = object : MapEventsReceiver { + override fun singleTapConfirmedHelper(p: GeoPoint): Boolean { + // 1. Hapus marker lama (opsional, biar tidak penuh) + overlays.clear() + // Jangan lupa tambahkan ulang event overlay ini agar bisa diklik lagi + val eventsOverlay = MapEventsOverlay(this) + overlays.add(eventsOverlay) + + // 2. Tambah Marker Baru di titik sentuh + val marker = Marker(this@apply) + marker.position = p + marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM) + marker.title = "Lokasi Dipilih" + overlays.add(marker) + invalidate() // Refresh peta + + // 3. Lakukan Geocoding (Poin 5) + scope.launch(Dispatchers.IO) { + try { + val geocoder = Geocoder(ctx, Locale.getDefault()) + // Ambil max 1 hasil alamat + val addresses = geocoder.getFromLocation(p.latitude, p.longitude, 1) + + val resultText = if (!addresses.isNullOrEmpty()) { + val address = addresses[0] + // Gabungkan baris alamat (misal: Jl. Sudirman, Jakarta) + address.getAddressLine(0) + } else { + "Alamat tidak ditemukan" + } + + // Update UI harus di Main Thread + withContext(Dispatchers.Main) { + selectedAddress = resultText + marker.snippet = resultText + marker.showInfoWindow() // Tampilkan balon info otomatis + } + } catch (e: Exception) { + withContext(Dispatchers.Main) { + selectedAddress = "Error: Cek koneksi internet" + } + } + } + return true + } + + override fun longPressHelper(p: GeoPoint?): Boolean = false + } + + // Pasang "jaring" penangkap sentuhan ke peta + val eventsOverlay = MapEventsOverlay(eventReceiver) + overlays.add(eventsOverlay) + + mapViewRef = this } }, update = { view -> - // Kode disini dijalankan setiap kali ada perubahan State (isNormalMode berubah) - - // Poin 3: Logika ganti tipe peta if (isNormalMode) { - view.setTileSource(TileSourceFactory.MAPNIK) // Tampilan Standar OSM + view.setTileSource(TileSourceFactory.MAPNIK) } else { - view.setTileSource(TileSourceFactory.USGS_TOPO) // Tampilan Topografi (Gratis) - // Catatan: OSM tidak punya satelit gratis yang sebagus Google, - // jadi kita pakai Topo atau Public Transport sebagai alternatif tampilan. + view.setTileSource(TileSourceFactory.USGS_TOPO) } } )