Skip to content

Instantly share code, notes, and snippets.

@nicemak
Last active January 10, 2020 04:50
Show Gist options
  • Save nicemak/201e84af9c36abf30221e67e9915ba70 to your computer and use it in GitHub Desktop.
Save nicemak/201e84af9c36abf30221e67e9915ba70 to your computer and use it in GitHub Desktop.
Location Monitoring Service Files
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
class BroadCastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
context.startForegroundService(Intent(context,LocationMonitoringService::class.java))
else
context.startService(Intent(context, LocationMonitoringService::class.java))
}
}
import android.Manifest
import android.app.*
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.os.IBinder
import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationCompat
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.api.GoogleApiClient
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationServices
class LocationMonitoringService : Service(), GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private var mLocationClient: GoogleApiClient? = null
private var mLocationRequest = LocationRequest()
var context: Context? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int
{
super.onStartCommand(intent, flags, startId)
println("onStartCommand")
mLocationClient = GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build()
mLocationRequest.interval = LOCATION_INTERVAL
mLocationRequest.fastestInterval = FASTEST_LOCATION_INTERVAL
//mLocationRequest.setSmallestDisplacement(DISTANCE_IN_METERS);
//PRIORITY_BALANCED_POWER_ACCURACY, PRIORITY_LOW_POWER, PRIORITY_NO_POWER are the other priority modes
mLocationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY //by default
mLocationClient!!.connect()
//Make it stick to the notification panel so it is less prone to get cancelled by the Operating System.
return START_STICKY
}
override fun onCreate()
{
super.onCreate()
context = this
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O)
startMyOwnForeground()
else
startForeground(1, Notification())
println("onCreate")
}
private fun startMyOwnForeground() {
println("startMyOwnForeground called ")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
val channelId = getString(R.string.app_name)
val channelName = "Background Service"
val chan = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH)
chan.lightColor = Color.BLUE
chan.lockscreenVisibility = Notification.VISIBILITY_PUBLIC // VISIBILITY_PRIVATE
val manager =
(getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager)
manager.createNotificationChannel(chan)
val notificationBuilder: NotificationCompat.Builder =
NotificationCompat.Builder(this, channelId)
val notification: Notification = notificationBuilder.setOngoing(true)
.setContentTitle("App is running in background")
.setSmallIcon(R.drawable.ikonnect_logo) // the status icon
.setPriority(NotificationManager.IMPORTANCE_HIGH)
.setCategory(Notification.CATEGORY_PROGRESS) //CATEGORY_SERVICE
.setOngoing(true)
.build()
startForeground(2, notification)
}
}
override fun onBind(intent: Intent?): IBinder? = null
override fun onConnected(dataBundle: Bundle?) {
val intent = Intent()
intent.action = LOCATION_PARAM
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
{
println("Error On onConnected() Permission not granted")
//Permission not granted by user so cancel the further execution.
intent.putExtra(LATITUDE, getStringValue(LATITUDE))
intent.putExtra(LONGITUDE, getStringValue(LONGITUDE))
LocalBroadcastManager.getInstance(context!!).sendBroadcast(intent)
return
}
if (mLocationClient!!.isConnected)
{
LocationServices.FusedLocationApi.requestLocationUpdates(mLocationClient, mLocationRequest)
{ location ->
if (location != null)
{
println("${location.latitude}, ${location.longitude}")
//System.out.println("" + location.getLatitude() + ", " + location.getLongitude() + ", Accuracy: " + location.getAccuracy());
//Save locations
saveString(LATITUDE, "${location.latitude}")
saveString(LONGITUDE, "${location.longitude}")
intent.putExtra(LATITUDE, location.latitude)
intent.putExtra(LONGITUDE, location.longitude)
LocalBroadcastManager.getInstance(context!!).sendBroadcast(intent)
}
}
}
else
{
println("Not Connected to Google API")
mLocationClient!!.connect()
}
println("Connected to Google API")
}
override fun onConnectionSuspended(p0: Int) {
println("Connection Suspended")
}
override fun onConnectionFailed(p0: ConnectionResult) {
println("Connection Failed")
}
override fun onDestroy() {
super.onDestroy()
if (mLocationClient != null) mLocationClient!!.disconnect()
val broadcastIntent = Intent()
broadcastIntent.action = "RestartService"
broadcastIntent.setClass(this, BroadCastReceiver::class.java)
/*if (keep_me_on) {
println("service ondestroy try")
this.sendBroadcast(broadcastIntent)
}*/
println("Service Destroyed")
}
/*override fun onTaskRemoved(rootIntent: Intent?) {
*//*try {
println("onTskRemoved try")
if (networkConsume.getBoolean(AppConstants.SHIFT_ACTIVE, context)) {
if (!isMyServiceRunning(this.javaClass)) {
val restartServiceIntent =
Intent(applicationContext, this.javaClass)
restartServiceIntent.setPackage(packageName)
val restartServicePendingIntent = PendingIntent.getService(
applicationContext,
1,
restartServiceIntent,
PendingIntent.FLAG_ONE_SHOT
)
val alarmService =
applicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmService[AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 1000] =
restartServicePendingIntent
}
}
} catch (e: java.lang.Exception) {
println("Service onTaskRemoved Exception : $e")
}*//*
super.onTaskRemoved(rootIntent)
}*/
private fun isMyServiceRunning(serviceClass: Class<*>): Boolean {
try {
val manager =
getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
for (service in manager.getRunningServices(Int.MAX_VALUE))
{
if (serviceClass.name == service.service.className) {
println("Service is running: " + service.service.className)
return true
}
}
} catch (e: Exception) {
println("isMyServiceRunning Exception: $e")
}
println("Service is not running")
return false
}
companion object {
private const val LOCATION_INTERVAL: Long = 30000
private const val FASTEST_LOCATION_INTERVAL: Long = 15000
private const val DISTANCE_IN_METERS = 10f
}
}
In Manifest Under Application Tag:
<service
android:name=".backgroundservice.LocationMonitoringService"
android:enabled="true"
android:exported="true"
android:icon="@drawable/ikonnect_logo"
android:stopWithTask="false" />
<receiver
android:name=".backgroundservice.BroadCastReceiver"
android:enabled="true"
android:exported="true"
android:label="RestartServiceWhenStopped">
<intent-filter>
<action android:name="RestartService" />
</intent-filter>
</receiver>
===========================================================================================================================
In MainActivity:
// Service
var mServiceIntent: Intent? = null
var mLocationService: LocationMonitoringService? = null
===========================================================================================================================
onCreate::
mLocationService = LocationMonitoringService()
mServiceIntent = Intent(context, LocationMonitoringService::class.java)
LocalBroadcastManager.getInstance(context).registerReceiver(broadcastReceiver, IntentFilter(LOCATION_PARAM))
startLocationService()
===========================================================================================================================
private fun isMyServiceRunning(serviceClass: Class<*>): Boolean {
try {
val manager =
getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
for (service in manager.getRunningServices(Int.MAX_VALUE)) {
if (serviceClass.name == service.service.className) {
println("Service is running: " + service.service.className)
return true
}
}
} catch (e: Exception) {
println("isMyServiceRunning Exception: $e")
}
println("Service is not running")
return false
}
===========================================================================================================================
private fun startLocationService() {
try
{
println("isServiceRunning: ${getBooleanValue(SP_SERVICE)}")
if (!isMyServiceRunning(mLocationService!!::class.java))
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
println("Service Start for oreo or above")
ContextCompat.startForegroundService(context, mServiceIntent!!)
} else {
println("Service Start normally")
startService(mServiceIntent)
}
}
} catch (e: Exception) {
println("Exception while starting service $e")
}
}
===========================================================================================================================
onDestroy::
try
{
// Unregister Broadcast Receiver
LocalBroadcastManager.getInstance(context).unregisterReceiver(broadcastReceiver)
// Stop Service
stopService(mServiceIntent)
}
catch (e: Exception)
{
println("onDestroy Exception: $e")
}
===========================================================================================================================
private var broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver()
{
override fun onReceive(context: Context, intent: Intent)
{
val status = getStringValue(SP_ACTIVITY_STATUS)
if (intent.hasExtra(LATITUDE) && intent.hasExtra(LONGITUDE) && status == "RESUME")
{
val currentLocation = Location("")
currentLocation.latitude = intent.getDoubleExtra(LATITUDE, 0.0)
currentLocation.longitude = intent.getDoubleExtra(LONGITUDE, 0.0)
if (getAddressFromLatLong(currentLocation).isNotEmpty())
tv_location.text = getAddressFromLatLong(currentLocation)[0].getAddressLine(0).toString()
else
tv_location.text = "Unknown Location"
}
}
}
===========================================================================================================================
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment