'Get current location inside a fragment

I need to get the current location of the user and store its values in separate longitude and latitude variables. Right now in the following code I have set them statically.

Here is my Location Fragment (all my fragments are displayed inside an Activity using viewpager):

package com.example.atry.MakeComplaint

import Retrofit.INodeJS
import Retrofit.Observables
import Retrofit.RetrofitClient
import android.app.Activity
import android.content.ContentValues.TAG
import android.content.Context
import android.content.Context.*
import android.content.Intent
import android.content.IntentSender
import android.content.pm.PackageManager
import android.location.*
import android.net.Uri
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.android.gms.maps.MapView

import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.example.atry.R
import com.google.android.gms.common.GooglePlayServicesNotAvailableException
import com.google.android.gms.common.api.ResolvableApiException
import com.google.android.gms.dynamic.SupportFragmentWrapper
import com.google.android.gms.location.*
import com.google.android.gms.maps.*
import com.google.android.gms.maps.model.*
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.fragment_complaint_details.view.*
import kotlinx.android.synthetic.main.fragment_location.*
import kotlinx.android.synthetic.main.fragment_location.view.*
import retrofit2.Call
import retrofit2.Response
import java.io.IOException
import java.util.Observer
import java.util.Optional.empty
import javax.security.auth.callback.Callback


class LocationFragment : Fragment(), OnMapReadyCallback, GoogleMap.OnMarkerClickListener {

    override fun onMarkerClick(p0: Marker?)= false

    private lateinit var map: GoogleMap
    private lateinit var mapView : MapView
//    lateinit var typeName: String
    lateinit var myAPI: INodeJS
    var MyCategory: Observables.ComplaintType?=null


    private var listener: OnLocationFragmentInteractionListener? = null


    var objectComplaint =
        Observables.Complaint(
        1 , "dummy problem" ,
        "url" ,
        Observables.Location("78.4","17.4"),
        Observables.ComplaintType("Smell", "null"),
        Observables.Status(2 , "Unresolved")

    )






    //for updating user's location/ for current location

    private lateinit var fusedLocationClient: FusedLocationProviderClient
    private lateinit var lastLocation: Location
    private lateinit var locationCallback: LocationCallback
    private lateinit var locationRequest: LocationRequest
    private var locationUpdateState = false

    companion object {
        private const val LOCATION_PERMISSION_REQUEST_CODE = 1

        private const val REQUEST_CHECK_SETTINGS = 2  //For updating user's location as they move

    }







    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val permissions = arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION)
        requestPermissions( permissions,0)
        arguments?.let {

        }

        //INIT API

        val retrofit = RetrofitClient.instanc
        myAPI = retrofit.create(INodeJS::class.java)

        //static way of bringing category names

//        if(arguments!!.getString("typeName") !=null){
//
//            typeName =arguments!!.getString("typeName")
//            Log.d("got it!!",typeName)
//
//        }




    }


    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        val v = inflater.inflate(com.example.atry.R.layout.fragment_location, container, false)
        mapView = v.findViewById(R.id.maps)
        mapView.onCreate(savedInstanceState)
        mapView.onResume()




       try {
        MapsInitializer.initialize(getActivity()!!.getApplicationContext());
    } catch (sendEx: IntentSender.SendIntentException) {
        sendEx.printStackTrace();
    }

        mapView.getMapAsync(this)




        v.backToList.setOnClickListener {
            backFragment()

        }

        v.forwardToDescription.setOnClickListener{
            getAllData()


        }

        return v
    }

    override public fun onResume() {
    super.onResume();
    mapView.onResume();
}

override public fun onPause() {
    super.onPause();
    mapView.onPause();
}

override public fun onDestroy() {
    super.onDestroy();
    mapView.onDestroy();
}

