diff --git a/.gitignore b/.gitignore
index 4b016310..fd4aca5a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,3 +42,4 @@ app.*.map.json
# Exceptions to above rules.
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
+health_calculators.dart
diff --git a/DQKey.jks b/DQKey.jks
deleted file mode 100644
index 7c844584..00000000
Binary files a/DQKey.jks and /dev/null differ
diff --git a/Keystore Pass.rtf b/Keystore Pass.rtf
deleted file mode 100644
index cd33f08e..00000000
--- a/Keystore Pass.rtf
+++ /dev/null
@@ -1,9 +0,0 @@
-{\rtf1\ansi\ansicpg1252\cocoartf2513
-\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-{\*\expandedcolortbl;;}
-\paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0
-\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0
-
-\f0\fs24 \cf0 keyPassword=HmGsa123\
-storePassword=HmGsa123}
\ No newline at end of file
diff --git a/android/app/build.gradle b/android/app/build.gradle
index faff5fa6..759fa6a7 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -26,12 +26,6 @@ apply plugin: 'kotlin-android'
apply plugin: 'com.google.gms.google-services'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
-def keystoreProperties = new Properties()
-def keystorePropertiesFile = rootProject.file('key.properties')
-if (keystorePropertiesFile.exists()) {
- keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
-}
-
android {
compileSdkVersion 30
@@ -40,9 +34,7 @@ android {
}
lintOptions {
-// disable 'InvalidPackage'
- checkReleaseBuilds false
- abortOnError false
+ disable 'InvalidPackage'
}
defaultConfig {
@@ -56,35 +48,21 @@ android {
}
- signingConfigs {
- release {
- keyAlias keystoreProperties['keyAlias']
- keyPassword keystoreProperties['keyPassword']
- storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
- storePassword keystoreProperties['storePassword']
- }
- }
-
buildTypes {
debug {}
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
-// signingConfig signingConfigs.debug
-// useProguard true
-
-// proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
-
- signingConfigs.release
+ signingConfig signingConfigs.debug
+ }
+ staging {
+ // Specifies a sorted list of fallback build types that the
+ // plugin should try to use when a dependency does not include a
+ // "staging" build type. You may specify as many fallbacks as you
+ // like, and the plugin selects the first build type that's
+ // available in the dependency.
+ matchingFallbacks = ['debug', 'qa', 'release']
}
-// staging {
-// // Specifies a sorted list of fallback build types that the
-// // plugin should try to use when a dependency does not include a
-// // "staging" build type. You may specify as many fallbacks as you
-// // like, and the plugin selects the first build type that's
-// // available in the dependency.
-// matchingFallbacks = ['debug', 'qa', 'release']
-// }
}
}
@@ -94,15 +72,27 @@ flutter {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
- implementation "com.google.firebase:firebase-messaging:20.3.0"
+ implementation "com.google.firebase:firebase-messaging:21.0.0"
+// implementation ('com.google.firebase:firebase-inappmessaging-display:19.1.2',{
+// exclude group: 'com.google.protobuf',module: 'protobuf-javalite'
+// 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
implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation 'com.google.code.gson:gson:2.8.6'
// Dependency on a remote binary
// implementation 'com.example.android:app-magic:12.3'
+ // Native Dependency
+ implementation "org.jetbrains.anko:anko-commons:0.10.4"
+ 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
+
+
}
diff --git a/android/app/google-services.json b/android/app/google-services.json
index a4655794..f86832ad 100644
--- a/android/app/google-services.json
+++ b/android/app/google-services.json
@@ -1,37 +1,39 @@
{
"project_info": {
- "project_number": "864393916058",
- "firebase_url": "https://diplomaticquarter-d2385.firebaseio.com",
- "project_id": "diplomaticquarter-d2385",
- "storage_bucket": "diplomaticquarter-d2385.appspot.com"
+ "project_number": "815750722565",
+ "firebase_url": "https://api-project-815750722565.firebaseio.com",
+ "project_id": "api-project-815750722565",
+ "storage_bucket": "api-project-815750722565.appspot.com"
},
"client": [
{
"client_info": {
- "mobilesdk_app_id": "1:864393916058:android:5b5a65cd6d8c18b4b97923",
+ "mobilesdk_app_id": "1:815750722565:android:62281cd3e5df4063",
"android_client_info": {
"package_name": "com.cloud.diplomaticquarterapp"
}
},
"oauth_client": [
{
- "client_id": "864393916058-tphjrn8j39ntevt32ekcvmll8aue7qql.apps.googleusercontent.com",
+ "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
- "current_key": "AIzaSyBdV3mos1BPhUzNKCj2KANJtiO3o2zh9IM"
+ "current_key": "AIzaSyDUfg6AKM1-00WyzpvLImUBC46wFrq9-qw"
}
],
"services": {
+ "analytics_service": {
+ "status": 1
+ },
"appinvite_service": {
- "other_platform_oauth_client": [
- {
- "client_id": "864393916058-tphjrn8j39ntevt32ekcvmll8aue7qql.apps.googleusercontent.com",
- "client_type": 3
- }
- ]
+ "status": 1,
+ "other_platform_oauth_client": []
+ },
+ "ads_service": {
+ "status": 2
}
}
}
diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml
index beeadd9e..d8fd4e88 100644
--- a/android/app/src/debug/AndroidManifest.xml
+++ b/android/app/src/debug/AndroidManifest.xml
@@ -3,6 +3,5 @@
-
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 0ef45c2b..1a3d4cfe 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -7,6 +7,7 @@
FlutterApplication and put your custom class here. -->
+
@@ -21,11 +22,19 @@
+
+
+
+
+
+
+
+
+ android:label="diplomaticquarterapp">
-
@@ -69,13 +76,33 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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 b8a87c8c..e67f646f 100644
--- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt
+++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt
@@ -1,11 +1,32 @@
package com.cloud.diplomaticquarterapp
+import android.os.Bundle
+import android.util.Log
import androidx.annotation.NonNull;
- import io.flutter.embedding.android.FlutterFragmentActivity
+import com.cloud.diplomaticquarterapp.utils.*
+import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
- import io.flutter.plugins.GeneratedPluginRegistrant
+import io.flutter.plugin.common.MethodChannel
+import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterFragmentActivity() {
- override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
- GeneratedPluginRegistrant.registerWith(flutterEngine);
- }
+ override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
+ GeneratedPluginRegistrant.registerWith(flutterEngine);
+ // 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() {
+ super.onResume()
+ }
}
\ No newline at end of file
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
new file mode 100644
index 00000000..b3fb4f56
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/GeoZoneModel.kt
@@ -0,0 +1,58 @@
+package com.cloud.diplomaticquarterapp.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/diplomaticquarterapp/geofence/HMG_Geofence.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/HMG_Geofence.kt
new file mode 100644
index 00000000..840075eb
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/geofence/HMG_Geofence.kt
@@ -0,0 +1,241 @@
+package com.cloud.diplomaticquarterapp.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.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
+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_UPDATE_CURRENT)
+ }
+
+ 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!!
+ }
+ }
+
+ 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