diff --git a/.gitignore b/.gitignore
index fd4aca5a..cff0e374 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,6 +25,7 @@
.dart_tool/
.flutter-plugins
pubspec.lock
+/ios/Podfile.lock
.flutter-plugins-dependencies
.packages
.pub-cache/
diff --git a/GoogleService-Info_DQ.plist b/GoogleService-Info_DQ.plist
new file mode 100644
index 00000000..0c093a2a
--- /dev/null
+++ b/GoogleService-Info_DQ.plist
@@ -0,0 +1,36 @@
+
+
+
+
+ CLIENT_ID
+ 864393916058-ekeb4s8tgfo58dutv0l54399t7ivr06r.apps.googleusercontent.com
+ REVERSED_CLIENT_ID
+ com.googleusercontent.apps.864393916058-ekeb4s8tgfo58dutv0l54399t7ivr06r
+ API_KEY
+ AIzaSyA_6ayGCk4fly7o7eTVBrj9kuHBYHMAOfs
+ GCM_SENDER_ID
+ 864393916058
+ PLIST_VERSION
+ 1
+ BUNDLE_ID
+ com.cloud.diplomaticquarterapp
+ PROJECT_ID
+ diplomaticquarter-d2385
+ STORAGE_BUCKET
+ diplomaticquarter-d2385.appspot.com
+ IS_ADS_ENABLED
+
+ IS_ANALYTICS_ENABLED
+
+ IS_APPINVITE_ENABLED
+
+ IS_GCM_ENABLED
+
+ IS_SIGNIN_ENABLED
+
+ GOOGLE_APP_ID
+ 1:864393916058:ios:13f787bbfe6051f8b97923
+ DATABASE_URL
+ https://diplomaticquarter-d2385.firebaseio.com
+
+
\ No newline at end of file
diff --git a/GoogleService-Info_HMG.plist b/GoogleService-Info_HMG.plist
new file mode 100644
index 00000000..153aa2c6
--- /dev/null
+++ b/GoogleService-Info_HMG.plist
@@ -0,0 +1,38 @@
+
+
+
+
+ CLIENT_ID
+ 815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt.apps.googleusercontent.com
+ REVERSED_CLIENT_ID
+ com.googleusercontent.apps.815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt
+ ANDROID_CLIENT_ID
+ 815750722565-m14h8mkosm7cnq6uh6rhqr54dn02d705.apps.googleusercontent.com
+ API_KEY
+ AIzaSyDiXnCO00li4V7Ioa2YZ_M4ECxRsu_P9tA
+ GCM_SENDER_ID
+ 815750722565
+ PLIST_VERSION
+ 1
+ BUNDLE_ID
+ com.HMG.Smartphone
+ PROJECT_ID
+ api-project-815750722565
+ STORAGE_BUCKET
+ api-project-815750722565.appspot.com
+ IS_ADS_ENABLED
+
+ IS_ANALYTICS_ENABLED
+
+ IS_APPINVITE_ENABLED
+
+ IS_GCM_ENABLED
+
+ IS_SIGNIN_ENABLED
+
+ GOOGLE_APP_ID
+ 1:815750722565:ios:328ec247a81a2ca23c186c
+ DATABASE_URL
+ https://api-project-815750722565.firebaseio.com
+
+
\ No newline at end of file
diff --git a/agconnect-services_DQ.json b/agconnect-services_DQ.json
new file mode 100644
index 00000000..563c412f
--- /dev/null
+++ b/agconnect-services_DQ.json
@@ -0,0 +1,14 @@
+{
+ "client":{
+ "appType":"1",
+ "cp_id":"2640966000002322881",
+ "product_id":"736430079244816576",
+ "client_id":"563737844552565952",
+ "client_secret":"9C9A2C272576B8AE6E886C78AF944E8354B91F0AF3381129BB8369FB35E41C47",
+ "project_id":"736430079244816576",
+ "app_id":"103856487",
+ "api_key":"CgB6e3x90XxBrOCMun809w+DOzcFEettcBDUF3fqaLry1ViqTeJqoPwpfaOq/uGw//x0oYwucu9aWazs+Rdj0GUF",
+ "package_name":"com.cloud.diplomaticquarterapp"
+ },
+ "configuration_version":"1.0"
+}
\ No newline at end of file
diff --git a/agconnect-services_HMG.json b/agconnect-services_HMG.json
new file mode 100644
index 00000000..cfdaf83b
--- /dev/null
+++ b/agconnect-services_HMG.json
@@ -0,0 +1,14 @@
+{
+ "client":{
+ "appType":"1",
+ "cp_id":"2640966000002322881",
+ "product_id":"736430079244816567",
+ "client_id":"563735388191982656",
+ "client_secret":"650C7C799812AFFD53A10C7756CF05FB9F215A7E49032ABA8EBF3E14B77535CF",
+ "project_id":"736430079244816567",
+ "app_id":"102857389",
+ "api_key":"CgB6e3x9DJzMgRCmnT6dyUEkp6UsIfddb6l3w0ZEXzeiRMHEFi3400Z5fJ5qaHneU0OrAI/JRpk+DMGVs3QpUxlI",
+ "package_name":"com.ejada.hmg"
+ },
+ "configuration_version":"1.0"
+}
\ No newline at end of file
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 19d22b13..11e99a2a 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -7,9 +7,9 @@ if (localPropertiesFile.exists()) {
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
-if (flutterRoot == null) {
- throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
-}
+//if (flutterRoot == null) {
+// throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+//}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
@@ -27,7 +27,7 @@ apply plugin: 'com.google.gms.google-services'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
- compileSdkVersion 28
+ compileSdkVersion 30
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
@@ -41,7 +41,7 @@ android {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.cloud.diplomaticquarterapp"
minSdkVersion 21
- targetSdkVersion 28
+ targetSdkVersion 30
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled true
@@ -78,6 +78,7 @@ dependencies {
// exclude group: 'com.google.protobuf',module: 'protobuf-lite'
// })
implementation 'pub.devrel:easypermissions:0.4.0'
+// implementation 'com.google.firebase:firebase-inappmessaging-display:17.2.0'
// implementation 'com.google.firebase:firebase-inappmessaging-display:17.2.0'
implementation 'com.google.guava:guava:27.0.1-android'
// Dependency on local binaries
@@ -93,6 +94,6 @@ dependencies {
implementation 'com.github.kittinunf.fuel:fuel:2.3.0' //for JVM
implementation 'com.github.kittinunf.fuel:fuel-android:2.3.0'
implementation 'com.google.android.gms:play-services-location:17.1.0'//for Android
-
+ implementation 'com.google.android.gms:play-services-basement:17.5.0'
}
diff --git a/android/app/google-services.json b/android/app/google-services.json
index f86832ad..a4655794 100644
--- a/android/app/google-services.json
+++ b/android/app/google-services.json
@@ -1,39 +1,37 @@
{
"project_info": {
- "project_number": "815750722565",
- "firebase_url": "https://api-project-815750722565.firebaseio.com",
- "project_id": "api-project-815750722565",
- "storage_bucket": "api-project-815750722565.appspot.com"
+ "project_number": "864393916058",
+ "firebase_url": "https://diplomaticquarter-d2385.firebaseio.com",
+ "project_id": "diplomaticquarter-d2385",
+ "storage_bucket": "diplomaticquarter-d2385.appspot.com"
},
"client": [
{
"client_info": {
- "mobilesdk_app_id": "1:815750722565:android:62281cd3e5df4063",
+ "mobilesdk_app_id": "1:864393916058:android:5b5a65cd6d8c18b4b97923",
"android_client_info": {
"package_name": "com.cloud.diplomaticquarterapp"
}
},
"oauth_client": [
{
- "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com",
+ "client_id": "864393916058-tphjrn8j39ntevt32ekcvmll8aue7qql.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
- "current_key": "AIzaSyDUfg6AKM1-00WyzpvLImUBC46wFrq9-qw"
+ "current_key": "AIzaSyBdV3mos1BPhUzNKCj2KANJtiO3o2zh9IM"
}
],
"services": {
- "analytics_service": {
- "status": 1
- },
"appinvite_service": {
- "status": 1,
- "other_platform_oauth_client": []
- },
- "ads_service": {
- "status": 2
+ "other_platform_oauth_client": [
+ {
+ "client_id": "864393916058-tphjrn8j39ntevt32ekcvmll8aue7qql.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
}
}
}
diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro
new file mode 100644
index 00000000..4ace459d
--- /dev/null
+++ b/android/app/proguard-rules.pro
@@ -0,0 +1,4 @@
+-keep class tvi.webrtc.** { *; }
+-keep class com.twilio.video.** { *; }
+-keep class com.twilio.common.** { *; }
+-keepattributes InnerClasses
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 1032b29b..1a3d4cfe 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -10,6 +10,7 @@
+
@@ -76,13 +77,21 @@
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt
index 8b73b0c7..e67f646f 100644
--- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt
+++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt
@@ -2,8 +2,7 @@ package com.cloud.diplomaticquarterapp
import android.os.Bundle
import android.util.Log
import androidx.annotation.NonNull;
-import com.cloud.diplomaticquarterapp.utils.FlutterText
-import com.cloud.diplomaticquarterapp.utils.PlatformBridge
+import com.cloud.diplomaticquarterapp.utils.*
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
@@ -15,6 +14,16 @@ class MainActivity: FlutterFragmentActivity() {
// Create Flutter Platform Bridge
PlatformBridge(flutterEngine.dartExecutor.binaryMessenger, this).create()
+ val time = timeToMillis("04:00:00", "HH:mm:ss")
+ print(time)
+
+// val d1 = Logs.list(this)
+// val d2 = Logs.raw(this)
+// val d3 = Logs.RegisterGeofence.list(this)
+// val d4 = Logs.RegisterGeofence.raw(this)
+// val d5 = Logs.GeofenceEvent.list(this)
+// val d6 = Logs.GeofenceEvent.raw(this)
+ print("")
}
override fun onResume() {
diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeoZoneModel.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeoZoneModel.kt
index 7eba1ead..b3fb4f56 100644
--- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeoZoneModel.kt
+++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeoZoneModel.kt
@@ -37,6 +37,7 @@ class GeoZoneModel {
val rad = Radius.toFloat()
if(lat != null && long != null){
+ val loiteringDelayMinutes:Int = 2 // in Minutes
return Geofence.Builder()
.setRequestId(identifier())
.setCircularRegion(
@@ -45,7 +46,8 @@ class GeoZoneModel {
rad
)
.setTransitionTypes(GeofenceTransition.ENTER_EXIT.value)
-// .setNotificationResponsiveness(0)
+ .setNotificationResponsiveness(0)
+ .setLoiteringDelay(loiteringDelayMinutes * 60 * 1000)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.build()
}
diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofenceBroadcastReceiver.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofenceBroadcastReceiver.kt
deleted file mode 100644
index 8fc1faae..00000000
--- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeofenceBroadcastReceiver.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-package com.cloud.diplomaticquarterapp.geofence
-
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-
-class GeofenceBroadcastReceiver : BroadcastReceiver() {
- override fun onReceive(context: Context, intent: Intent) {
- GeofenceTransitionsJobIntentService.enqueueWork(context, intent)
- }
-}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/HMG_Geofence.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/HMG_Geofence.kt
index 4d2c48b3..840075eb 100644
--- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/HMG_Geofence.kt
+++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/HMG_Geofence.kt
@@ -6,7 +6,11 @@ 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.cloud.diplomaticquarterapp.geofence.intent_receivers.GeofenceBroadcastReceiver
+import com.cloud.diplomaticquarterapp.geofence.intent_receivers.ReregisterGeofenceJobService
+import com.cloud.diplomaticquarterapp.utils.*
import com.google.android.gms.location.Geofence
import com.google.android.gms.location.GeofencingClient
import com.google.android.gms.location.GeofencingRequest
@@ -17,8 +21,10 @@ 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(4);
+ DWELL_EXIT((DWELL.value or EXIT.value));
companion object {
fun fromInt(value: Int) = GeofenceTransition.values().first { it.value == value }
@@ -27,17 +33,13 @@ enum class GeofenceTransition(val value: Int) {
fun named():String{
if (value == 1)return "Enter"
if (value == 2)return "Exit"
- if (value == (ENTER.value or EXIT.value))return "Enter or 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"
}
}
-const val PREFS_STORAGE = "FlutterSharedPreferences"
-const val PREF_KEY_SUCCESS = "HMG_GEOFENCE_SUCCESS"
-const val PREF_KEY_FAILED = "HMG_GEOFENCE_FAILED"
-const val PREF_KEY_HMG_ZONES = "flutter.hmg-geo-fences"
-
class HMG_Geofence {
// https://developer.android.com/training/location/geofencing#java
@@ -69,13 +71,53 @@ class HMG_Geofence {
}
}
- fun register(geoZones: List){
+ 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(0)
+ .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_DWELL)
.addGeofences(geofences)
.build()
}
@@ -83,9 +125,9 @@ class HMG_Geofence {
getActiveGeofences({ active ->
val geofences = mutableListOf()
- geoZones.forEach {
- it.toGeofence()?.let { geof ->
- if(!active.contains(geof.requestId)){ // if not already registered then register
+ geoZones_.forEach {
+ it.toGeofence()?.let { geof ->
+ if (!active.contains(geof.requestId)) { // if not already registered then register
geofences.add(geof)
}
}
@@ -95,31 +137,29 @@ class HMG_Geofence {
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 {
- print(it.localizedMessage)
+ .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)
+
+ }, null)
+
}
- fun unRegisterAll(completion: (status: Boolean, exception:Exception?) -> Unit){
- getActiveGeofences({ success ->
- val mList = success.toMutableList()
- mList.add("12345")
- geofencingClient
- .removeGeofences(success)
- .addOnSuccessListener {
- completion(true, null)
- }
- .addOnFailureListener {
- completion(false, it)
- }
- removeActiveGeofences()
- }, { failed ->
- // Nothing to do with failed geofences.
- })
+ 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){
@@ -130,8 +170,8 @@ class HMG_Geofence {
}
fun removeActiveGeofences(){
- preferences.edit().putString(PREF_KEY_SUCCESS,"[]").apply()
- preferences.edit().putString(PREF_KEY_FAILED,"[]").apply()
+ preferences.edit().putString(PREF_KEY_SUCCESS, "[]").apply()
+ preferences.edit().putString(PREF_KEY_FAILED, "[]").apply()
}
fun getActiveGeofences(success: (success: List) -> Unit, failure: ((failed: List) -> Unit)?){
@@ -154,12 +194,48 @@ class HMG_Geofence {
}
fun getPatientID():Int?{
- val profileJson = preferences.getString("flutter.imei-user-data", "{}")
+ var profileJson = preferences.getString("flutter.imei-user-data", null)
+ if (profileJson == null)
+ profileJson = preferences.getString("flutter.user-profile", null)
+
val type = object : TypeToken