How to get Android Device Current locaction, i.e latitude and longitude in Kotlin Using Fused Location SDK.
In this Android development article, you will learn, how to get device current location in android kotlin using Google Fused Location Client SDK.
Now a days, device current location fetching is a common feature in many applications, and for us we need to write same code in every project. So I make this code in such a way that, we can integrate the device location pick feature (i.e latitude, longitude ) within 5 minute. Just follow this steps-
Okay, first we create an android project and create a activity
MainActivity.kt and respective xml file is activity_main.xml
Add Location Permission in AndroidMenifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.devicecurrentlocation"> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".LocationPickerActivity" android:excludeFromRecents="true" android:label=" " android:screenOrientation="portrait" android:theme="@style/Transparent" /> <activity android:name=".MainActivity" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
styles.xml
<resources xmlns:tools="http://schemas.android.com/tools"> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorAccent">@color/colorAccent</item> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> </style> <style name="Transparent" parent="Theme.AppCompat.Dialog"> <item name="android:windowIsTranslucent">true</item> <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowNoTitle">true</item> <item name="android:windowIsFloating">true</item> <item name="android:backgroundDimEnabled">true</item> <item name="android:windowCloseOnTouchOutside">true</item> </style> <style name="TransparentDialog" parent="Theme.AppCompat.Light.Dialog"> <item name="android:windowFrame">@null</item> <item name="android:windowIsTranslucent">true</item> <item name="android:layout_gravity">top</item> <item name="android:windowMinWidthMajor">90%</item> <item name="android:windowMinWidthMinor">90%</item> <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowNoTitle">true</item> <item name="android:windowActionBar">false</item> <item name="android:windowIsFloating">true</item> <item name="android:backgroundDimEnabled">true</item> <item name="android:windowCloseOnTouchOutside">true</item> <item name="android:windowFullscreen">false</item> </style> </resources>
colors.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorAccent">#00C0A5</color> <color name="colorPrimary">#00C0A5</color> <color name="colorPrimaryDark">#00C0A5</color> </resources>
strings.xml
<resources> <string name="app_name">DeviceCurrentLocation</string> <string name="current_device_location">Current Device Location</string> <string name="get_location">Get Location</string> <string name="loading">Loading</string> </resources>
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/current_device_location" android:textSize="25sp" app:layout_constraintBottom_toBottomOf="@+id/guideline" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent=".30" /> <Button android:id="@+id/btnLocation" android:layout_width="match_parent" android:layout_height="55dp" android:layout_marginStart="15dp" android:layout_marginEnd="15dp" android:text="@string/get_location" app:layout_constraintTop_toTopOf="@+id/guideline" /> <TextView android:id="@+id/tvLatLng" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="25sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@+id/btnLocation" /> </androidx.constraintlayout.widget.ConstraintLayout>
package com.example.devicecurrentlocation import android.annotation.SuppressLint import android.app.Activity import android.content.Intent import android.os.Bundle import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult import androidx.appcompat.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_main.* import org.json.JSONObject class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) btnLocation.setOnClickListener { val intent = Intent(this, LocationPickerActivity::class.java) resultLauncher.launch(intent) } } @SuppressLint("SetTextI18n") private val resultLauncher = registerForActivityResult(StartActivityForResult()) { result -> if (result.resultCode == Activity.RESULT_OK) { // There are no request codes try { val data: Intent? = result.data val mJson = JSONObject(data?.getStringExtra("response")!!) tvLatLng.text = "Latitude: ${mJson.optString("lat")}" + "\nLongitude: ${mJson.optString("lng")}" } catch (e: Exception) { e.printStackTrace() } } } }
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".LocationPickerActivity"> </androidx.constraintlayout.widget.ConstraintLayout>
package com.example.devicecurrentlocation import android.Manifest import android.annotation.SuppressLint import android.app.Activity import android.app.AlertDialog import android.app.Dialog import android.content.Context import android.content.Intent import android.content.IntentSender.SendIntentException import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.location.Location import android.net.Uri import android.os.Bundle import android.os.Looper import android.provider.Settings import android.view.LayoutInflater import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.google.android.gms.common.api.ApiException import com.google.android.gms.common.api.ResolvableApiException import com.google.android.gms.location.* import com.karumi.dexter.BuildConfig import com.karumi.dexter.Dexter import com.karumi.dexter.MultiplePermissionsReport import com.karumi.dexter.PermissionToken import com.karumi.dexter.listener.multi.MultiplePermissionsListener import kotlinx.android.synthetic.main.progress_dialog.view.* import org.json.JSONObject import java.text.DateFormat import java.util.* class LocationPickerActivity : AppCompatActivity(), MultiplePermissionsListener { private val updateIntervalInMillisecond: Long = 10000 private val fastestUpdateIntervalInMilliseconds: Long = 5000 private val requestCheckSettings = 100 private val context: Context = this // location last updated time var mLastUpdateTime: String? = null private var mFusedLocationClient: FusedLocationProviderClient? = null private var mSettingsClient: SettingsClient? = null private var mLocationRequest: LocationRequest? = null private var mLocationSettingsRequest: LocationSettingsRequest? = null private var mLocationCallback: LocationCallback? = null var mCurrentLocation: Location? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_location_picker) this.setFinishOnTouchOutside(false) reqLocationPermission() } private fun reqLocationPermission() { Dexter.withContext(this) .withPermissions( Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION ) .withListener(this).onSameThread() .check() } private fun initLocation() { mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this) mSettingsClient = LocationServices.getSettingsClient(this) mLocationCallback = object : LocationCallback() { override fun onLocationResult(locationResult: LocationResult) { super.onLocationResult(locationResult) // location is received mCurrentLocation = locationResult.lastLocation mLastUpdateTime = DateFormat.getTimeInstance().format(Date()) updateLocationUI() } } mLocationRequest = LocationRequest() mLocationRequest!!.interval = updateIntervalInMillisecond mLocationRequest!!.fastestInterval = fastestUpdateIntervalInMilliseconds mLocationRequest!!.priority = LocationRequest.PRIORITY_HIGH_ACCURACY val builder = LocationSettingsRequest.Builder() builder.addLocationRequest(mLocationRequest!!).setAlwaysShow(true).setNeedBle(true) mLocationSettingsRequest = builder.build() } @SuppressLint("MissingPermission") private fun startLocationUpdates() { mSettingsClient ?.checkLocationSettings(mLocationSettingsRequest!!) ?.addOnSuccessListener(this) { mFusedLocationClient!!.requestLocationUpdates( mLocationRequest!!, mLocationCallback!!, Looper.myLooper()!! ) // Toast.makeText(context, "startLocationUpdates before", Toast.LENGTH_SHORT).show(); // updateLocationUI(); // Toast.makeText(context, "startLocationUpdates after", Toast.LENGTH_SHORT).show(); } ?.addOnFailureListener(this) { e -> when ((e as ApiException).statusCode) { LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> { try { // Show the dialog by calling startResolutionForResult(), and check the // result in onActivityResult(). val rae = e as ResolvableApiException rae.startResolutionForResult( this, requestCheckSettings ) } catch (sie: SendIntentException) { } } LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> { val errorMessage = "Location settings are inadequate, and cannot be " + "fixed here. Fix in Settings." Toast.makeText(context, errorMessage, Toast.LENGTH_LONG).show() } } //updateLocationUI(); } } private fun stopLocationUpdates() { // Removing location updates mFusedLocationClient ?.removeLocationUpdates(mLocationCallback) ?.addOnCompleteListener(this) { //Toast.makeText(getApplicationContext(), "Location updates stopped!", Toast.LENGTH_SHORT).show(); } } fun updateLocationUI() { var loc: String? = null if (mCurrentLocation != null) { loc = "Lat: " + mCurrentLocation!!.latitude + ", " + "Lng: " + mCurrentLocation!!.longitude try { val mObject = JSONObject() mObject.put("lat", mCurrentLocation!!.latitude) mObject.put("lng", mCurrentLocation!!.longitude) mObject.put("date_in_mili", mCurrentLocation!!.time) //mObject.put("address", Util.getCompleteAddressString(context,mCurrentLocation!!.latitude,mCurrentLocation!!.longitude)) // PrefUtils.saveUserLocation(context,mObject.toString().trim()) successResult(mObject) } catch (e: Exception) { e.printStackTrace() } stopLocationUpdates() } // giving a blink animation on TextView } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when (requestCode) { requestCheckSettings -> when (resultCode) { Activity.RESULT_OK -> reqLocationPermission() Activity.RESULT_CANCELED -> cancelResult() } } } private fun openSettings() { val intent = Intent() intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS val uri = Uri.fromParts( "package", BuildConfig.APPLICATION_ID, null ) intent.data = uri intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK //startActivityForResult(intent,REQUEST_CHECK_SETTINGS) startActivity(intent) finish() } private fun successResult(json: JSONObject) { val intent: Intent = intent intent.putExtra("response", json.toString()) setResult(Activity.RESULT_OK, intent) finish() } private fun cancelResult() { val intent: Intent = intent setResult(Activity.RESULT_CANCELED, intent) finish() } override fun onPermissionsChecked(report: MultiplePermissionsReport) { // Here you have to check granted permissions if (report.areAllPermissionsGranted()) { val dialog = progressDialog(context, getString(R.string.loading)) dialog.show() initLocation() startLocationUpdates() } else { if (report.isAnyPermissionPermanentlyDenied) { showSettingsDialog() } else { reqLocationPermission() } } } override fun onPermissionRationaleShouldBeShown( p0: MutableList<com.karumi.dexter.listener.PermissionRequest>?, token: PermissionToken? ) { token?.continuePermissionRequest() } private fun showSettingsDialog() { val builder: AlertDialog.Builder = AlertDialog.Builder(this) builder.setTitle("Need Permissions") builder.setMessage("This app needs permission to use this feature. You can grant them in app settings.") builder.setPositiveButton( "GOTO SETTINGS" ) { dialog, _ -> dialog.cancel() openSettings() } builder.setNegativeButton( "Cancel" ) { dialog, _ -> dialog.cancel() cancelResult() } builder.show() } @SuppressLint("InflateParams") fun progressDialog(context: Context, message: String): Dialog { val dialog = Dialog(context, R.style.TransparentDialog) val inflate = LayoutInflater.from(context).inflate(R.layout.progress_dialog, null) dialog.setContentView(inflate) inflate.tvMessage.text = message dialog.setCancelable(false) dialog.window!!.setBackgroundDrawable( ColorDrawable(Color.TRANSPARENT) ) return dialog } }
<?xml version="1.0" encoding="utf-8"?> <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="80dp"> <ProgressBar android:id="@+id/progressBar" style="?android:attr/progressBarStyle" android:layout_width="40dp" android:layout_height="40dp" android:layout_centerVertical="true" android:layout_margin="15dp" android:backgroundTint="@color/colorAccent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/tvMessage" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_margin="7dp" android:layout_toEndOf="@+id/progressBar" android:text="@string/loading" app:layout_constraintBottom_toBottomOf="@id/progressBar" app:layout_constraintStart_toEndOf="@id/progressBar" app:layout_constraintTop_toTopOf="@id/progressBar" /> </androidx.constraintlayout.widget.ConstraintLayout> </androidx.cardview.widget.CardView>
Comments
Post a Comment