Falguni Rana
Falguni Rana

Reputation: 11

Android Kotlin: Getting Location = null when device in Doze mode in OEM devices like Samsung, Xiaomi and so on

I used FusedLocationProviderClient with JobScheduler to get current location all time and it working well when app in background.
But getCurrentLocation() method return Location = null when I tested with Doze and App Standby command.

I faced this issue in OEM devices like samsung, xiaomi, huawei and so on.

Can anyone help me to solve this?

Here is the code,

LocationJob.kt

class LocationJob : JobService() {

    private var mLocationRequest: LocationRequest? = null
    private var mLocationRequestBuilder: LocationRequest.Builder? = null
    private var mFusedLocationClient: FusedLocationProviderClient? = null
    private var mLocationCallback: LocationCallback? = null

    private val workHandler: Handler = Handler(Looper.getMainLooper())
    var workRunnable: Runnable? = null
    var handlerThread: HandlerThread? = null

    override fun onCreate() {
        super.onCreate()
        // TODO: Start a background thread to receive location result.
        handlerThread = HandlerThread("RequestLocation");
        handlerThread!!.start();

        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
        mLocationCallback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult) {
               //Note: this is not called in case of Doze mode in OEM device.  
                if (locationResult.lastLocation == null) {
                    Log.e(TAG, "Location missing in callback.")
                } else {
                    Log.e(TAG, "Location callback. ${locationResult.lastLocation}")
                }
                super.onLocationResult(locationResult)

            }

            override fun onLocationAvailability(locationAvailability: LocationAvailability) {
                super.onLocationAvailability(locationAvailability)
            }
        }
        if (mLocationRequest == null) {
           if (mLocationRequestBuilder == null){
               mLocationRequestBuilder = LocationRequest.Builder(
                  Priority.PRIORITY_HIGH_ACCURACY,
                  sessionManager?.moveOnTripInterval.makeLong()
               )
            }
            mLocationRequestBuilder?.setIntervalMillis()
            mLocationRequestBuilder?.setMinUpdateIntervalMillis()
            mLocationRequest = mLocationRequestBuilder!!.build()
        }
    }

override fun onStartJob(params: JobParameters?): Boolean {
        Log.e(TAG, "onStartJob")
        if (mFusedLocationClient != null) return false

        workRunnable = Runnable {
            try {
                mFusedLocationClient!!.requestLocationUpdates(
                    mLocationRequest!!, mLocationCallback!!, handlerThread!!.looper
                )

                Handler(Looper.getMainLooper()).postDelayed({
                    mFusedLocationClient!!.getCurrentLocation(PRIORITY_HIGH_ACCURACY, null)
                        .addOnSuccessListener {
                            Log.e("Loc: $it")
                            if (it != null) {
                                val loc = it
                                println("$TAG: ${loc.latitude},${loc.longitude}")
                            } else {
                                Log.e("Loc: is null")
                            }
                        }.addOnFailureListener {
                            println("cancel")
                        }

                }, 10 * 1000)
            } catch (unlikely: SecurityException) {
                println("$TAG Lost location permission. Could not request updates. ")
            }
            jobFinished(params, true)
        }
        workHandler.post(workRunnable!!)
        return true
    }

MainActivity.kt

class MainActivity: AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
      //trigger LocationJob service
        triggerJobService(true)
    }

    fun triggerJobService(start: Boolean) {
        try {
            val jobScheduler =
                getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
            if (start) {
                val jobInfo =
                    JobInfo.Builder(Constant.JOB_ID, ComponentName(this, LocationJob::class.java))
                        .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                        .setRequiresDeviceIdle(false).setRequiresCharging(false).setPersisted(true)
//                        .setOverrideDeadline(3 * 60 * 1000)
                val job = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    jobInfo.setMinimumLatency(Constant.REFRESH_INTERVAL)
                        .build()
                } else {
                    jobInfo.setPeriodic(Constant.REFRESH_INTERVAL)
                        .setMinimumLatency(1)
                        .build()
                }
                //.setOverrideDeadline(3 * 60 * 1000)
                jobScheduler.schedule(job)
            } else {
                jobScheduler.cancel(Constant.JOB_ID)
            }
        } catch (e: Exception) {
            e.printStackTrace()
            return
        }
    }

}

Upvotes: 1

Views: 397

Answers (0)

Related Questions