override public fun onLowMemory() {
    super.onLowMemory();
    mapView.onLowMemory()
}

    override fun onMapReady(googleMap: GoogleMap?) {
        map = googleMap!!
        map.uiSettings?.isZoomControlsEnabled = true
        map.isMyLocationEnabled = true
//        var criteria = Criteria()
//        var locationManager = context!!.getSystemService(LOCATION_SERVICE) as LocationManager
//        var provider = locationManager.getBestProvider(criteria, true)
//        var location = locationManager.getLastKnownLocation(provider)
//        var latitude = location.latitude
//        var longitude = location.longitude




//         latitude and longitude
        val latitude = 17.385044
        val longitude = 78.486671

        val marker = MarkerOptions().position(LatLng(latitude,longitude)).title("hello maps")

        marker.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED))

        map.addMarker(marker)

        val cameraPosition = CameraPosition.builder().target(LatLng(latitude,longitude)).zoom(12f).build()
        map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))


    }

    private fun backFragment() {
        val manager = (context as AppCompatActivity).supportFragmentManager
        manager.popBackStackImmediate()
    }


    fun sendCategoryItem(category: Observables.ComplaintType) {


        this.MyCategory = category
        Log.d("here", "i am here 1")
        Log.d("here", MyCategory.toString())


    }


    fun getAllData(){

        val latitude = 17.4
        val longitude = 78.4

//        LocationUtils().getInstance(appContext)
//        LocationUtils().getLocation().observe(this, Observer {loc: Location? ->
//            location = loc!!
//            // Yay! location recived. Do location related work here
//            Log.i(TAG,"Location: ${location.latitude}  ${location.longitude}")
//
//        })

        var typename = MyCategory!!.typeName.toString()


        val call = myAPI.checkExistingComplain(typename,longitude.toString(), latitude.toString() )
        Log.d("T", typename)
        Log.d("Lo", longitude.toString())
        Log.d("La", latitude.toString())




        call.enqueue(object : retrofit2.Callback<Observables.checkExistingResult> {
            override fun onFailure(call: Call<Observables.checkExistingResult>?, t: Throwable?) {

                Log.d("NO", t!!.message)


            }

            override fun onResponse(call: Call<Observables.checkExistingResult>?, response: Response<Observables.checkExistingResult>?) {

                if(response?.body()?.Complain ==null) {

                    setExistingData(response!!.body()!!.Complain)
                    descriptionFragment()
//                    notifyDataSetChanged()

                }

                else if(response!!.code() == 200){



                    Log.d("YES", "200")
                    Log.d("response", response.body().toString())


                    objectComplaint = response.body()!!.Complain

                    Log.d("got the complaint",objectComplaint.toString())
                    setExistingData(objectComplaint)



                    existPopup()
                }

                else if(response!!.code() == 201){

                    Log.d("response", response.body().toString())

//                    alreadyMadeComplaintPopup()
                }

                else{
                    descriptionFragment()
                }

                val item = objectComplaint

                listener?.onLocationFragmentInteraction(item)

            }
        })
    }


    interface OnLocationFragmentInteractionListener {
        // TODO: Update argument type and name
        fun onLocationFragmentInteraction(item: Observables.Complaint?)
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        if (context is OnLocationFragmentInteractionListener) {
            listener = context as OnLocationFragmentInteractionListener
        } else {
            throw RuntimeException("$context must implement OnLocationFragmentInteractionListener")
        }
    }

    fun setExistingData(test: Observables.Complaint) {
        objectComplaint = test
    }

    //opening up the checkExisting popup

    private fun existPopup(){
        val fm = activity!!.supportFragmentManager
        val dialog = PopupDialog() // creating new object
        dialog.show(fm, "dialog")
    }



    private fun descriptionFragment() {
        val dFragment= Category_Description()
        val lFragment = LocationFragment()
        val manager = (context as AppCompatActivity).supportFragmentManager
        val transaction =  manager.beginTransaction()
        transaction.replace(
            R.id.location_screen,
            dFragment
        ) // give your fragment container id in first parameter
        transaction.show(dFragment)
        transaction.hide(lFragment)
        transaction.isAddToBackStackAllowed
        transaction.addToBackStack(lFragment.fragmentManager.toString())  // if written, this transaction will be added to backstack
        transaction.commit()
    }



}


What can I try next?



Solution 1:[1]

Here look at this example: GpsUtils

Its pretty self explanatory. Just call GpsUtils.getInstance().findDeviceLocation(activity) from your fragment and after that accessing the static latitude and longitude variables in the GpsUtils class should give you the current locations. Note: Theres scope for improvement regarding the design of this class but it does the job pretty fine.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 because_im_batman