Reputation: 219
I'm building a Flutter app that requires Geofencing service, so I opt to use the Native Geofence library where I'll check for all necessary permission on Flutter then pass the regions thru the Method Channel from Flutter to Android.
I followed the tutorial documented by Android and develop a simple prototype. I manage to register all the geofences but whenever I ENTER or EXIT a region, I do not get notified. Below are the codes of my prototype. Can anyone help me?
In my AndroidManifest.xml
I have declared
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<receiver android:name=".GeofenceBroadcastReceiver" android:enabled="true" android:exported="true"/>
MainActivity.kt
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
GeneratedPluginRegistrant.registerWith(flutterEngine)
Geofence().initialize(this.applicationContext, this.activity, flutterEngine)
}
}
Geofence.kt
class Geofence: MethodChannel.MethodCallHandler {
private var channel: MethodChannel? = null
private var context: Context? = null
private var geofencingClient: GeofencingClient? = null
private var geofenceList = mutableListOf<Geofence>()
private val channelName = "com.example.geofence/geofence"
fun initialize(context: Context, activity: Activity, flutterEngine: FlutterEngine) {
this.context = context
geofencingClient = LocationServices.getGeofencingClient(this.context!!)
channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channelName)
channel!!.setMethodCallHandler(this)
}
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when(call.method) {
"startService" -> {
val args = call.arguments<ArrayList<*>>()
startService(args!!)
result.success(null)
}
else -> result.notImplemented()
}
}
@SuppressLint("MissingPermission")
private fun startService(regions: ArrayList<*>) {
for (r in regions) {
val o = r as HashMap<*, *>
geofenceList.add(
Geofence.Builder()
.setRequestId(o["id"] as String)
.setCircularRegion(o["latitude"] as Double, o["longitude"] as Double, (o["radius"] as Int).toFloat())
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_EXIT)
.build()
)
}
Log.d("TAG", "startService: Geofence count: ${geofenceList.count()}")
geofencingClient!!.addGeofences(getGeofencingRequest(), geofencePendingIntent).run {
addOnSuccessListener {
Log.d("TAG", "startService: Geofence Added Successfully")
}
addOnFailureListener{
Log.e("TAG", "startService: Failed to add Geofence ${it.message}")
}
}
}
private fun getGeofencingRequest(): GeofencingRequest {
Log.d("TAG", "getGeofencingRequest")
return GeofencingRequest.Builder().apply {
setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER or GeofencingRequest.INITIAL_TRIGGER_EXIT)
addGeofences(geofenceList)
}.build()
}
private val geofencePendingIntent: PendingIntent by lazy {
val intent = Intent(context, GeofenceBroadcastReceiver::class.java)
PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
}
}
GeofenceBroadcastReceiver.kt
class GeofenceBroadcastReceiver: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
Log.d("TAG", "onReceive")
val geofencingEvent = GeofencingEvent.fromIntent(intent!!)
if (geofencingEvent!!.hasError()) {
Log.e("TAG", "onReceive: ${GeofenceStatusCodes.getStatusCodeString(geofencingEvent.errorCode)}")
return
}
val geofenceTransition = geofencingEvent.geofenceTransition
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
Log.d("TAG", "onReceive: Geofence transition: $geofenceTransition")
} else {
Log.e("TAG", "onReceive: Error")
}
}
}
From the Flutter side I'll invoke startService
which will pass a List of regions to Android thru the MethodChannel
Upvotes: 0
Views: 80