Reputation: 1585
Geofence not working in Kotlin, though same code is working in Java. I am newbie to Kotlin hence not able to understand the issue.
Actually I am calling MainGeofence.kt
service class from an activity MainActivity
following is the code
MainGeofence.kt
public class MainGeofence : IntentService("MyService"), LocationListener {
internal var mGeofencePendingIntent: PendingIntent? = null
private var mGeofenceList: ArrayList<Geofence>? = null
private var mGoogleApiClient: GoogleApiClient? = null
val TAG = "Activity"
internal lateinit var mLocationRequest: LocationRequest
internal var currentLatitude = <<lat value
internal var currentLongitude = <<long value
override fun onCreate() {
super.onCreate()
}
override fun onHandleIntent(p0: Intent?) {
mGeofenceList = ArrayList<Geofence>()
if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this)
== ConnectionResult.SUCCESS) {
initGoogleAPIClient()
createGeofences(currentLatitude, currentLongitude)
} else {
Log.e(TAG, "Your Device doesn't support Google Play Services.")
}
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(1 * 1000)
.setFastestInterval(1 * 1000)
}
public fun initGoogleAPIClient(): Unit {
mGoogleApiClient = GoogleApiClient.Builder(this)
.addApi(API)
.addConnectionCallbacks(connectionAddListener)
.addOnConnectionFailedListener(connectionFailedListener)
.build()
mGoogleApiClient?.connect()
}
private val connectionAddListener = object : GoogleApiClient.ConnectionCallbacks {
@SuppressLint("MissingPermission")
override fun onConnected(bundle: Bundle?) {
Log.i(TAG, "onConnected")
@SuppressLint("MissingPermission")
val location = FusedLocationApi.getLastLocation(mGoogleApiClient)
if (location == null) {
FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this@MainGeofence)
} else {
//If everything went fine lets get latitude and longitude
currentLatitude = location.latitude
currentLongitude = location.longitude
Log.i(TAG, currentLatitude.toString() + " WORKS " + currentLongitude)
//createGeofences(currentLatitude, currentLongitude);
//registerGeofences(mGeofenceList);
}
try {
GeofencingApi.addGeofences(
mGoogleApiClient,
getGeofencingRequest(),
getGeofencePendingIntent()
).setResultCallback(ResultCallback<Status> { status ->
if (status.isSuccess) {
Log.i(TAG, "Saving Geofence")
} else {
Log.e(TAG, "Registering geofence failed: " + status.statusMessage +
" : " + status.statusCode)
}
})
} catch (securityException: SecurityException) {
// Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
Log.e(TAG, "Error")
}
}
override fun onConnectionSuspended(i: Int) {
Log.e(TAG, "onConnectionSuspended")
}
}
/**
* Create a Geofence list
*/
fun createGeofences(latitude: Double, longitude: Double) {
val id = UUID.randomUUID().toString()
println("latnlon " + latitude + " " + longitude)
val fence = Geofence.Builder()
.setRequestId(id)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_EXIT)
.setCircularRegion(latitude, longitude, 50f)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.build()
mGeofenceList?.add(fence)
}
private fun getGeofencingRequest(): GeofencingRequest {
val builder = GeofencingRequest.Builder()
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
builder.addGeofences(mGeofenceList)
return builder.build()
}
private fun getGeofencePendingIntent(): PendingIntent {
// Reuse the PendingIntent if we already have it.
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent!!
}
val intent = Intent(this, GeofenceIntentService::class.java)
// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
// calling addGeofences() and removeGeofences().
return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}
private val connectionFailedListener = GoogleApiClient.OnConnectionFailedListener { Log.e(TAG, "onConnectionFailed") }
override fun onLocationChanged(location: Location?) {
if (location != null) {
currentLatitude = location.latitude
currentLongitude = location.longitude
Log.i(TAG, "onLocationChanged")
}
}
}
MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
dummyBtn = findViewById(R.id.dummyBtn)
dummyTv = findViewById(R.id.dummyTv)
dummyBtn.setOnClickListener(View.OnClickListener {
// startLocationUpdates()
startService(Intent(this, MainGeofence::class.java))
...
})
....
}
and GeofenceIntentService.kt
public class GeofenceIntentService : IntentService("GeofenceIntentService") {
private final var TAG: String = "Geofence"
override fun onHandleIntent(intent: Intent?) {
Log.i(TAG, "onHandleIntent")
val geofencingEvent = fromIntent(intent)
if (geofencingEvent.hasError()) {
Log.e(TAG, "Goefencing Error " + geofencingEvent.errorCode)
return
}
//Create AudioManager object to change phone profile
var am: AudioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
// Get the transition type.
val geofenceTransition = geofencingEvent.geofenceTransition
Log.i(TAG, "geofenceTransition = " + geofenceTransition + " Enter : " +
Geofence.GEOFENCE_TRANSITION_ENTER + "Exit : " + Geofence.GEOFENCE_TRANSITION_EXIT)
when (geofenceTransition) {
Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_DWELL -> {
showNotification("Entered", "Entered the Location")
am.setRingerMode(AudioManager.RINGER_MODE_VIBRATE) //put ringer to vibration
}
Geofence.GEOFENCE_TRANSITION_EXIT -> {
showNotification("Exited", "Exited the Location")
am.setRingerMode(AudioManager.RINGER_MODE_NORMAL) //put ringer to normal
}
else -> {
println("oh cow's eye! something bad happened!")
Log.e(TAG, "Error ")
}
}
}
fun showNotification(text: String, bigText: String) {
// 1. Create a NotificationManager
val notificationManager = this.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// 2. Create a PendingIntent for AllGeofencesActivity
val intent = Intent(this, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingNotificationIntent = PendingIntent.getActivity(this, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT)
// 3. Create and send a notification
val notification = NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Title")
.setContentText(text)
.setContentIntent(pendingNotificationIntent)
.setStyle(NotificationCompat.BigTextStyle().bigText(bigText))
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.build()
notificationManager.notify(0, notification)
}
}
Geofence points seldom fires and that too only Exit
one. But code works perfect in Java. Is this problem of language or implementation?
Help is greatly appreciated!
Upvotes: 1
Views: 950
Reputation: 73480
I think your problem is the when clause in onHandleIntent
You essentially have
when (x) {
A or B -> { ... }
C -> { ... }
else -> { ... }
}
I think Geofence.GEOFENCE_TRANSITION_ENTER
etc are Int
types so you're ending up calling "bitwise or" on them using infix fun or(other: Int): Int (source)
.
I think what you really want is:
when (x) {
A, B -> { ... }
C -> { ... }
else -> { ... }
}
Upvotes: 1