Skip to main content

Simplify Your Tax Calculations with GST Calculator 2024: The Ultimate Tool for Businesses and Individuals

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>


activity_main.xml

<?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>


MainActivity.kt

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()
            }

        }
    }

}



activity_location_picker.xml

 
<?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>


LocationPickerActivity.kt

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
    }

}


progress_dialog.xml

<?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

Popular posts from this blog

How to Insert Multiple rows in a single db transaction in Android Room Database? | Android | Room DB

  To insert multiple rows into a Room database in Android, you can follow these steps: 1. Set up Room Database: First, make sure you have set up your Room database correctly in your Android project. Define your Entity class, create a Database class that extends RoomDatabase, and set up your DAO (Data Access Object) interface. 2. Create Entity Class: Define an Entity class that represents the data you want to insert into the database. For example: 1 2 3 4 5 6 7 8 9 @Entity (tableName = "my_table" ) public class MyEntity { @PrimaryKey (autoGenerate = true ) public int id; public String name; public int age; // Add other fields and getters/setters as needed } Create DAO: Create a DAO interface with a method to insert multiple rows. For example: 1 2 3 4 5 @Dao public interface MyEntityDao { @Insert void insertAll (List<MyEntity> entities); } Initialise Database and DAO: In your application code, create an insta...

How to fetch Latitude, Longitude from address and vice-versa(address from Latitude, Longitude) using Google Geo coder SDK in android| Kotlin

 In this Android development related article, you will get a simple solution that, how to get address using Latitude, Longitude and vice-versa. i.e latitude, longitude from an address text. It is very easy and simple. Read full article and carefully follow all the steps. Here we use google Geocoder SDK. Okay, first we create an android project in kotlin and create an Activity say MainActivity.kt. Use the below code- Function get Latitude, Longitude from Address- fun getLatLngFromAddress (context: Context, mAddress: String): String { val coder = Geocoder(context) lateinit var address: List<Address> try { address = coder.getFromLocationName(mAddress, 5 ) if (address == null ) { return "Fail to find Lat,Lng" } val location = address[ 0 ] return " Latitude: ${location.latitude}\n Longitude: ${location.longitude}" } catch (e: Exception...

onBackPressed() method is deprecated, you are looking for an alternative? Here It is the Latest Solution in android | Kotlin

With the evolution of Android development, several APIs and functions get deprecated over time to make way for more robust and flexible alternatives. One such deprecation that developers need to be aware of is the onBackPressed() method in Android. In Android, onBackPressed() was commonly used to handle back button presses within an activity. However, with the introduction of the Jetpack libraries and the emphasis on more structured navigation, this method has been deprecated. This blog will explore why onBackPressed() is deprecated and what the best alternative solutions are in Kotlin for handling back navigation. Why onBackPressed() is Deprecated The primary reasons for deprecating onBackPressed() include: Improved Navigation Architecture: Android Jetpack's Navigation Component provides a more consistent and predictable way to handle navigation, including back navigation. Lifecycle Awareness: Handling back...