diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c661268957eb56058df4c347bcb3edc02b4c05b6..437046d6bfeb8fdf97f6d08556c233bd4d2c59ff 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -2,6 +2,7 @@ plugins { id("com.android.application") id("org.jetbrains.kotlin.android") id("kotlin-kapt") + id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") } android { @@ -49,6 +50,8 @@ dependencies { implementation("androidx.appcompat:appcompat:1.6.1") implementation("com.google.android.material:material:1.11.0") implementation("androidx.constraintlayout:constraintlayout:2.1.4") + implementation("com.google.android.gms:play-services-maps:18.2.0") + implementation("com.google.android.gms:play-services-location:21.2.0") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d5023aa6e4cd485afe0170a90f5e7811da1204fa..f862ae3e1f0597cea68b01a64a289308ed999585 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> - + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.INTERNET" /> <application @@ -10,6 +11,27 @@ android:roundIcon="@mipmap/ic_primary_logo_round" android:supportsRtl="true" android:theme="@style/Theme.NerbOS"> + + <!-- + TODO: Before you run your application, you need a Google Maps API key. + + To get one, follow the directions here: + + https://developers.google.com/maps/documentation/android-sdk/get-api-key + + Once you have your API key (it starts with "AIza"), define a new property in your + project's local.properties file (e.g. MAPS_API_KEY=Aiza...), and replace the + "YOUR_API_KEY" string in this file with "${MAPS_API_KEY}". + --> + <meta-data + android:name="com.google.android.geo.API_KEY" + android:value="AIzaSyBdVOQUHGOg7TS74kPCzoEtDDlGGZHpAEs" /> + + <activity + android:name=".MapsActivity" + android:exported="false" + android:label="@string/title_activity_maps" /> + <service android:name=".service.TokenCheckService" android:enabled="true" diff --git a/app/src/main/java/com/example/nerbos/MapsActivity.kt b/app/src/main/java/com/example/nerbos/MapsActivity.kt new file mode 100644 index 0000000000000000000000000000000000000000..8c00b4673c512ce92891c4d4b1b1a0061bfad4be --- /dev/null +++ b/app/src/main/java/com/example/nerbos/MapsActivity.kt @@ -0,0 +1,95 @@ +package com.example.nerbos + +import android.Manifest +import android.content.pm.PackageManager +import android.graphics.Camera +import android.location.Location +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import android.util.Log +import android.widget.Toast +import androidx.core.app.ActivityCompat + +import com.google.android.gms.maps.CameraUpdateFactory +import com.google.android.gms.maps.GoogleMap +import com.google.android.gms.maps.OnMapReadyCallback +import com.google.android.gms.maps.SupportMapFragment +import com.google.android.gms.maps.model.LatLng +import com.google.android.gms.maps.model.MarkerOptions +import com.example.nerbos.databinding.ActivityMapsBinding +import com.google.android.gms.location.FusedLocationProviderClient +import com.google.android.gms.location.LocationServices +import com.google.android.gms.maps.model.Marker + +class MapsActivity : AppCompatActivity(), OnMapReadyCallback, GoogleMap.OnMarkerClickListener { + + private lateinit var mMap: GoogleMap + private lateinit var binding: ActivityMapsBinding + + private lateinit var currentLocation: Location + private lateinit var fusedLocationProviderClient: FusedLocationProviderClient + private val permissionCode = 1 + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + binding = ActivityMapsBinding.inflate(layoutInflater) + setContentView(binding.root) + + // Obtain the SupportMapFragment and get notified when the map is ready to be used. + val mapFragment = supportFragmentManager + .findFragmentById(R.id.map) as SupportMapFragment + mapFragment.getMapAsync(this) + + fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this) + } + /** + * Manipulates the map once available. + * This callback is triggered when the map is ready to be used. + * This is where we can add markers or lines, add listeners or move the camera. In this case, + * we just add a marker near Sydney, Australia. + * If Google Play services is not installed on the device, the user will be prompted to install + * it inside the SupportMapFragment. This method will only be triggered once the user has + * installed Google Play services and returned to the app. + */ + override fun onMapReady(googleMap: GoogleMap) { + mMap = googleMap + + mMap.uiSettings.isZoomControlsEnabled = true + mMap.setOnMarkerClickListener ( this ) + setUpMap() + } + + private fun setUpMap() { + if (ActivityCompat.checkSelfPermission( + this, + Manifest.permission.ACCESS_FINE_LOCATION + ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( + this, + Manifest.permission.ACCESS_COARSE_LOCATION + ) != PackageManager.PERMISSION_GRANTED + ) { + ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), permissionCode) + Log.i("Maps", "Masuk Setup") + return + } + + mMap.isMyLocationEnabled = true + fusedLocationProviderClient.lastLocation.addOnSuccessListener (this){ + location -> if(location!=null){ + currentLocation = location + val currentLatLong = LatLng(location.latitude, location.longitude) + placeMarkerOnMap(currentLatLong) + mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLong, 7f)) + } + } + } + + private fun placeMarkerOnMap(currentLatLong: LatLng) { + val markerOptions = MarkerOptions().position(currentLatLong).title("Current Location") + mMap.addMarker(markerOptions) + Log.i("Maps", markerOptions.position.toString()) + } + + override fun onMarkerClick(p0: Marker) = false + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/nerbos/fragments/transaction/TransactionFragment.kt b/app/src/main/java/com/example/nerbos/fragments/transaction/TransactionFragment.kt index 14b0558317ff5d3a1d459d7ec05c5061e134296f..b92a7e3632c5b030eb9c5a93b15033b8d1e34666 100644 --- a/app/src/main/java/com/example/nerbos/fragments/transaction/TransactionFragment.kt +++ b/app/src/main/java/com/example/nerbos/fragments/transaction/TransactionFragment.kt @@ -1,7 +1,12 @@ package com.example.nerbos.fragments.transaction +import android.Manifest import android.app.AlertDialog import android.app.Dialog +import android.content.pm.PackageManager +import android.location.Address +import android.location.Geocoder +import android.location.Location import android.os.Bundle import android.text.TextUtils import android.util.Log @@ -17,6 +22,7 @@ import android.widget.RadioButton import android.widget.RadioGroup import android.widget.TextView import android.widget.Toast +import androidx.core.app.ActivityCompat import androidx.fragment.app.Fragment import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider @@ -28,6 +34,11 @@ import com.example.nerbos.model.TransactionCategory import com.example.nerbos.viewmodel.TransactionViewModel import com.example.nerbos.service.Authentication import com.example.nerbos.service.Utils +import com.google.android.gms.location.FusedLocationProviderClient +import com.google.android.gms.location.LocationServices +import com.google.android.gms.maps.CameraUpdateFactory +import com.google.android.gms.maps.model.LatLng +import java.util.Locale // TODO: Rename parameter arguments, choose names that match // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER @@ -45,6 +56,10 @@ class TransactionFragment : Fragment() { private var param2: String? = null private lateinit var transactionViewModel: TransactionViewModel private lateinit var authentication: Authentication + private var currentLocation: Location? = null + private lateinit var fusedLocationProviderClient: FusedLocationProviderClient + private lateinit var geocoder: Geocoder + private val permissionCode = 1 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -52,6 +67,8 @@ class TransactionFragment : Fragment() { param1 = it.getString(ARG_PARAM1) param2 = it.getString(ARG_PARAM2) } + fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(requireContext()) + geocoder = Geocoder(requireContext(), Locale.getDefault()) } override fun onCreateView( @@ -102,6 +119,14 @@ class TransactionFragment : Fragment() { dialog.dismiss() } + dialog.findViewById<EditText>(R.id.locationInput).setOnClickListener { + // TODO: Buat percabangan kalau ada internet + if (true){ + val etLocation= dialog.findViewById<EditText>(R.id.locationInput) + etLocation.setText(getAddressName()) + } + } + dialog.show() dialog.window!!.setBackgroundDrawableResource(R.drawable.round_corner_transparent) dialog.window!!.attributes = layoutParams @@ -214,6 +239,36 @@ class TransactionFragment : Fragment() { } } + private fun setLocation(){ + if (ActivityCompat.checkSelfPermission( + requireContext(), + Manifest.permission.ACCESS_FINE_LOCATION + ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( + requireContext(), + Manifest.permission.ACCESS_COARSE_LOCATION + ) != PackageManager.PERMISSION_GRANTED + ) { + ActivityCompat.requestPermissions(requireActivity(), arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), permissionCode) + return + } + fusedLocationProviderClient.lastLocation.addOnSuccessListener (requireActivity()){ + location -> + currentLocation = location + } + } + + private fun getAddressName() : String{ + // Hanya set otomatis jika mendapatkan permission, jika tidak input lokasi string + setLocation() + return if (currentLocation!=null){ + // Geocode to get the address string + val address = geocoder.getFromLocation(currentLocation!!.latitude, currentLocation!!.longitude, 1) + address!![0].getAddressLine(0) + } else { + "" + } + } + private fun inputCheck(name: String, nominal:Float, location:String): Boolean { return !(TextUtils.isEmpty(name) || TextUtils.isEmpty(location) || (nominal<0) ) } diff --git a/app/src/main/res/layout/activity_maps.xml b/app/src/main/res/layout/activity_maps.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec352fc6b1aa00e0353cac5e2f4c176086cc6900 --- /dev/null +++ b/app/src/main/res/layout/activity_maps.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<fragment xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:map="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/map" + android:name="com.google.android.gms.maps.SupportMapFragment" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".MapsActivity" /> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 01be6dda86dc3244c968ab95fb5d24b1607b4153..66a23ad733ac615225ad154abaaa1253ba76262d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -45,5 +45,6 @@ <string name="delete_success">Transaction successfully deleted</string> <string name="income">Income</string> <string name="outcome">Outcome</string> + <string name="title_activity_maps">MapsActivity</string> </resources> \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 98de0e48fee24c2754decc4211bfc712e0299e5f..1764a12d184f94f866991078a28422563e8d4935 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,4 +2,5 @@ plugins { id("com.android.application") version "8.3.1" apply false id("org.jetbrains.kotlin.android") version "1.9.22" apply false + id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") version "2.0.1" apply false } \ No newline at end of file