diff --git a/README.md b/README.md
index 8a284cae..25605462 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# diplomaticquarterapp
+# hmg_patient_app
A new Flutter application.
diff --git a/android/app/build.gradle b/android/app/build.gradle
index a14da293..5136988a 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -55,7 +55,7 @@ configurations.all {
android {
compileSdkVersion 34
// ndkVersion "24.0.8215888"
- namespace = "com.ejada.hmg"
+
buildFeatures {
viewBinding true
dataBinding true
@@ -133,7 +133,7 @@ android {
compileOptions {
- coreLibraryDesugaringEnabled true
+// coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
@@ -147,7 +147,7 @@ flutter {
}
dependencies {
- coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
+// coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "com.google.firebase:firebase-messaging:21.0.0"
diff --git a/android/app/gradle/wrapper/gradle-wrapper.properties b/android/app/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..a2c20300
--- /dev/null
+++ b/android/app/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+#Sun Sep 20 09:53:06 EEST 2020
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
+#distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index e9bc7171..907a2729 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -193,7 +193,6 @@
-
diff --git a/android/app/src/main/kotlin/com/cloud/hmg_patient_app/Application.kt b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/Application.kt
new file mode 100644
index 00000000..e179bc6a
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/Application.kt
@@ -0,0 +1,59 @@
+//package com.cloud.diplomaticquarterapp
+package com.ejada.hmg
+
+import com.facebook.stetho.Stetho
+import io.flutter.app.FlutterApplication
+import io.flutter.plugin.common.PluginRegistry
+import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
+//import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService
+
+class Application : FlutterApplication(), PluginRegistrantCallback {
+ override fun onCreate() {
+ super.onCreate()
+ // FlutterFirebaseMessagingService.setPluginRegistrant(this)
+
+// Stetho.initializeWithDefaults(this);
+ // Create an InitializerBuilder
+ // Create an InitializerBuilder
+ val initializerBuilder = Stetho.newInitializerBuilder(this)
+
+
+ // Enable Chrome DevTools
+ initializerBuilder.enableWebKitInspector(
+ Stetho.defaultInspectorModulesProvider(this)
+ )
+
+ // Enable command line interface
+ initializerBuilder.enableDumpapp(
+ Stetho.defaultDumperPluginsProvider(this)
+ )
+
+
+ // Use the InitializerBuilder to generate an Initializer
+ val initializer = initializerBuilder.build()
+
+
+ // Initialize Stetho with the Initializer
+ Stetho.initialize(initializer)
+ }
+
+ override fun registerWith(registry: PluginRegistry) {
+ // io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin.registerWith(registry?.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
+ }
+}
+
+//import io.flutter.app.FlutterApplication
+//import io.flutter.plugin.common.PluginRegistry
+//import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
+//import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService
+//
+//class Application : FlutterApplication(), PluginRegistrantCallback {
+// override fun onCreate() {
+// super.onCreate()
+// FlutterFirebaseMessagingService.setPluginRegistrant(this)
+// }
+//
+// override fun registerWith(registry: PluginRegistry?) {
+// FirebaseCloudMessagingPluginRegistrant.registerWith(registry)
+// }
+//}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/cloud/hmg_patient_app/FirebaseCloudMessagingPluginRegistrant.kt b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/FirebaseCloudMessagingPluginRegistrant.kt
new file mode 100644
index 00000000..df471796
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/FirebaseCloudMessagingPluginRegistrant.kt
@@ -0,0 +1,25 @@
+//package com.cloud.diplomaticquarterapp
+package com.ejada.hmg
+
+import io.flutter.plugin.common.PluginRegistry
+//import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin
+
+object FirebaseCloudMessagingPluginRegistrant {
+ fun registerWith(registry: PluginRegistry?) {
+ if (alreadyRegisteredWith(registry)) {
+ return
+ }
+ // FirebaseMessagingPlugin.registerWith(registry?.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"))
+ }
+
+ private fun alreadyRegisteredWith(registry: PluginRegistry?): Boolean {
+ val key: String? = FirebaseCloudMessagingPluginRegistrant::class.java.canonicalName
+ if (key?.let { registry?.hasPlugin(it) }!!) {
+ return true
+ }
+ if (registry != null) {
+ registry.registrarFor(key)
+ }
+ return false
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/cloud/hmg_patient_app/MainActivity.kt b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/MainActivity.kt
new file mode 100644
index 00000000..6f47d6be
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/MainActivity.kt
@@ -0,0 +1,75 @@
+package com.ejada.hmg
+import android.app.PendingIntent
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.os.Build
+import android.util.Log
+import android.view.WindowManager
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi
+import com.cloud.hmg_patient_app.PenguinInPlatformBridge
+import com.cloud.hmg_patient_app.whatsapp.AppSignatureRetriever
+import com.ejada.hmg.utils.*
+import io.flutter.embedding.android.FlutterFragmentActivity
+import io.flutter.embedding.engine.FlutterEngine
+import io.flutter.plugins.GeneratedPluginRegistrant
+import com.cloud.hmg_patient_app.whatsapp.WhatsApp
+import com.cloud.hmg_patient_app.whatsapp.WhatsAppOtpPlatformBridge
+
+
+class MainActivity: FlutterFragmentActivity() {
+ @RequiresApi(Build.VERSION_CODES.O)
+ override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
+ GeneratedPluginRegistrant.registerWith(flutterEngine);
+ // Create Flutter Platform Bridge
+ this.window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON)
+
+ PlatformBridge(flutterEngine, this).create()
+ OpenTokPlatformBridge(flutterEngine, this).create()
+ PenguinInPlatformBridge(flutterEngine, this).create()
+ WhatsAppOtpPlatformBridge(flutterEngine, this).invoke()
+ AppSignatureRetriever().logSignatures(this)
+// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {x
+// val mChannel = NotificationChannel("video_call_noti", "video call", NotificationManager.IMPORTANCE_HIGH)
+// val soundUri = Uri.parse("android.resource://" + getApplicationContext()
+// .getPackageName() + "/" + R.raw.alert)
+// System.out.println("soundUri");
+// System.out.println("soundUri: $soundUri");
+// System.out.println("soundUri : ${soundUri.path}");
+// val att = AudioAttributes.Builder()
+// .setUsage(AudioAttributes.USAGE_NOTIFICATION)
+// .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
+// .build();
+// mChannel.setSound(soundUri , att)
+// mChannel.description = "Video Call Notifications"
+// val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
+// notificationManager.createNotificationChannel(mChannel)
+// }
+
+// val time = timeToMillis("04:00:00", "HH:mm:ss")
+
+ }
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array,
+ grantResults: IntArray
+ ) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+
+ val granted = grantResults.all { it == PackageManager.PERMISSION_GRANTED }
+ val intent = Intent("PERMISSION_RESULT_ACTION").apply {
+ putExtra("PERMISSION_GRANTED", granted)
+ }
+ sendBroadcast(intent)
+
+ // Log the request code and permission results
+ Log.d("PermissionsResult", "Request Code: $requestCode")
+ Log.d("PermissionsResult", "Permissions: ${permissions.joinToString()}")
+ Log.d("PermissionsResult", "Grant Results: ${grantResults.joinToString()}")
+
+ }
+
+ override fun onResume() {
+ super.onResume()
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/cloud/hmg_patient_app/PenguinInPlatformBridge.kt b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/PenguinInPlatformBridge.kt
new file mode 100644
index 00000000..2fd03a5d
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/PenguinInPlatformBridge.kt
@@ -0,0 +1,53 @@
+package com.cloud.hmg_patient_app
+
+import com.ejada.hmg.MainActivity
+import android.os.Build
+import android.util.Log
+import androidx.annotation.RequiresApi
+import com.cloud.hmg_patient_app.penguin.PenguinView
+import io.flutter.embedding.engine.FlutterEngine
+import io.flutter.plugin.common.MethodCall
+import io.flutter.plugin.common.MethodChannel
+
+class PenguinInPlatformBridge(
+ private var flutterEngine: FlutterEngine,
+ private var mainActivity: MainActivity
+) {
+
+ private lateinit var channel: MethodChannel
+
+ companion object {
+ private const val CHANNEL = "launch_penguin_ui"
+ }
+
+ @RequiresApi(Build.VERSION_CODES.O)
+ fun create() {
+// openTok = OpenTok(mainActivity, flutterEngine)
+ channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
+ channel.setMethodCallHandler { call: MethodCall, result: MethodChannel.Result ->
+ when (call.method) {
+ "launchPenguin" -> {
+ print("the platform channel is being called")
+ val args = call.arguments as Map?
+ Log.d("TAG", "configureFlutterEngine: $args")
+ println("args")
+ args?.let {
+ PenguinView(
+ mainActivity,
+ 100,
+ args,
+ flutterEngine.dartExecutor.binaryMessenger,
+ activity = mainActivity,
+ channel
+ )
+ }
+ }
+
+ else -> {
+ result.notImplemented()
+ }
+ }
+ }
+ }
+
+}
diff --git a/android/app/src/main/kotlin/com/cloud/hmg_patient_app/PermissionManager/PermissionHelper.kt b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/PermissionManager/PermissionHelper.kt
new file mode 100644
index 00000000..b308af05
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/PermissionManager/PermissionHelper.kt
@@ -0,0 +1,28 @@
+package com.cloud.diplomaticquarterapp.PermissionManager
+
+import android.Manifest
+import android.os.Build
+
+object PermissionHelper {
+
+ fun getRequiredPermissions(): Array {
+ val permissions = mutableListOf(
+ Manifest.permission.INTERNET,
+ Manifest.permission.ACCESS_FINE_LOCATION,
+ Manifest.permission.ACCESS_COARSE_LOCATION,
+ Manifest.permission.ACCESS_NETWORK_STATE,
+ Manifest.permission.BLUETOOTH,
+ Manifest.permission.BLUETOOTH_ADMIN,
+// Manifest.permission.ACTIVITY_RECOGNITION
+ )
+
+ // For Android 12 (API level 31) and above, add specific permissions
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // Android 12 (API 31) and above
+ permissions.add(Manifest.permission.BLUETOOTH_SCAN)
+ permissions.add(Manifest.permission.BLUETOOTH_CONNECT)
+ permissions.add(Manifest.permission.HIGH_SAMPLING_RATE_SENSORS)
+ }
+
+ return permissions.toTypedArray()
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/cloud/hmg_patient_app/PermissionManager/PermissionManager.kt b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/PermissionManager/PermissionManager.kt
new file mode 100644
index 00000000..81f2a6f0
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/PermissionManager/PermissionManager.kt
@@ -0,0 +1,50 @@
+package com.cloud.diplomaticquarterapp.PermissionManager
+
+import android.app.Activity
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.Build
+import androidx.core.app.ActivityCompat
+import androidx.core.content.ContextCompat
+
+class PermissionManager(
+ private val context: Context,
+ val listener: PermissionListener,
+ private val requestCode: Int,
+ vararg permissions: String
+) {
+
+ private val permissionsArray = permissions
+
+ interface PermissionListener {
+ fun onPermissionGranted()
+ fun onPermissionDenied()
+ }
+
+ fun arePermissionsGranted(): Boolean {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ permissionsArray.all {
+ ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
+ }
+ } else {
+ true
+ }
+ }
+
+ fun requestPermissions(activity: Activity) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ ActivityCompat.requestPermissions(activity, permissionsArray, requestCode)
+ }
+ }
+
+ fun handlePermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
+ if (this.requestCode == requestCode) {
+ val allGranted = grantResults.all { it == PackageManager.PERMISSION_GRANTED }
+ if (allGranted) {
+ listener.onPermissionGranted()
+ } else {
+ listener.onPermissionDenied()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/cloud/hmg_patient_app/PermissionManager/PermissionResultReceiver.kt b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/PermissionManager/PermissionResultReceiver.kt
new file mode 100644
index 00000000..33765192
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/PermissionManager/PermissionResultReceiver.kt
@@ -0,0 +1,15 @@
+package com.cloud.diplomaticquarterapp.PermissionManager
+
+// PermissionResultReceiver.kt
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+
+class PermissionResultReceiver(
+ private val callback: (Boolean) -> Unit
+) : BroadcastReceiver() {
+ override fun onReceive(context: Context?, intent: Intent?) {
+ val granted = intent?.getBooleanExtra("PERMISSION_GRANTED", false) ?: false
+ callback(granted)
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/cloud/hmg_patient_app/bkp_files/CustomFlutterHmsMessageService.java b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/bkp_files/CustomFlutterHmsMessageService.java
new file mode 100644
index 00000000..c96a60af
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/bkp_files/CustomFlutterHmsMessageService.java
@@ -0,0 +1,56 @@
+/*
+* ---------------
+* Note: Todo
+* ---------------
+* Need to be place in huawei_push (package com.huawei.hms.flutter.push.hms) and define in huawei_push manifest.xml
+* */
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.util.Log;
+
+import com.huawei.hms.flutter.push.hms.FlutterHmsMessageService;
+import com.huawei.hms.flutter.push.utils.ApplicationUtils;
+
+import org.json.JSONObject;
+
+//package com.huawei.hms.flutter.push.hms
+//
+//
+//import android.content.Context;
+//import android.content.Intent;
+//import android.content.SharedPreferences;
+//
+//import com.huawei.hms.flutter.push.hms.FlutterHmsMessageService;
+//import com.huawei.hms.flutter.push.utils.ApplicationUtils;
+//import com.huawei.hms.push.RemoteMessage;
+//
+//import org.json.JSONObject;
+//
+//public class CustomFlutterHmsMessageService extends FlutterHmsMessageService {
+// @Override
+// public void onMessageReceived(RemoteMessage remoteMessage) {
+// super.onMessageReceived(remoteMessage);
+// try {
+// String jsonStr = remoteMessage.getData();
+// JSONObject json_data = new JSONObject(jsonStr);
+// JSONObject json_data_data = new JSONObject(json_data.getString("data"));
+// if(json_data_data.getString("is_call").equalsIgnoreCase("true")){
+// boolean isApplicationInForeground = ApplicationUtils.isApplicationInForeground(this);
+// if(!isApplicationInForeground){
+// SharedPreferences preferences = getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE);
+// preferences.edit().putString("flutter.call_data", json_data.getString("data")).apply();
+//
+// Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName());
+// intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
+// startActivity(intent);
+// Log.v("onMessageReceived", "startActivity(intent) called");
+// }
+// }
+//
+// } catch (Exception e) {
+// e.printStackTrace();
+// }
+// }
+//}
diff --git a/android/app/src/main/kotlin/com/cloud/hmg_patient_app/geofence/GeoZoneModel.kt b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/geofence/GeoZoneModel.kt
new file mode 100644
index 00000000..16ed0939
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/geofence/GeoZoneModel.kt
@@ -0,0 +1,58 @@
+package com.ejada.hmg.geofence
+
+import com.google.android.gms.location.Geofence
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+
+class GeoZoneModel {
+ var GEOF_ID:Int = 0
+ var Radius:Int = 0
+ var Type:Int = 0
+ var ProjectID:Int = 0
+
+ var Description:String? = null
+ var DescriptionN:String? = null
+ var Latitude:String? = null
+ var Longitude:String? = null
+ var ImageURL:String? = null
+ var IsCity:String? = null
+
+ fun identifier():String{
+ return "$GEOF_ID" + "_hmg"
+ }
+
+ fun message():String{
+ return Description ?: "nil"
+ }
+
+ fun listFrom(jsonString: String) : List{
+ val type = object : TypeToken?>() {}.getType()
+ return Gson().fromJson(jsonString, type)
+ }
+
+ fun toGeofence() : Geofence?{
+ if (!Latitude.isNullOrEmpty() && !Longitude.isNullOrEmpty() && Radius > 50) {
+ val lat = Latitude!!.trim().toDoubleOrNull()
+ val long = Longitude!!.trim().toDoubleOrNull()
+ val rad = Radius.toFloat()
+ if(lat != null && long != null){
+
+ val loiteringDelayMinutes:Int = 2 // in Minutes
+ return Geofence.Builder()
+ .setRequestId(identifier())
+ .setCircularRegion(
+ lat,
+ long,
+ rad
+ )
+ .setTransitionTypes(GeofenceTransition.ENTER_EXIT.value)
+ .setNotificationResponsiveness(0)
+ .setLoiteringDelay(loiteringDelayMinutes * 60 * 1000)
+ .setExpirationDuration(Geofence.NEVER_EXPIRE)
+ .build()
+ }
+ }
+ return null
+ }
+
+}
diff --git a/android/app/src/main/kotlin/com/cloud/hmg_patient_app/geofence/HMG_Geofence.kt b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/geofence/HMG_Geofence.kt
new file mode 100644
index 00000000..8452a083
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/hmg_patient_app/geofence/HMG_Geofence.kt
@@ -0,0 +1,291 @@
+package com.ejada.hmg.geofence
+
+import android.Manifest
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.content.SharedPreferences
+import android.content.pm.PackageManager
+import android.location.Location
+import androidx.core.content.ContextCompat
+import com.ejada.hmg.geofence.intent_receivers.GeofenceBroadcastReceiver
+import com.ejada.hmg.geofence.intent_receivers.ReregisterGeofenceJobService
+import com.ejada.hmg.utils.*
+import com.google.android.gms.location.Geofence
+import com.google.android.gms.location.GeofencingClient
+import com.google.android.gms.location.GeofencingRequest
+import com.google.android.gms.location.LocationServices
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+
+enum class GeofenceTransition(val value: Int) {
+ ENTER(1),
+ EXIT(2),
+ DWELL(4),
+
+ ENTER_EXIT((ENTER.value or EXIT.value)),
+ DWELL_EXIT((DWELL.value or EXIT.value));
+
+ companion object {
+ fun fromInt(value: Int) = GeofenceTransition.values().first { it.value == value }
+ }
+
+ fun named(): String {
+ if (value == 1) return "Enter"
+ if (value == 2) return "Exit"
+ if (value == 4) return "dWell"
+ if (value == (ENTER.value or EXIT.value)) return "Enter or Exit"
+ if (value == (DWELL.value or EXIT.value)) return "DWell or Exit"
+ return "unknown"
+ }
+}
+
+class HMG_Geofence {
+ // https://developer.android.com/training/location/geofencing#java
+
+ private lateinit var context: Context
+ private lateinit var preferences: SharedPreferences
+ private val gson = Gson()
+
+ private lateinit var geofencingClient: GeofencingClient
+ private val geofencePendingIntent: PendingIntent by lazy {
+ val intent = Intent(context, GeofenceBroadcastReceiver::class.java)
+ PendingIntent.getBroadcast(
+ context,
+ 0,
+ intent,
+ PendingIntent.FLAG_IMMUTABLE
+ )
+ }
+
+ companion object {
+
+ var instance: HMG_Geofence? = null
+ fun shared(context: Context): HMG_Geofence {
+ if (instance == null) {
+ instance = HMG_Geofence()
+ instance?.context = context
+ instance?.geofencingClient = LocationServices.getGeofencingClient(context)
+ instance?.preferences =
+ context.getSharedPreferences(PREFS_STORAGE, Context.MODE_PRIVATE)
+ }
+ return instance!!
+ }
+ }
+
+ private fun limitize(zones: List): List {
+ var geoZones_ = zones
+ if (zones.size > 100)
+ geoZones_ = zones.subList(0, 99)
+ return geoZones_
+ }
+
+
+ fun register(completion: ((Boolean, java.lang.Exception?) -> Unit)) {
+ unRegisterAll { status, exception ->
+ val geoZones = getGeoZonesFromPreference(context)
+ doRegister(geoZones) { status_, error ->
+ completion.let { it(status_, error) }
+ }
+ }
+ }
+
+ fun unRegisterAll(completion: (status: Boolean, exception: Exception?) -> Unit) {
+ getActiveGeofences({ success ->
+ removeActiveGeofences()
+ if (success.isNotEmpty())
+ geofencingClient
+ .removeGeofences(success)
+ .addOnSuccessListener {
+ completion(true, null)
+ }
+ .addOnFailureListener {
+ completion(false, it)
+ saveLog(context, "error:REMOVE_GEOFENCES", it.localizedMessage)
+ }
+ else
+ completion(true, null)
+
+ }, { failed ->
+ // Nothing to do with failed geofences.
+ })
+ }
+
+ private fun doRegister(
+ geoZones: List,
+ completion: ((Boolean, java.lang.Exception?) -> Unit)? = null
+ ) {
+ if (geoZones.isEmpty())
+ return
+
+ val geoZones_ = limitize(geoZones)
+
+ fun buildGeofencingRequest(geofences: List): GeofencingRequest {
+ return GeofencingRequest.Builder()
+ .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_DWELL)
+ .addGeofences(geofences)
+ .build()
+ }
+
+ getActiveGeofences({ active ->
+
+ val geofences = mutableListOf()
+ geoZones_.forEach {
+ it.toGeofence()?.let { geof ->
+ if (!active.contains(geof.requestId)) { // if not already registered then register
+ geofences.add(geof)
+ }
+ }
+ }
+
+ if (checkPermission() && geofences.isNotEmpty()) {
+ geofencingClient
+ .addGeofences(buildGeofencingRequest(geofences), geofencePendingIntent)
+ .addOnSuccessListener {
+ Logs.RegisterGeofence.save(
+ context,
+ "SUCCESS",
+ "Successfuly registered the geofences",
+ Logs.STATUS.SUCCESS
+ )
+ saveActiveGeofence(geofences.map { it.requestId }, listOf())
+ completion?.let { it(true, null) }
+ }
+ .addOnFailureListener { exc ->
+ Logs.RegisterGeofence.save(
+ context,
+ "FAILED_TO_REGISTER",
+ "Failed to register geofence",
+ Logs.STATUS.ERROR
+ )
+ completion?.let { it(false, exc) }
+ }
+
+ // Schedule the job to register after specified duration (due to: events not calling after long period.. days or days [Needs to register fences again])
+ HMGUtils.scheduleJob(
+ context,
+ ReregisterGeofenceJobService::class.java,
+ ReregisterGeofenceJobService.JobID,
+ ReregisterGeofenceJobService.TriggerIntervalDuration
+ )
+ }
+
+ }, null)
+
+ }
+
+ fun getGeoZonesFromPreference(context: Context): List {
+ val pref = context.getSharedPreferences(PREFS_STORAGE, Context.MODE_PRIVATE)
+ val json = pref.getString(PREF_KEY_HMG_ZONES, "[]")
+
+ val geoZones = GeoZoneModel().listFrom(json!!)
+ return geoZones
+ }
+
+ fun saveActiveGeofence(success: List, failed: List) {
+ val jsonSuccess = gson.toJson(success)
+ val jsonFailure = gson.toJson(failed)
+ preferences.edit().putString(PREF_KEY_SUCCESS, jsonSuccess).apply()
+ preferences.edit().putString(PREF_KEY_FAILED, jsonFailure).apply()
+ }
+
+ fun removeActiveGeofences() {
+ preferences.edit().putString(PREF_KEY_SUCCESS, "[]").apply()
+ preferences.edit().putString(PREF_KEY_FAILED, "[]").apply()
+ }
+
+ fun getActiveGeofences(
+ success: (success: List) -> Unit,
+ failure: ((failed: List) -> Unit)?
+ ) {
+ val type = object : TypeToken?>() {}.type
+
+ val jsonSuccess = preferences.getString(PREF_KEY_SUCCESS, "[]")
+ val success = gson.fromJson>(jsonSuccess, type)
+ success(success)
+
+ if (failure != null) {
+ val jsonFailure = preferences.getString(PREF_KEY_FAILED, "[]")
+ val failed = gson.fromJson>(jsonFailure, type)
+ failure(failed)
+ }
+
+ }
+
+ private fun checkPermission(): Boolean {
+ return ContextCompat.checkSelfPermission(
+ context,
+ Manifest.permission.ACCESS_FINE_LOCATION
+ ) == PackageManager.PERMISSION_GRANTED
+ }
+
+ fun getPatientID(): Int? {
+ var profileJson = preferences.getString("flutter.imei-user-data", null)
+ if (profileJson == null)
+ profileJson = preferences.getString("flutter.user-profile", null)
+
+ val type = object : TypeToken