Hi everyone, I'm an android application developer and have developed a location-based app that is supposed to run even in the background and even in phone locked state but Huawei battery services are killing my application service and I'm unable to find the location.
I have given all types of permission required for the location provided below is the code of my service class. please suggest.
Thanks!
class LocationUpdatesService : Service(), LogOutTimerUtil.LogOutListener {
private val mBinder: IBinder = LocalBinder()
private var mNotificationManager: NotificationManager? = null
private var mLocationRequest: LocationRequest? = null
private var mFusedLocationClient: FusedLocationProviderClient? = null
private var mLocationCallback: LocationCallback? = null
private var mLocation: Location? = null
private lateinit var database: FirebaseDatabase
private lateinit var dbRef: DatabaseReference
private var prefManager: PrefManager? = null
private var driverLocationFireBase: DriverLocationFirebase = DriverLocationFirebase()
private var bearing: Float = 0f
private var userLat: Double = 0.0
private var userLong: Double = 0.0
private var mServiceHandler: Handler? = null
private var handler: Handler? = null
private var runnable = object : Runnable {
override fun run() {
updateFireBaseDataBase()
handler?.removeCallbacks(this)
handler?.postDelayed(this, DISPATCH_TIME)
}
}
private val DISPATCH_TIME = TimeUnit.SECONDS.toMillis(6)
override fun onCreate() {
initServicePrams()
}
private fun initServicePrams() {
createLocationRequest()
getLastLocation()
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
mLocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
super.onLocationResult(locationResult)
if (locationResult == null) {
return
}
for (location in locationResult.locations) {
if (location != null) {
onNewLocation(location)
}
}
}
}
val handlerThread = HandlerThread(TAG)
handlerThread.start()
mServiceHandler = Handler(handlerThread.looper)
mNotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name: CharSequence = getString(R.string.app_name)
val channel = NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_LOW)
channel.setSound(null, null)
mNotificationManager!!.createNotificationChannel(channel)
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.i("ServiceStarted", "Service started")
LogOutTimerUtil.startLogoutTimer(this, this)
initServicePrams()
timerForFireBase()
database = FirebaseDatabase.getInstance()
dbRef = database.getReference(BuildConfig.FIREBASE_DATABASE)
prefManager = PrefManager(applicationContext)
return START_STICKY
}
private fun timerForFireBase() {
if (handler == null) {
val handlerThread = HandlerThread(TAG)
handlerThread.start()
handler = Handler(handlerThread.looper)
Log.i("ServicesLoG", "NewhandlerCalled")
}
handler?.post(runnable)
}
override fun onBind(intent: Intent): IBinder? {
Log.i(TAG, "in onBind()")
stopForeground(true)
return mBinder
}
override fun onRebind(intent: Intent) {
Log.i(TAG, "in onRebind()")
stopForeground(true)
super.onRebind(intent)
}
override fun onUnbind(intent: Intent): Boolean {
Log.i(TAG, "Last client unbound from service")
startForeground(NOTIFICATION_ID, notification)
return true // Ensures onRebind() is called when a client re-binds.
}
override fun onDestroy() {
mServiceHandler?.removeCallbacksAndMessages(null)
handler?.removeCallbacks(runnable)
LogOutTimerUtil.stopLogoutTimer()
}
fun requestLocationUpdates() {
LocationUpdateUtils.setRequestingLocationUpdates(this, true)
startService(Intent(applicationContext, LocationUpdatesService::class.java))
try {
mFusedLocationClient?.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper())
} catch (unlikely: SecurityException) {
LocationUpdateUtils.setRequestingLocationUpdates(this, false)
Log.e(TAG, "Lost location permission. Could not request updates. $unlikely")
}
}
fun removeLocationUpdates() {
Log.i(TAG, "Removing location updates")
try {
mFusedLocationClient?.removeLocationUpdates(mLocationCallback)
LocationUpdateUtils.setRequestingLocationUpdates(this, false)
stopSelf()
} catch (unlikely: SecurityException) {
LocationUpdateUtils.setRequestingLocationUpdates(this, true)
Log.e(TAG, "Lost location permission. Could not remove updates. $unlikely")
}
}
private val notification: Notification
get() {
val text: CharSequence = LocationUpdateUtils.getLocationText(mLocation)
val builder = NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.icon_notification)
.setContentTitle(getString(R.string.app_name))
.setContentText(getString(R.string.location_discp))
.setOngoing(true)
.setSound(null)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setSmallIcon(R.mipmap.ic_launcher)
.setTicker(text)
.setWhen(System.currentTimeMillis())
// Set the Channel ID for Android O.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId(CHANNEL_ID) // Channel ID
}
return builder.build()
}
private fun getLastLocation() {
try {
mFusedLocationClient?.lastLocation
?.addOnCompleteListener { task: Task<Location?> ->
if (task.isSuccessful && task.result != null) {
mLocation = task.result
} else {
Log.w(TAG, "Failed to get location.")
}
}
} catch (unlikely: SecurityException) {
Log.e(TAG, "Lost location permission.$unlikely")
}
}
private fun onNewLocation(location: Location) {
Log.i(TAG, "New location: $location")
mLocation = location
bearing = location.bearing
userLat = location.latitude
userLong = location.longitude
prefManager?.saveDouble(Const.TAG_DRIVER_LAT, location.latitude)
prefManager?.saveDouble(Const.TAG_DRIVER_LNG, location.longitude)
}
private fun updateFireBaseDataBase() {
driverLocationFireBase.userId = "" + prefManager?.getString(Const.TAG_USERID, "")
driverLocationFireBase.time = System.currentTimeMillis()
driverLocationFireBase.bearing = bearing
driverLocationFireBase.orderId = prefManager?.getInt(Const.TAG_ORDER_ID, 0)
driverLocationFireBase.fireBaseToken = PrefManager(this).getString(TAG_FCM_DEVICE_TOKEN, "")
if (userLat == 0.0 || userLong == 0.0) {
LocationServices.getFusedLocationProviderClient(this).lastLocation.addOnSuccessListener {
it?.apply {
prefManager?.saveDouble(Const.TAG_DRIVER_LAT, latitude)
prefManager?.saveDouble(Const.TAG_DRIVER_LNG, longitude)
driverLocationFireBase.lat = latitude
driverLocationFireBase.lng = longitude
}
}
} else {
driverLocationFireBase.lat = userLat
driverLocationFireBase.lng = userLong
}
dbRef.child(prefManager?.getString(Const.TAG_USERID, "")!!).setValue(driverLocationFireBase)
}
private fun createLocationRequest() {
if (mLocationRequest == null) {
mLocationRequest = LocationRequest()
mLocationRequest?.interval = UPDATE_INTERVAL_IN_MILLISECONDS
mLocationRequest?.fastestInterval = FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS
mLocationRequest?.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
mLocationRequest?.smallestDisplacement = 25f
}
}
inner class LocalBinder : Binder() {
val service: LocationUpdatesService
get() = this@LocationUpdatesService
}
companion object {
private val TAG = LocationUpdatesService::class.java.simpleName
private const val CHANNEL_ID = "locationChannel"
private val UPDATE_INTERVAL_IN_MILLISECONDS: Long = TimeUnit.SECONDS.toMillis(8)
private val FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2
private const val NOTIFICATION_ID = 12345678
}
}
