Skip to content

Commit

Permalink
Android embedding v2 only (DwayneCoussement#31)
Browse files Browse the repository at this point in the history
* Android embedding v2 only

* Cleanup
  • Loading branch information
DwayneCoussement authored Oct 15, 2020
1 parent 3b2182b commit 11c9b64
Show file tree
Hide file tree
Showing 21 changed files with 248 additions and 245 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
/.idea
/.packages
/example/ios/Flutter/.last_build_id
/flutter_geofence.iml
10 changes: 10 additions & 0 deletions .metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: f30b7f4db93ee747cd727df747941a28ead25ff5
channel: stable

project_type: plugin
3 changes: 1 addition & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
group 'com.intivoto.geofence'
group 'com.intivoto.flutter_geofence'
version '1.0-SNAPSHOT'

buildscript {
Expand Down Expand Up @@ -32,7 +32,6 @@ android {
}
defaultConfig {
minSdkVersion 16
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
lintOptions {
disable 'InvalidPackage'
Expand Down
1 change: 0 additions & 1 deletion android/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true
2 changes: 1 addition & 1 deletion android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
2 changes: 1 addition & 1 deletion android/settings.gradle
Original file line number Diff line number Diff line change
@@ -1 +1 @@
rootProject.name = 'geofence'
rootProject.name = 'flutter_geofence'
3 changes: 1 addition & 2 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.intivoto.geofence">

package="com.intivoto.flutter_geofence">
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
package com.intivoto.flutter_geofence

import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import androidx.annotation.NonNull
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat

import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry

/** FlutterGeofencePlugin */
class FlutterGeofencePlugin : FlutterPlugin, MethodCallHandler, ActivityAware, PluginRegistry.RequestPermissionsResultListener {
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private lateinit var channel: MethodChannel
private var geofenceManager: GeofenceManager? = null
private var currentActivity: Activity? = null


override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "geofence")
channel.setMethodCallHandler(this)
}

override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
if (call.method == "addRegion") {
val arguments = call.arguments as? HashMap<*, *>
if (arguments != null) {
val region = safeLet(arguments["id"] as? String,
arguments["radius"] as? Double,
arguments["lat"] as? Double,
arguments["lng"] as? Double,
arguments["event"] as? String)
{ id, radius, latitude, longitude, event ->
GeoRegion(
id,
radius.toFloat(),
latitude,
longitude,
events = when (event) {
"GeolocationEvent.entry" -> listOf(GeoEvent.entry)
"GeolocationEvent.exit" -> listOf(GeoEvent.exit)
else -> GeoEvent.values().toList()
})
}
if (region != null) {
geofenceManager?.startMonitoring(region)
result.success(null)
} else {
result.error("Invalid arguments", "Has invalid arguments", "Has invalid arguments")
}
} else {
result.error("Invalid arguments", "Has invalid arguments", "Has invalid arguments")
}
} else if (call.method == "removeRegion") {
val arguments = call.arguments as? HashMap<*, *>
if (arguments != null) {
val region = safeLet(arguments["id"] as? String,
arguments["radius"] as? Double,
arguments["lat"] as? Double,
arguments["lng"] as? Double,
arguments["event"] as? String)
{ id, radius, latitude, longitude, event ->
GeoRegion(
id,
radius.toFloat(),
latitude,
longitude,
events = when (event) {
"GeolocationEvent.entry" -> listOf(GeoEvent.entry)
"GeolocationEvent.exit" -> listOf(GeoEvent.exit)
else -> GeoEvent.values().toList()
})
}
if (region != null) {
geofenceManager?.stopMonitoring(region)
result.success(null)
} else {
result.error("Invalid arguments", "Has invalid arguments", "Has invalid arguments")
}
} else {
result.error("Invalid arguments", "Has invalid arguments", "Has invalid arguments")
}
} else if (call.method == "removeRegions") {
geofenceManager?.stopMonitoringAllRegions()
result.success(null)
} else if (call.method == "getUserLocation") {
geofenceManager?.getUserLocation()
result.success(null)
} else if (call.method == "requestPermissions") {
requestPermissions()
} else if (call.method == "startListeningForLocationChanges") {
geofenceManager?.startListeningForLocationChanges()
result.success(null)
} else if (call.method == "stopListeningForLocationChanges") {
geofenceManager?.stopListeningForLocationChanges()
result.success(null)
} else {
result.notImplemented()
}
}

private fun requestPermissions() {
safeLet(currentActivity, currentActivity?.applicationContext) { activity, context ->
checkPermissions(context, activity)
}
}

@SuppressLint("InlinedApi")
private fun checkPermissions(context: Context, activity: Activity) {
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_BACKGROUND_LOCATION)
!= PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(activity,
Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity,
arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION),
999)
} else {
// Permission has already been granted
startGeofencing(context)
}
}

private fun startGeofencing(context: Context) {
context.let {
geofenceManager = GeofenceManager(it, {
handleGeofenceEvent(it)
}, {
channel.invokeMethod("userLocationUpdated", hashMapOf("lat" to it.latitude, "lng" to it.longitude))
}, {
channel.invokeMethod("backgroundLocationUpdated", hashMapOf("lat" to it.latitude, "lng" to it.longitude))
})
}
}

private fun handleGeofenceEvent(region: GeoRegion) {
if (region.events.contains(GeoEvent.entry)) {
channel.invokeMethod("entry", region.serialized())
} else {
channel.invokeMethod("exit", region.serialized())
}
}

override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}

override fun onAttachedToActivity(binding: ActivityPluginBinding) {
currentActivity = binding.activity
binding.addRequestPermissionsResultListener(this)
}

override fun onDetachedFromActivityForConfigChanges() {
currentActivity = null
}

override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
currentActivity = binding.activity
binding.addRequestPermissionsResultListener(this)
}

override fun onDetachedFromActivity() {
currentActivity = null
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>?, grantResults: IntArray?): Boolean =
when (requestCode) {
999 -> {
if (grantResults != null && grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
currentActivity?.let {
startGeofencing(it.applicationContext)
}
true
} else {
false
}
} else -> false
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.intivoto.geofence
package com.intivoto.flutter_geofence

import android.content.BroadcastReceiver
import android.content.Context
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.intivoto.geofence
package com.intivoto.flutter_geofence

import android.app.PendingIntent
import android.content.Context
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.intivoto.geofence
package com.intivoto.flutter_geofence

fun <T1: Any, T2: Any, R: Any> safeLet(p1: T1?, p2: T2?, block: (T1, T2)->R?): R? {
return if (p1 != null && p2 != null) block(p1, p2) else null
Expand Down
Loading

0 comments on commit 11c9b64

Please sign in to comment.