Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package io.intheloup.geolocation

import android.app.IntentService
import android.content.Intent
import android.util.Log
import com.google.android.gms.location.Geofence
import com.google.android.gms.location.GeofencingEvent

class GeofenceTransitionsIntentService : IntentService("GeofenceTransitionsIntentService") {

override fun onHandleIntent(intent: Intent?) {

val geofencingEvent = GeofencingEvent.fromIntent(intent)
if (geofencingEvent.hasError()) {
// val errorMessage = GeofenceErrorMessages.getErrorString(this,
// geofencingEvent.errorCode)
// Log.e(TAG, errorMessage)
return
}

// Get the transition type.
val geofenceTransition = geofencingEvent.geofenceTransition

// Test that the reported transition was of interest.
if (
geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT
) {

// Get the geofences that were triggered. A single event can trigger
// multiple geofences.
val triggeringGeofences = geofencingEvent.triggeringGeofences

// Get the transition details as a String.
// val geofenceTransitionDetails = getGeofenceTransitionDetails(
// this,
// geofenceTransition,
// triggeringGeofences
// )

// Send notification and log the transition details.
// sendNotification(geofenceTransitionDetails)
Log.i("BLA", geofenceTransition.toString())
} else {
// Log the error.
// Log.e(TAG, getString(R.string.geofence_transition_invalid_type,
// geofenceTransition))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import io.intheloup.geolocation.location.LocationClient

class GeolocationPlugin(val registrar: Registrar) {

private val locationClient = LocationClient(registrar.activity())
private val locationClient = LocationClient(registrar.activity(), registrar.context())
private val locationChannel = LocationChannel(locationClient)

init {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@ import io.intheloup.geolocation.location.LocationClient
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.launch

class LocationChannel(private val locationClient: LocationClient) : MethodChannel.MethodCallHandler, EventChannel.StreamHandler {
class LocationChannel(private val locationClient: LocationClient) : MethodChannel.MethodCallHandler {

fun register(plugin: GeolocationPlugin) {
val locationUpdatesHandler = LocationUpdatesHandler(locationClient)
val geofenceUpdatesHandler = GeofenceUpdatesHandler(locationClient)

val methodChannel = MethodChannel(plugin.registrar.messenger(), "geolocation/location")
methodChannel.setMethodCallHandler(this)

val eventChannel = EventChannel(plugin.registrar.messenger(), "geolocation/locationUpdates")
eventChannel.setStreamHandler(this)
val locationEventChannel = EventChannel(plugin.registrar.messenger(), "geolocation/locationUpdates")
locationEventChannel.setStreamHandler(locationUpdatesHandler)

val geofenceEventChannel = EventChannel(plugin.registrar.messenger(), "geolocation/geofenceUpdates")
geofenceEventChannel.setStreamHandler(geofenceUpdatesHandler)
}

private fun isLocationOperational(permission: Permission, result: MethodChannel.Result) {
Expand Down Expand Up @@ -48,7 +54,20 @@ class LocationChannel(private val locationClient: LocationClient) : MethodChanne
locationClient.removeLocationUpdatesRequest(id)
}

// geofencing
private fun addGeofenceRegion() {
locationClient.addGeofenceRegion()
}

private fun removeGeofenceRegion() {

}

private fun geofenceRegions(result: MethodChannel.Result) {
launch(UI) {
result.success("[]")
}
}
// MethodChannel.MethodCallHandler

override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
Expand All @@ -58,20 +77,40 @@ class LocationChannel(private val locationClient: LocationClient) : MethodChanne
"lastKnownLocation" -> lastKnownLocation(Codec.decodePermission(call.arguments), result)
"addLocationUpdatesRequest" -> addLocationUpdatesRequest(Codec.decodeLocationUpdatesRequest(call.arguments))
"removeLocationUpdatesRequest" -> removeLocationUpdatesRequest(Codec.decodeInt(call.arguments))
// "addGeofenceRegion" -> addGeofenceRegion(Codec.decodeGeofenceRegion(call.arguments))
"addGeofenceRegion" -> addGeofenceRegion()
"removeGeofenceRegion" -> removeGeofenceRegion()
"geofenceRegions" -> geofenceRegions(result)
else -> result.notImplemented()
}
}

class LocationUpdatesHandler(private val locationClient: LocationClient) : EventChannel.StreamHandler {

// EventChannel.StreamHandler
// EventChannel.StreamHandler
override fun onListen(arguments: Any?, events: EventChannel.EventSink) {
locationClient.registerLocationUpdatesCallback { result ->
events.success(Codec.encodeResult(result))
}
}

override fun onListen(arguments: Any?, events: EventChannel.EventSink) {
locationClient.registerLocationUpdatesCallback { result ->
events.success(Codec.encodeResult(result))
override fun onCancel(arguments: Any?) {
locationClient.deregisterLocationUpdatesCallback()
}
}

override fun onCancel(arguments: Any?) {
locationClient.deregisterLocationUpdatesCallback()
class GeofenceUpdatesHandler(private val locationClient: LocationClient) : EventChannel.StreamHandler {
// EventChannel.StreamHandler
override fun onListen(arguments: Any?, events: EventChannel.EventSink) {
// locationClient.registerGeofenceUpdatesCallback { result ->
// events.success(Codec.encodeResult(result))
// }
}

override fun onCancel(arguments: Any?) {
// locationClient.deregisterGeofenceUpdatesCallback()
}
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright (c) 2018 Loup Inc.
// Licensed under Apache License v2.0

package io.intheloup.geolocation.data

import com.google.android.gms.location.Geofence

class GeofenceData(val id: String,
// val region: Region,
val notifyOnEntry: Boolean,
val notifyOnExit: Boolean
) {
companion object {
fun from(geofence: Geofence) = GeofenceData(
id = geofence.requestId,

notifyOnEntry = false,
notifyOnExit = false
)
}
}


//class Region(
// val center: Location,
// val radius: Double) {
// companion object {
// fun from(location: Location) = LocationData(
// latitude = location.latitude,
// longitude = location.longitude,
// altitude = location.altitude
// )
// }
// init(from region: CLCircularRegion)
// {
// self.center = Location(from: region. center)
// self.radius = region.radius
// }
//}

//class GeofenceRegion(
// val region: Region,
// val id: String,
// val notifyOnEntry: Bool,
// val notifyOnExit: Bool){
// {
// companion object {
// fun from(geofence: Geofence) = Geofence(
// latitude = location.latitude,
// longitude = location.longitude,
// altitude = location.altitude
// self.region = Region(from: region)
// self.id = region.identifier
// self.notifyOnEntry = region.notifyOnEntry
// self.notifyOnExit = region.notifyOnExit
// )
// }
//
// var clRegion: CLCircularRegion {
// val result = CLCircularRegion(center: self. region . center . coordinate2D, radius: self.region.radius, identifier: self.id)
// result.notifyOnExit = self.notifyOnExit
// result.notifyOnEntry = self.notifyOnEntry
// return result
// }
//}
//
//enum GeofenceEventType: String, Codable {
// case entered, exited
//}
//
//data class GeofenceEvent (
// val type: GeofenceEventType
// val geofenceRegion: GeofenceRegion
//){
// init(region: CLCircularRegion, type: GeofenceEventType) {
// self.type = type
// self.geofenceRegion = GeofenceRegion(from: region)
// }
//}
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,32 @@ package io.intheloup.geolocation.location

import android.annotation.SuppressLint
import android.app.Activity
import android.app.IntentService
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.location.Location
import android.support.v4.app.ActivityCompat
import android.util.Log
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import com.google.android.gms.location.*
import io.flutter.plugin.common.PluginRegistry
import io.intheloup.geolocation.GeolocationPlugin
import io.intheloup.geolocation.data.LocationData
import io.intheloup.geolocation.data.LocationUpdatesRequest
import io.intheloup.geolocation.data.Permission
import io.intheloup.geolocation.data.Result
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.launch
import kotlin.coroutines.experimental.suspendCoroutine
import com.google.android.gms.location.Geofence
import io.intheloup.geolocation.GeofenceTransitionsIntentService
import io.intheloup.geolocation.data.*


@SuppressLint("MissingPermission")
class LocationClient(private val activity: Activity) {
class LocationClient(
private val activity: Activity,
private val context: Context
) {

val permissionResultListener: PluginRegistry.RequestPermissionsResultListener = PluginRegistry.RequestPermissionsResultListener { id, _, grantResults ->
if (id == GeolocationPlugin.Intents.LocationPermissionRequestId) {
Expand Down Expand Up @@ -78,6 +86,54 @@ class LocationClient(private val activity: Activity) {
}
}


private suspend fun geofenceRegions(): Geofence? = suspendCoroutine { cont ->
cont.resume(Geofence.Builder()
// Set the request ID of the geofence. This is a string to identify this
// geofence.
.setRequestId("just an example")

// Set the circular region of this geofence.
.setCircularRegion(
10.0,
10.0,
10.0f
)

// Set the expiration duration of the geofence. This geofence gets automatically
// removed after this period of time.
.setExpirationDuration(1000*60*60*99)

// Set the transition types of interest. Alerts are only generated for these
// transition. We track entry and exit transitions in this sample.
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_EXIT)

// Create the geofence.
.build())
// providerClient.lastLocation
// .addOnSuccessListener { location: Location? -> cont.resume(location) }
// .addOnFailureListener { cont.resumeWithException(it) }
}

suspend fun geofenceRegions(permission: Permission): Result {
val validity = validateServiceStatus(permission)
if (!validity.isValid) {
return validity.failure!!
}

val geofence = try {
geofenceRegions()
} catch (e: Exception) {
return Result.failure(Result.Error.Type.Runtime, message = e.message)
}

return if (geofence != null) {
Result.success(arrayOf(GeofenceData.from(geofence)))
} else {
Result.failure(Result.Error.Type.LocationNotFound)
}
}

suspend fun lastKnownLocation(permission: Permission): Result {
val validity = validateServiceStatus(permission)
if (!validity.isValid) {
Expand All @@ -99,7 +155,6 @@ class LocationClient(private val activity: Activity) {


// Updates API

suspend fun addLocationUpdatesRequest(request: LocationUpdatesRequest) {
val validity = validateServiceStatus(request.permission)
if (!validity.isValid) {
Expand All @@ -126,6 +181,63 @@ class LocationClient(private val activity: Activity) {
locationUpdatesCallback = null
}

private val geofencePendingIntent: PendingIntent by lazy {
val intent = Intent(context, GeofenceTransitionsIntentService::class.java)
// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling
// addGeofences() and removeGeofences().
PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}



/**
* geofencing
*/
fun addGeofenceRegion() {
val region = Geofence.Builder()
// Set the request ID of the geofence. This is a string to identify this
// geofence.
.setRequestId("MyHome")

// Set the circular region of this geofence.
.setCircularRegion(
10.0,
10.0,
23.0f
)

// Set the expiration duration of the geofence. This geofence gets automatically
// removed after this period of time.
.setExpirationDuration(-1)

// Set the transition types of interest. Alerts are only generated for these
// transition. We track entry and exit transitions in this sample.
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_EXIT)

// Create the geofence.
.build()

val regions: List<Geofence> = mutableListOf(region)

val request = GeofencingRequest.Builder().apply {
setInitialTrigger(Geofence.GEOFENCE_TRANSITION_ENTER)
addGeofences(regions)
}.build()

// val geo: GeofenceTransitionsIntentService = GeofenceTransitionsIntentService()

LocationServices.getGeofencingClient(activity)?.addGeofences(request, geofencePendingIntent)?.run {
addOnSuccessListener {
// Geofences added
Log.i("GEOFENCE", "SUCCESESS")
}
addOnFailureListener {
Log.i("GEOFENCE", "FAIL")
// Failed to add geofences
}
}

}

// Lifecycle API

Expand Down
Loading