diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..603b1407
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,14 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 00000000..b3405b3b
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+My Application
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 00000000..681f41ae
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ xmlns:android
+
+ ^$
+
+
+
+
+
+
+
+
+ xmlns:.*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*:id
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ .*:name
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ name
+
+ ^$
+
+
+
+
+
+
+
+
+ style
+
+ ^$
+
+
+
+
+
+
+
+
+ .*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*
+
+ http://schemas.android.com/apk/res/android
+
+
+ ANDROID_ATTRIBUTE_ORDER
+
+
+
+
+
+
+ .*
+
+ .*
+
+
+ BY_NAME
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 00000000..169fd0dd
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 00000000..f5c6d9eb
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 00000000..7f68460d
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..94a25f7f
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 8485fa33..73ea5c50 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,22 @@
# disaster-management
Lynk Hackathon 2019 - Disaster Management
+
+Helfy App
+an android app that creates a mesh network to stimulate a decentralized network communication which is build upon wifi, bluetooth, network, sms and the internet. this network enables the users to perform complex message transfer and the message analysis on the every device connected to the network to help them in times of emergency.
+
+Project Specification:
+1. the app is entirely written in kotlin.
+2. uses bridgify and hype mesh sdk to connect with near by devices
+3. custom location class component to indentify users location and even without interent or any network connection
+4. uses twilio to send sms and what's app message to the emergency contact
+5. uses android architecture components like, livedata coroutines, viewmodel, navigation
+4. uses room library to collect and store the nearby devices id.
+
+app features:
+1. send emergency sms to others without network or internet.
+2. request for food or medicien support through the network.
+3. enable volunteers to join the network easily and help the victims
+4. send out a alert message to nearby devices, to help the person in danger
+5. send network call request to volunteer server to inform about the situation and help needed.
+6. all the payload consists of location of the user
+7. allow anyone to work as a volunteer on the fly without any registration
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 00000000..796b96d1
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 00000000..9f68cb8e
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,91 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+apply plugin: 'kotlin-kapt'
+
+android {
+ compileSdkVersion 29
+ buildToolsVersion "29.0.2"
+ defaultConfig {
+ applicationId "com.example.myapplication"
+ minSdkVersion 21
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ targetCompatibility JavaVersion.VERSION_1_8
+ sourceCompatibility JavaVersion.VERSION_1_8
+ }
+
+ packagingOptions {
+ exclude 'META-INF/DEPENDENCIES'
+ exclude 'META-INF/LICENSE'
+ exclude 'META-INF/LICENSE.txt'
+ exclude 'META-INF/license.txt'
+ exclude 'META-INF/NOTICE'
+ exclude 'META-INF/NOTICE.txt'
+ exclude 'META-INF/notice.txt'
+ exclude 'META-INF/ASL2.0'
+ }
+}
+
+dependencies {
+ def lifecycle_version = "2.1.0"
+ def nav_version = "2.1.0"
+ def google_play_service = '17.0.0'
+
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation 'androidx.appcompat:appcompat:1.0.2'
+ implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+ implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'androidx.test:runner:1.1.1'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
+ implementation "androidx.core:core-ktx:+"
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation 'com.bridgefy:android-sdk:1.1.24'
+ implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
+ // For Kotlin use lifecycle-viewmodel-ktx
+ // Kotlin
+ implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
+ implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
+ implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
+
+ //twilio for sms
+ implementation group: "com.twilio.sdk", name: "twilio", version: "7.42.0"
+
+ implementation "com.google.android.gms:play-services-location:${google_play_service}"
+ implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.1.0'
+
+ def room_version = "2.2.0"
+
+ implementation "androidx.room:room-runtime:$room_version"
+ kapt "androidx.room:room-compiler:$room_version"
+ // For Kotlin use kapt instead of annotationProcessor
+
+ // optional - Kotlin Extensions and Coroutines support for Room
+ implementation "androidx.room:room-ktx:$room_version"
+
+ // Animations
+ implementation 'com.airbnb.android:lottie:3.0.7'
+ implementation 'com.wang.avi:library:2.1.3'
+ implementation 'com.skyfishjy.ripplebackground:library:1.0.1'
+
+
+}
+repositories {
+ mavenCentral()
+ maven {
+ url "http://maven.bridgefy.com/artifactory/libs-release-local"
+ artifactUrls = ["http://jcenter.bintray.com/"]
+ }
+}
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 00000000..7064aba6
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,32 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
+-keep class com.bridgefy.sdk.** { *; }
+-dontwarn com.bridgefy.sdk.**
+-dontwarn org.w3c.dom.bootstrap.DOMImplementationRegistry
+-keepattributes *Annotation*,EnclosingMethod,Signature
+-keepnames class com.fasterxml.jackson.** { *; }
+ -dontwarn com.fasterxml.jackson.databind.**
+ -keep class org.codehaus.** { *; }
+ -keepclassmembers public final enum org.codehaus.jackson.annotate.JsonAutoDetect$Visibility {
+ public static final org.codehaus.jackson.annotate.JsonAutoDetect$Visibility *; }
+-keep class org.msgpack.core.**{ *; }
+-dontwarn org.msgpack.core.**
\ No newline at end of file
diff --git a/app/src/androidTest/java/com/example/myapplication/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/example/myapplication/ExampleInstrumentedTest.java
new file mode 100644
index 00000000..af713468
--- /dev/null
+++ b/app/src/androidTest/java/com/example/myapplication/ExampleInstrumentedTest.java
@@ -0,0 +1,27 @@
+package com.example.myapplication;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ assertEquals("com.example.myapplication", appContext.getPackageName());
+ }
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..6713262e
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/assets/bridgefy-license.txt b/app/src/main/assets/bridgefy-license.txt
new file mode 100644
index 00000000..c52a67ad
--- /dev/null
+++ b/app/src/main/assets/bridgefy-license.txt
@@ -0,0 +1 @@
+gqRkYXRh3ABLMjAyMC0wMi0yMVQxOTo1Nzo1NC43OTFafDIwMjAtMDQtMDNUMTk6NTg6MDAuMzQyWnxjb20uZXhhbXBsZS5teWFwcGxpY2F0aW9uqXNpZ25hdHVyZdwBAAYOzN8YEcz4fUTMuMyib8yTzMVXzN3MxszsZcyyzODMoczKJi0AzO3MucyZzMFGMEbMrszeT8y0DxnMusyEzK/Mv8y+zKjM7syrzNrM+czxRghyzPIDzLHMgMyAzOFzzLrM92rMyxvM7GUreg3MnyhmSsyxzMbMqU1hLhnMj03MnW/M6EPMssybzJgTfV/M025OQzoVzNQ+zIsWB3fM3CfMng8hzMQSzNh5zPMgc8yNzOjMy3x7AxTM18y4zMPMoFZ4zPTMzgFOzPkjzPVYzLzMtibM3syuRczFYszJCszdzMfMwFxWzJzMrcy4zOYJzMYPzKvM1inMohjMtcz+zLEYzJjM6XhFBsyuzKXMrwTMsjVazLQRang/QE/MsMzPzPvMzSfMyFnM+cyVD0jMhsytR8ybP8y2GszazKnM+MzzzLHM0Rt9JBBrC8y9zJ0yW8zyZszlzJBfzJxKSzICEm4fMX1uYDQ4zKnMwnHM5w5yzI86WAnM+m5dzPLMp8yi
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/BridegfyVictim/BridgefyActivity.kt b/app/src/main/java/com/example/myapplication/BridegfyVictim/BridgefyActivity.kt
new file mode 100644
index 00000000..36378c8f
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/BridgefyActivity.kt
@@ -0,0 +1,99 @@
+package com.example.myapplication.BridegfyVictim
+
+import android.Manifest
+import android.content.pm.PackageManager
+import android.os.Bundle
+import android.os.PersistableBundle
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.app.ActivityCompat
+import androidx.core.content.ContextCompat
+import androidx.core.app.ComponentActivity.ExtraData
+import androidx.core.content.ContextCompat.getSystemService
+import android.icu.lang.UCharacter.GraphemeClusterBreak.T
+import androidx.navigation.findNavController
+import com.example.myapplication.BridegfyVictim.Dao.AppDatabaseInstance
+import com.example.myapplication.R
+import kotlinx.coroutines.runBlocking
+
+class BridgefyActivity : AppCompatActivity() {
+
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_bridgefy)
+ // Here, thisActivity is the current activity
+ if (ContextCompat.checkSelfPermission(this,
+ Manifest.permission.ACCESS_COARSE_LOCATION)
+ != PackageManager.PERMISSION_GRANTED) {
+
+ // Permission is not granted
+ // Should we show an explanation?
+ if (ActivityCompat.shouldShowRequestPermissionRationale(this,
+ Manifest.permission.READ_CONTACTS)) {
+ // Show an explanation to the user *asynchronously* -- don't block
+ // this thread waiting for the user's response! After the user
+ // sees the explanation, try again to request the permission.
+ } else {
+ // No explanation needed, we can request the permission.
+ ActivityCompat.requestPermissions(this,
+ arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION),
+ 100)
+
+ // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
+ // app-defined int constant. The callback method gets the
+ // result of the request.
+ }
+ } else {
+ // Permission has already been granted
+ }
+ checkForSmsPermission()
+ val userDao = AppDatabaseInstance.getDb(this).userDao()
+ runBlocking {
+ val currentUser = userDao.getCurrentUser()
+ if (currentUser.isNull()) { //no user instance found
+ findNavController(R.id.nav_host_fragment).navigate(R.id.loginFragment)
+ } else {
+ findNavController(R.id.nav_host_fragment).navigate(R.id.mainFragment)
+ }
+ }
+ }
+
+ private fun checkForSmsPermission() {
+ if (ActivityCompat.checkSelfPermission(this,
+ Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) {
+ // Permission not yet granted. Use requestPermissions().
+ // MY_PERMISSIONS_REQUEST_SEND_SMS is an
+ // app-defined int constant. The callback method gets the
+ // result of the request.
+ ActivityCompat.requestPermissions(this,
+ arrayOf(Manifest.permission.SEND_SMS),
+ 101)
+ } else {
+ // Permission already granted. Enable the SMS button.
+ }
+ }
+
+ override fun onRequestPermissionsResult(requestCode: Int,
+ permissions: Array, grantResults: IntArray) {
+ when (requestCode) {
+ 100 -> {
+ // If request is cancelled, the result arrays are empty.
+ if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
+ // permission was granted, yay! Do the
+ // contacts-related task you need to do.
+ } else {
+ // permission denied, boo! Disable the
+ // functionality that depends on this permission.
+ }
+ return
+ }
+
+ // Add other 'when' lines to check for other
+ // permissions this app might request.
+ else -> {
+ // Ignore all other requests.
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/myapplication/BridegfyVictim/CommonViewModel.kt b/app/src/main/java/com/example/myapplication/BridegfyVictim/CommonViewModel.kt
new file mode 100644
index 00000000..9f32938a
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/CommonViewModel.kt
@@ -0,0 +1,18 @@
+package com.example.myapplication.BridegfyVictim
+
+import androidx.lifecycle.ViewModel
+import com.bridgefy.sdk.client.Bridgefy
+import com.bridgefy.sdk.client.BridgefyClient
+import com.example.myapplication.BridegfyVictim.model.DisasterResources
+
+class CommonViewModel: ViewModel() {
+
+ companion object {
+ fun broadcastMessage(disasterResources: DisasterResources) {
+ val json = NetworkUtil.gson.toJson(disasterResources)
+ val data = HashMap()
+ data["data"] = json
+ Bridgefy.sendBroadcastMessage(data)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/BridegfyVictim/Dao/AppDatabase.kt b/app/src/main/java/com/example/myapplication/BridegfyVictim/Dao/AppDatabase.kt
new file mode 100644
index 00000000..6a72d70a
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/Dao/AppDatabase.kt
@@ -0,0 +1,30 @@
+package com.example.myapplication.BridegfyVictim.Dao
+
+import android.content.Context
+import androidx.room.Database
+import androidx.room.Room
+import androidx.room.RoomDatabase
+import androidx.room.TypeConverters
+import com.example.myapplication.BridegfyVictim.Dao.food.FoodServiceDao
+import com.example.myapplication.BridegfyVictim.Dao.food.FoodServiceEntity
+import com.example.myapplication.BridegfyVictim.Dao.user.UserDao
+import com.example.myapplication.BridegfyVictim.Dao.user.UserDetail
+
+object AppDatabaseInstance {
+ fun getDb(context: Context) : AppDatabase {
+ return Room.databaseBuilder(
+ context,
+ AppDatabase::class.java, "database-name"
+ )
+ .allowMainThreadQueries()
+ .fallbackToDestructiveMigration()
+ .build()
+ }
+}
+
+@Database(entities = [FoodServiceEntity::class, UserDetail::class], version = 2)
+@TypeConverters(UserDetail.EnumConverters::class)
+abstract class AppDatabase : RoomDatabase() {
+ abstract fun foodServiceDao(): FoodServiceDao
+ abstract fun userDao(): UserDao
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/BridegfyVictim/Dao/food/FoodServiceDao.kt b/app/src/main/java/com/example/myapplication/BridegfyVictim/Dao/food/FoodServiceDao.kt
new file mode 100644
index 00000000..327fb488
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/Dao/food/FoodServiceDao.kt
@@ -0,0 +1,15 @@
+package com.example.myapplication.BridegfyVictim.Dao.food
+
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.Query
+
+@Dao
+interface FoodServiceDao {
+
+ @Query("SELECT * FROM FoodServiceEntity")
+ fun getSavedFoodServices(): List
+
+ @Insert
+ fun insertFoodService(foodServiceEntity: FoodServiceEntity)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/BridegfyVictim/Dao/food/FoodServiceEntity.kt b/app/src/main/java/com/example/myapplication/BridegfyVictim/Dao/food/FoodServiceEntity.kt
new file mode 100644
index 00000000..f2242a99
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/Dao/food/FoodServiceEntity.kt
@@ -0,0 +1,13 @@
+package com.example.myapplication.BridegfyVictim.Dao.food
+
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity
+data class FoodServiceEntity(
+ @PrimaryKey(autoGenerate = true) val _id: Int = 0,
+ val longitude: Double,
+ val latitude: Double,
+ val message: String
+) {
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/BridegfyVictim/Dao/user/UserDao.kt b/app/src/main/java/com/example/myapplication/BridegfyVictim/Dao/user/UserDao.kt
new file mode 100644
index 00000000..e05beb57
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/Dao/user/UserDao.kt
@@ -0,0 +1,14 @@
+package com.example.myapplication.BridegfyVictim.Dao.user
+
+import androidx.room.*
+
+@Dao
+interface UserDao {
+
+ @Query("SELECT * FROM UserDetail WHERE _userId=0")
+ suspend fun getCurrentUser(): UserDetail?
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ suspend fun updateUser(userDetail: UserDetail)
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/BridegfyVictim/Dao/user/UserDetail.kt b/app/src/main/java/com/example/myapplication/BridegfyVictim/Dao/user/UserDetail.kt
new file mode 100644
index 00000000..73010a81
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/Dao/user/UserDetail.kt
@@ -0,0 +1,45 @@
+package com.example.myapplication.BridegfyVictim.Dao.user
+
+import androidx.room.Embedded
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import androidx.room.TypeConverter
+
+@Entity
+data class UserDetail (
+ @PrimaryKey(autoGenerate = false) val _userId: Int = 0,
+ val userName: String,
+ val phoneNumber: Long,
+ val gender: Gender = Gender.NONE,
+ @Embedded val emergencyContact: EmergencyContact
+ ) {
+ enum class Gender {
+ MALE, FEMALE, NONE
+ }
+
+ data class EmergencyContact(
+ val contact1: Long,
+ val contact2: Long
+ )
+
+ class EnumConverters() {
+ @TypeConverter
+ fun fromGenderToInt(gender: Gender): Int {
+ return when (gender) {
+ Gender.MALE -> 1
+ Gender.FEMALE -> 2
+ Gender.NONE -> 3
+ }
+ }
+
+ @TypeConverter
+ fun fromIntToGender(int: Int): Gender{
+ return when (int) {
+ 1 -> Gender.MALE
+ 2 ->Gender.FEMALE
+ else -> Gender.NONE
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/BridegfyVictim/Repo/SmsRepo.kt b/app/src/main/java/com/example/myapplication/BridegfyVictim/Repo/SmsRepo.kt
new file mode 100644
index 00000000..cd69ce62
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/Repo/SmsRepo.kt
@@ -0,0 +1,28 @@
+package com.example.myapplication.BridegfyVictim.Repo
+
+import com.twilio.Twilio
+
+import com.twilio.rest.api.v2010.account.Message
+import com.twilio.type.PhoneNumber
+
+class SmsRepo {
+
+}
+
+object SmsSender {
+ // Find your Account Sid and Auth Token at twilio.com/console
+ val ACCOUNT_SID = "AC455f51a42329ffcb2e4f6b438b9082df"
+ val AUTH_TOKEN = "00cea12e845806de3578cd5390c7015d"
+
+ fun sendSms() {
+ Twilio.init(ACCOUNT_SID, AUTH_TOKEN)
+
+ val message = Message
+ .creator(PhoneNumber("+917010065028"), // to
+ PhoneNumber("+12568040107"), // from
+ "Where's Wallace?")
+ .create()
+
+ println(message.status)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/BridegfyVictim/SettingsFragment.kt b/app/src/main/java/com/example/myapplication/BridegfyVictim/SettingsFragment.kt
new file mode 100644
index 00000000..bca84a44
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/SettingsFragment.kt
@@ -0,0 +1,97 @@
+package com.example.myapplication.BridegfyVictim
+
+import android.content.Context
+import android.content.SharedPreferences
+import android.net.Uri
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProviders
+import com.example.myapplication.BridegfyVictim.model.DisasterResources
+import com.example.myapplication.BridegfyVictim.model.NativeLocationFragment
+import com.example.myapplication.BridegfyVictim.model.OneOf
+
+import com.example.myapplication.R
+import kotlinx.android.synthetic.main.activity_food.*
+import kotlinx.android.synthetic.main.fragment_settings.*
+
+class SettingsFragment : NativeLocationFragment() {
+
+ lateinit var sharedPreferences: SharedPreferences
+ lateinit var viewModel: CommonViewModel
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ sharedPreferences = requireContext().getSharedPreferences("Settings", Context.MODE_PRIVATE)
+ viewModel = activity?.run {
+ ViewModelProviders.of(this)[CommonViewModel::class.java]
+ } ?: throw Exception("Invalid Activity")
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ // Inflate the layout for this fragment
+ return inflater.inflate(R.layout.fragment_settings, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ switch1.isChecked = sharedPreferences.getBoolean(FOOD_AVAILABLE, false)
+ switch2.isChecked = sharedPreferences.getBoolean(MEDICINE_AVAILABLE, false)
+
+ switch3.isChecked = sharedPreferences.getBoolean(ALERT, false)
+
+ switch1.setOnClickListener {
+ sharedPreferences.edit()
+ .putBoolean(FOOD_AVAILABLE, switch1.isChecked)
+ .apply()
+ if (switch1.isChecked) {
+ detectLocation()
+ }
+ }
+
+ switch2.setOnClickListener {
+ sharedPreferences.edit()
+ .putBoolean(FOOD_AVAILABLE, switch2.isChecked)
+ .apply()
+ }
+
+ switch3.setOnClickListener {
+ sharedPreferences.edit()
+ .putBoolean(ALERT, switch3.isChecked)
+ .apply()
+ }
+ }
+
+ private fun detectLocation() {
+ updateLocation()
+ locationLiveData.observe(this@SettingsFragment, Observer { location ->
+ when (location) {
+ is OneOf.Success -> {
+ val sendRequest = DisasterResources.FoodService(
+ latitude = location.a.latitude,
+ longitude = location.a.longitude,
+ numOfPeople = 3,
+ deviceId = getDeviceId(requireContext())
+ )
+ CommonViewModel.broadcastMessage(sendRequest)
+ locationLiveData.removeObservers(this)
+ }
+ is OneOf.Failure -> {
+ Toast.makeText(requireContext(), "failed : ${location.b}", Toast.LENGTH_SHORT)
+ .show()
+ }
+ }
+ })
+ }
+
+ companion object {
+ const val FOOD_AVAILABLE = "food_available"
+ const val MEDICINE_AVAILABLE = "medicine_available"
+ const val ALERT = "alert"
+ }
+}
diff --git a/app/src/main/java/com/example/myapplication/BridegfyVictim/Util.kt b/app/src/main/java/com/example/myapplication/BridegfyVictim/Util.kt
new file mode 100644
index 00000000..81fcfedd
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/Util.kt
@@ -0,0 +1,69 @@
+package com.example.myapplication.BridegfyVictim
+
+import android.content.Context
+import android.content.Context.CONNECTIVITY_SERVICE
+import android.net.ConnectivityManager
+import android.provider.Settings
+import android.telephony.TelephonyManager
+import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationManagerCompat
+import com.example.myapplication.BridegfyVictim.model.DisasterResources
+import com.example.myapplication.R
+import com.google.gson.Gson
+
+fun isNetworkAvailable(context: Context): Boolean {
+ val tel = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ return !(tel.networkOperator != null && tel.networkOperator == "")
+}
+
+fun isInternetAvailable(context: Context): Boolean {
+ val cm = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
+ val netInfo = cm.activeNetworkInfo
+ return netInfo != null && netInfo.isAvailable
+}
+
+fun showNotification(context: Context, disasterResources: DisasterResources) {
+
+ val builder = NotificationCompat.Builder(context, "100")
+ .setSmallIcon(R.drawable.ic_launcher_foreground)
+ .setContentTitle(
+ getTitle(disasterResources)
+ )
+ .setContentText(getContent(disasterResources))
+ .setPriority(NotificationCompat.PRIORITY_DEFAULT)
+
+ with(NotificationManagerCompat.from(context)) {
+ // notificationId is a unique int for each notification that you must define
+ notify(1, builder.build())
+ }
+}
+
+fun getContent(disasterResources: DisasterResources): String {
+ return when (disasterResources) {
+ is DisasterResources.SendEmergencyMessage -> "Send sms"
+ is DisasterResources.FoodRequest -> "Required ${disasterResources.requiredFood} at ${disasterResources.area}"
+ is DisasterResources.Medication -> " Medication Required ${disasterResources.requiredMedication} at ${disasterResources.area}"
+ is DisasterResources.FoodService -> ""
+ }
+}
+
+fun getTitle(disasterResources: DisasterResources): String {
+ return when (disasterResources) {
+ is DisasterResources.SendEmergencyMessage -> "Send emergency contact"
+ is DisasterResources.FoodRequest -> "Food Request"
+ is DisasterResources.Medication -> " Medication Request"
+ is DisasterResources.FoodService -> ""
+ }
+}
+
+
+fun getDeviceId(context: Context): String {
+ return Settings.Secure.getString(context.contentResolver,
+ Settings.Secure.ANDROID_ID)
+}
+
+object NetworkUtil {
+ val gson = Gson()
+}
+
+fun Any?.isNull(): Boolean = this == null
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/BridegfyVictim/model/DisasterResources.kt b/app/src/main/java/com/example/myapplication/BridegfyVictim/model/DisasterResources.kt
new file mode 100644
index 00000000..41000f76
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/model/DisasterResources.kt
@@ -0,0 +1,49 @@
+package com.example.myapplication.BridegfyVictim.model
+
+import com.bridgefy.sdk.client.Bridgefy
+
+sealed class DisasterResources(
+ val userDeviceId: String
+) {
+
+ data class SendEmergencyMessage(
+ val emergencyContact: Long,
+ val message: String,
+ val deviceId: String,
+ private val tag: String = EMERGENCY_CONTACT_TAG
+ ): DisasterResources(deviceId)
+
+ data class FoodRequest(
+ val latitude: Double?,
+ val longitude: Double?,
+ val area: String,
+ val numOfPeople: Int,
+ val requiredFood: String,
+ val deviceId: String,
+ private val tag: String = FOOD_REQUEST
+ ) : DisasterResources(deviceId)
+
+ data class Medication(
+ val latitude: Double?,
+ val longitude: Double?,
+ val area: String,
+ val requiredMedication: String,
+ val deviceId: String,
+ private val tag: String = MEDICATION
+ ) : DisasterResources(deviceId)
+
+ data class FoodService(
+ val latitude: Double,
+ val longitude: Double,
+ val numOfPeople: Int,
+ val deviceId: String,
+ private val tag: String = FOOD_SERVICE
+ ) : DisasterResources(deviceId)
+
+ companion object {
+ const val EMERGENCY_CONTACT_TAG = "emergency_tag"
+ const val FOOD_REQUEST = "food_request"
+ const val MEDICATION = "MedicationFragment"
+ const val FOOD_SERVICE = "food_service"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/BridegfyVictim/model/Failure.kt b/app/src/main/java/com/example/myapplication/BridegfyVictim/model/Failure.kt
new file mode 100644
index 00000000..e127ea49
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/model/Failure.kt
@@ -0,0 +1,56 @@
+package com.example.myapplication.BridegfyVictim.model
+
+sealed class Failure {
+
+ /**
+ * class : UnknownFailure
+ * this type of failure is used when the cause of error is unknown
+ * and this failure also represents the generic failure
+ * */
+ object UnKnownFailure : Failure()
+
+ /**
+ * The request was valid, but the server is refusing action.
+ * The user might not have the necessary permissions for a resource,
+ * or may need an account of some sort. This code is also typically used
+ * if the request provided authentication via the WWW-Authenticate header field, but the server did not accept that authentication.
+ * */
+ object ForbiddenFailure : Failure()
+
+ /**
+ The server timed out waiting for the request. According to HTTP specifications: "The client did not produce a request
+ within the time that the server was prepared to wait. The client MAY repeat the request without modifications at any later time.
+ */
+ object RequestTimeoutFailure : Failure()
+
+ /**
+ The requested resource could not be found but may be available in the future. Subsequent requests by the client are permissible.
+ */
+ object NotFoundFailure : Failure()
+
+ /**
+ * This failure represents a generic network failure. for eg: this failure can be used in
+ * case of no internet connection
+ */
+
+ object NetworkFailure : Failure()
+
+ object DatabaseFailure : Failure()
+
+ /**
+ * use this failure if it is not possible to fetch location. if both fetch from network and database is unsuccessful
+ * */
+
+
+ sealed class LocationFailure : Failure() {
+
+ object LocationPermissionDeniedFailure : LocationFailure()
+
+ object LocationNotEnabledFailure : LocationFailure()
+
+ object NoSavedLocationFailure : LocationFailure()
+
+ object UnknownLocationFailure : LocationFailure()
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/BridegfyVictim/model/NativeLocationFragment.kt b/app/src/main/java/com/example/myapplication/BridegfyVictim/model/NativeLocationFragment.kt
new file mode 100644
index 00000000..fd845d3a
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/model/NativeLocationFragment.kt
@@ -0,0 +1,245 @@
+package com.example.myapplication.BridegfyVictim.model
+
+import android.Manifest
+import android.app.Activity
+import android.content.Intent
+import android.content.IntentSender
+import android.content.pm.PackageManager
+import android.location.Location
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.core.content.ContextCompat
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.MutableLiveData
+import com.example.myapplication.R
+import com.google.android.gms.common.api.ResolvableApiException
+import com.google.android.gms.location.*
+
+/**
+ * This Fragment represents the base Location class, any fragment which needs access to the
+ * native location feature will extend from this Fragment
+ * */
+open class NativeLocationFragment : Fragment() {
+
+ private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
+
+ /**
+ * [locationLiveData] will expose the current location obtained from the device,
+ * [OneOf.Success] represents the location has been successfully obtained
+ * [OneOf.Failure] is used if the location cannot be obtained due to lack of permission
+ * or required setting is not available/enabled in the device
+ * */
+ val locationLiveData: MutableLiveData> =
+ MutableLiveData()
+
+ private val locationRequest = LocationRequest.create().apply {
+ interval = 10
+ priority = LocationRequest.PRIORITY_HIGH_ACCURACY
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ fusedLocationProviderClient =
+ LocationServices.getFusedLocationProviderClient(requireContext())
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ // Inflate the layout for this fragment
+ return inflater.inflate(R.layout.fragment_native_location, container, false)
+ }
+
+ /**
+ *call this method to update the location value in [locationLiveData].The execution is as follows,
+ * [isLocationPermissionGranted] -> [checkRequiredLocationSettings] (if success) -> [fetchLastKnownLocation]
+ * (if failure) -> open settings screen to enable location
+ */
+ fun updateLocation() {
+
+ if (isLocationPermissionGranted()) {
+ checkRequiredLocationSettings(
+ successListener = {
+ fetchLastKnownLocation()
+
+ },
+ failureListener = { exception ->
+ if (exception is ResolvableApiException) {
+ // Location settings are not satisfied
+ try {
+ // Show the dialog by calling startIntentSenderForResult(),
+ // and check the result in onActivityResult().
+ startIntentSenderForResult(
+ exception.resolution.intentSender,
+ REQUEST_CHECK_SETTINGS,
+ null,
+ 0,
+ 0,
+ 0,
+ null
+ )
+ } catch (sendEx: IntentSender.SendIntentException) {
+ //Ignore
+ }
+ }
+ }
+ )
+ } else {
+ requestLocationPermission()
+ }
+ }
+
+ /**
+ * check if the location permission is granted or not
+ */
+ private fun isLocationPermissionGranted(): Boolean {
+ return ContextCompat.checkSelfPermission(
+ requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION
+ ) == PackageManager.PERMISSION_GRANTED
+ }
+
+ /**
+ * request the runtime permission for location, for devices above android 6
+ */
+ private fun requestLocationPermission() {
+ requestPermissions(
+ arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
+ LOCATION_PERMISSION_CHECK
+ )
+ }
+
+ /**
+ * check if the current devices settings match the required settings needed to obtain the location
+ * [successListener] is a lambda with a param [LocationSettingsResponse] will be executed if the current settings
+ * match the required settings
+ * [failureListener] will be invoked if the current settings and the required settings doesn't match
+ */
+ private fun checkRequiredLocationSettings(
+ successListener: (LocationSettingsResponse) -> Unit,
+ failureListener: (Exception) -> Unit
+ ) {
+ val locationSettingRequest = LocationSettingsRequest.Builder()
+ .addLocationRequest(locationRequest)
+ .build()
+
+ val settingsClient = LocationServices.getSettingsClient(requireContext())
+
+ settingsClient.checkLocationSettings(locationSettingRequest)
+ .addOnSuccessListener(successListener)
+ .addOnFailureListener(failureListener)
+ }
+
+ /**
+ * this method is used to post the last know location using [fusedLocationProviderClient.lastLocation]
+ * returns [OneOf.Success] if the location value is not null and [OneOf.Failure] if the operation fails
+ * if the [Location] value returned is null, a new locationUpdateRequest is subscribed by calling [requestNewLocationUpdates]
+ */
+ private fun fetchLastKnownLocation() {
+ fusedLocationProviderClient.lastLocation
+ .addOnSuccessListener { location: Location? ->
+ if (location != null) {
+ locationLiveData.postValue(
+ OneOf.Success(
+ location,
+ OneOf.Success.DataState.FRESH_DATA
+ )
+ )
+ } else {
+ requestNewLocationUpdates()
+ }
+ }
+ .addOnFailureListener {
+ locationLiveData.postValue(
+ OneOf.Failure(
+ Failure.LocationFailure.UnknownLocationFailure
+ )
+ )
+ }
+ }
+
+ /**
+ * call this method if the [fusedLocationProviderClient.lastLocation] returns null.
+ * this method will setup a new location update callback with single update for location.
+ */
+ private fun requestNewLocationUpdates() {
+ fusedLocationProviderClient.requestLocationUpdates(
+ locationRequest.apply {
+ numUpdates = 1
+ },
+ object : LocationCallback() {
+ override fun onLocationResult(locations: LocationResult?) {
+ super.onLocationResult(locations)
+ locations?.let {
+ locationLiveData.postValue(
+ OneOf.Success(
+ it.lastLocation,
+ OneOf.Success.DataState.FRESH_DATA
+ )
+ )
+ } ?: run {
+ // this block is executed if the location is null
+ locationLiveData.postValue(
+ OneOf.Failure(
+ Failure.LocationFailure.UnknownLocationFailure
+ )
+ )
+ }
+ }
+ },
+ null
+ )
+
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+
+ when (requestCode) {
+ REQUEST_CHECK_SETTINGS -> {
+ if (resultCode == Activity.RESULT_OK) {
+ //the users has changed the current location settings to meet the requirements, retry getting location
+ updateLocation()
+ } else {
+ //the user failed to update the location settings to meet the requirement
+ locationLiveData.postValue(
+ OneOf.Failure(
+ Failure.LocationFailure.LocationNotEnabledFailure
+ )
+ )
+ }
+ }
+ }
+ }
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array,
+ grantResults: IntArray
+ ) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+
+ when (requestCode) {
+ LOCATION_PERMISSION_CHECK -> {
+ if (grantResults.isNotEmpty() and (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
+ //the user has granted the location permission, hence retry to obtain the current location
+ updateLocation()
+ } else {
+ //the user has denied the location permission
+ locationLiveData.postValue(
+ OneOf.Failure(
+ Failure.LocationFailure.LocationPermissionDeniedFailure
+ )
+ )
+ }
+ }
+ }
+ }
+
+ companion object {
+ private const val REQUEST_CHECK_SETTINGS = 100
+ private const val LOCATION_PERMISSION_CHECK = 101
+ }
+}
+
diff --git a/app/src/main/java/com/example/myapplication/BridegfyVictim/model/OneOf.kt b/app/src/main/java/com/example/myapplication/BridegfyVictim/model/OneOf.kt
new file mode 100644
index 00000000..b90f51ae
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/model/OneOf.kt
@@ -0,0 +1,44 @@
+package com.example.myapplication.BridegfyVictim.model
+
+/**
+ * Represents a value of one of two possible types (a disjoint union).
+ * Instances of [OneOf] are either an instance of [Success] or [Failure].
+ *
+ * @see Success
+ * @see Failure
+ */
+sealed class OneOf {
+ /** * Represents the success side of [OneOf] class which by convention is a "Failure".
+ * @param S represents the data type to be returned by the successful response
+ * @param dataState represents the type of data loaded into the success response,
+ * [DataState.CACHED_DATA] represents cached data and
+ * [DataState.FRESH_DATA] represents a newly loaded data
+ * */
+ data class Success(
+ val a: S,
+ val dataState: DataState
+ ) : OneOf() {
+ enum class DataState {
+ FRESH_DATA, CACHED_DATA
+ }
+ }
+
+ /** * Represents the failure side of [OneOf] class which by convention is a "Failure". */
+ data class Failure(val b: F) : OneOf()
+
+ val isFailure get() = this is Failure
+ val isSuccess get() = this is Success
+
+ fun success(a: S, dataState: Success.DataState) = Success(a, dataState)
+ fun failure(b: F) = Failure(b)
+
+ suspend fun oneOf(fnS: suspend (S) -> Any, fnF: suspend (F) -> Any): Any =
+ when (this) {
+ is Success -> fnS(a)
+ is Failure -> fnF(b)
+ }
+}
+
+fun ((A) -> B).c(f: (B) -> C): (A) -> C = {
+ f(this(it))
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/EmergencyFragment.kt b/app/src/main/java/com/example/myapplication/EmergencyFragment.kt
new file mode 100644
index 00000000..ccc35c19
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/EmergencyFragment.kt
@@ -0,0 +1,99 @@
+package com.example.myapplication
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProviders
+import androidx.navigation.fragment.findNavController
+import com.example.myapplication.BridegfyVictim.CommonViewModel
+import com.example.myapplication.BridegfyVictim.CommonViewModel.Companion.broadcastMessage
+import com.example.myapplication.BridegfyVictim.Dao.AppDatabaseInstance
+import com.example.myapplication.BridegfyVictim.getDeviceId
+import com.example.myapplication.BridegfyVictim.model.DisasterResources
+import com.example.myapplication.BridegfyVictim.model.NativeLocationFragment
+import com.example.myapplication.BridegfyVictim.model.OneOf
+import kotlinx.android.synthetic.main.activity_emergencyactivity.*
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+class EmergencyFragment : NativeLocationFragment() {
+
+ lateinit var viewModel: CommonViewModel
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ viewModel = activity?.run {
+ ViewModelProviders.of(this)[CommonViewModel::class.java]
+ } ?: throw Exception("Invalid Activity")
+ return inflater.inflate(R.layout.activity_emergencyactivity, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ detectLocation()
+ default_button.setOnClickListener {
+ message_button.isChecked = false
+
+ }
+
+ message_button.setOnClickListener {
+ default_button.isChecked = false
+ }
+
+ back.setOnClickListener {
+ findNavController().popBackStack()
+ }
+
+ broadcast.setOnClickListener {
+ CoroutineScope(Dispatchers.IO).launch {
+ val userDao = AppDatabaseInstance.getDb(requireContext()).userDao()
+ val message = if (default_button.isActivated) {
+ default_sos.text.toString()
+ } else {
+ message.editableText.toString().trim()
+ }
+
+ val contact1 = DisasterResources.SendEmergencyMessage(
+ emergencyContact = userDao.getCurrentUser()?.emergencyContact?.contact1 ?: 8788043980,
+ message = message,
+ deviceId = getDeviceId(requireContext())
+ )
+ val contact2 = DisasterResources.SendEmergencyMessage(
+ emergencyContact = userDao.getCurrentUser()?.emergencyContact?.contact2 ?: 7010065028,
+ message = message,
+ deviceId = getDeviceId(requireContext())
+ )
+ broadcastMessage(contact1)
+ broadcastMessage(contact2)
+
+ withContext(Dispatchers.Main){
+ Toast.makeText(requireContext(), "Message sent to nearby" +
+ " ${(this@EmergencyFragment.activity?.application as MyApplication).availableDevices.size}",
+ Toast.LENGTH_SHORT).show()
+ this@EmergencyFragment.findNavController().popBackStack()
+ }
+ }
+ }
+ }
+
+ private fun detectLocation() {
+ updateLocation()
+ locationLiveData.observe(this, Observer { location ->
+ when (location) {
+ is OneOf.Success -> {
+ default_sos.text = "SOS, I am stuck and need help. I am here at ${location.a.latitude}, ${ location.a.longitude}"
+ locationLiveData.removeObservers(this)
+ }
+ is OneOf.Failure -> {
+ Toast.makeText(requireContext(), "failed : ${location.b}", Toast.LENGTH_SHORT)
+ .show()
+ }
+ }
+ })
+ }
+}
diff --git a/app/src/main/java/com/example/myapplication/FoodFragment.kt b/app/src/main/java/com/example/myapplication/FoodFragment.kt
new file mode 100644
index 00000000..3efa6926
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/FoodFragment.kt
@@ -0,0 +1,65 @@
+package com.example.myapplication
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.ViewModelProviders
+import com.example.myapplication.BridegfyVictim.CommonViewModel
+import com.example.myapplication.BridegfyVictim.CommonViewModel.Companion.broadcastMessage
+import com.example.myapplication.BridegfyVictim.getDeviceId
+import com.example.myapplication.BridegfyVictim.model.DisasterResources
+import com.example.myapplication.BridegfyVictim.model.NativeLocationFragment
+import com.example.myapplication.BridegfyVictim.model.OneOf
+import kotlinx.android.synthetic.main.activity_food.*
+
+class FoodFragment : NativeLocationFragment() {
+
+ private lateinit var viewModel: CommonViewModel
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ viewModel = activity?.run {
+ ViewModelProviders.of(this)[CommonViewModel::class.java]
+ } ?: throw Exception("Invalid Activity")
+ return inflater.inflate(R.layout.activity_food, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ send_food_request.setOnClickListener {
+ detectLocation()
+ }
+ }
+
+ private fun detectLocation() {
+ updateLocation()
+ locationLiveData.observe(this@FoodFragment, Observer { location ->
+ when (location) {
+ is OneOf.Success -> {
+ val area = area_text_box.editableText.toString().trim()
+ val numberOfPeople = no_of_people_text_box.editableText.toString().trim()
+ val message = message_box.editableText.toString().trim()
+ val sendRequest = DisasterResources.FoodRequest(
+ latitude = location.a.latitude,
+ longitude = location.a.longitude,
+ area = area,
+ numOfPeople = numberOfPeople.toInt(),
+ requiredFood = message,
+ deviceId = getDeviceId(requireContext())
+ )
+ broadcastMessage(sendRequest)
+ locationLiveData.removeObservers(this)
+ }
+ is OneOf.Failure -> {
+ Toast.makeText(requireContext(), "failed : ${location.b}", Toast.LENGTH_SHORT)
+ .show()
+ }
+ }
+ })
+ }
+
+
+}
diff --git a/app/src/main/java/com/example/myapplication/MainFragment.kt b/app/src/main/java/com/example/myapplication/MainFragment.kt
new file mode 100644
index 00000000..31091f08
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/MainFragment.kt
@@ -0,0 +1,38 @@
+package com.example.myapplication
+
+import android.content.Intent
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.fragment.app.Fragment
+import androidx.navigation.fragment.findNavController
+import kotlinx.android.synthetic.main.activity_main.*
+
+class MainFragment : Fragment() {
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.activity_main, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ ripple.startRippleAnimation()
+ ripple_img.setOnClickListener {
+ findNavController().navigate(R.id.action_mainFragment_to_emergencyFragment)
+ }
+
+// food_button.setOnClickListener {
+// findNavController().navigate(R.id.action_mainFragment_to_foodFragment)
+// }
+//
+// medication_button.setOnClickListener {
+// findNavController().navigate(R.id.action_mainFragment_to_medicationFragment)
+// }
+//
+// settings_icon.setOnClickListener {
+// findNavController().navigate(R.id.action_mainFragment_to_settingsFragment)
+// }
+ }
+}
diff --git a/app/src/main/java/com/example/myapplication/MedicationFragment.kt b/app/src/main/java/com/example/myapplication/MedicationFragment.kt
new file mode 100644
index 00000000..0401583d
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/MedicationFragment.kt
@@ -0,0 +1,43 @@
+package com.example.myapplication
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProviders
+import com.example.myapplication.BridegfyVictim.CommonViewModel
+import com.example.myapplication.BridegfyVictim.CommonViewModel.Companion.broadcastMessage
+import com.example.myapplication.BridegfyVictim.getDeviceId
+import com.example.myapplication.BridegfyVictim.model.DisasterResources
+import kotlinx.android.synthetic.main.activity_medication.*
+
+class MedicationFragment : Fragment() {
+
+ private lateinit var viewModel: CommonViewModel
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ viewModel = activity?.run {
+ ViewModelProviders.of(this)[CommonViewModel::class.java]
+ } ?: throw Exception("Invalid Activity")
+ return inflater.inflate(R.layout.activity_medication, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ send_medication_button.setOnClickListener {
+ val area = area_text_box.editableText.toString().trim()
+ val noOfPeople = no_of_people_text_box.editableText.toString().trim()
+ val message = message_box.editableText.toString().trim()
+
+ val medicationRequest = DisasterResources.Medication(
+ latitude = null,
+ longitude = null,
+ area = area,
+ requiredMedication = message,
+ deviceId = getDeviceId(requireContext())
+ )
+
+ broadcastMessage(medicationRequest)
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/myapplication/MyApplication.kt b/app/src/main/java/com/example/myapplication/MyApplication.kt
new file mode 100644
index 00000000..0a1c17ce
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/MyApplication.kt
@@ -0,0 +1,239 @@
+package com.example.myapplication
+
+import android.app.Application
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.content.Context
+import android.os.Build
+import android.util.Log
+import android.widget.Toast
+import com.bridgefy.sdk.client.*
+import com.example.myapplication.BridegfyVictim.model.DisasterResources
+import com.google.gson.JsonParser
+import com.bridgefy.sdk.client.Bridgefy
+import com.bridgefy.sdk.framework.exceptions.MessageException
+import java.util.*
+import android.telephony.SmsManager
+import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationManagerCompat
+import com.example.myapplication.BridegfyVictim.*
+import com.example.myapplication.BridegfyVictim.Dao.food.FoodServiceDao
+import com.example.myapplication.BridegfyVictim.Dao.AppDatabaseInstance
+import com.example.myapplication.BridegfyVictim.Dao.food.FoodServiceEntity
+
+class MyApplication : Application() {
+
+ val availableDevices: MutableList = mutableListOf()
+ lateinit var foodServiceDao: FoodServiceDao
+
+ val messageListener = object : MessageListener() {
+ override fun onMessageSent(messageId: String?) {
+ super.onMessageSent(messageId)
+ Log.v("bridgefy", messageId)
+ }
+
+ override fun onBroadcastMessageReceived(message: Message?) {
+ super.onBroadcastMessageReceived(message)
+ Log.v("Broadcast message", message?.toString())
+ handleMessage(message?.content?.get("data").toString())
+ }
+
+ override fun onMessageDataProgress(message: UUID?, progress: Long, fullSize: Long) {
+ super.onMessageDataProgress(message, progress, fullSize)
+ Log.v("progress", progress.toString())
+ }
+
+ override fun onMessageFailed(message: Message?, e: MessageException?) {
+ super.onMessageFailed(message, e)
+ Log.v("failed", e.toString())
+ }
+ }
+
+ val stateListener = object : StateListener() {
+
+ override fun onStarted() {
+ super.onStarted()
+ Log.v("bridgefy", "started")
+ Toast.makeText(this@MyApplication, "started", Toast.LENGTH_SHORT).show()
+ }
+
+ override fun onStartError(message: String?, errorCode: Int) {
+ super.onStartError(message, errorCode)
+ Log.v("bridgefy", "started_error")
+ }
+ override fun onDeviceConnected(device: Device?, session: Session?) {
+ super.onDeviceConnected(device, session)
+ Toast.makeText(applicationContext, "Device connected", Toast.LENGTH_SHORT).show()
+ if (applicationContext.getSharedPreferences("Settings", Context.MODE_PRIVATE).getBoolean(SettingsFragment.ALERT, false)) {
+ val builder = NotificationCompat.Builder(applicationContext, "100")
+ .setSmallIcon(R.drawable.ic_launcher_foreground)
+ .setContentTitle(
+ "Alert"
+ )
+ .setContentText("someone nearby needs help")
+ .setPriority(NotificationCompat.PRIORITY_DEFAULT)
+
+ with(NotificationManagerCompat.from(applicationContext)) {
+ // notificationId is a unique int for each notification that you must define
+ notify(1, builder.build())
+ }
+ }
+
+ availableDevices.add(device)
+ }
+
+ override fun onDeviceLost(device: Device?) {
+ super.onDeviceLost(device)
+ availableDevices.removeAll {
+ it?.userId == device?.userId
+ }
+ }
+ }
+
+ override fun onCreate() {
+ super.onCreate()
+
+ createNotificationChannel()
+ foodServiceDao = AppDatabaseInstance.getDb(applicationContext).foodServiceDao()
+ Bridgefy.initialize(applicationContext, "2b56623e-15a4-43ca-9050-eb6d8fd3edf7", object : RegistrationListener() {
+
+ override fun onRegistrationSuccessful(bridgefyClient: BridgefyClient) {
+ // BridgefyActivity is ready to start
+ val builder = Config.Builder()
+ builder.apply {
+ setEnergyProfile(BFEnergyProfile.HIGH_PERFORMANCE)
+ setEncryption(false)
+ }
+
+ Bridgefy.start(messageListener, stateListener, builder.build())
+ }
+
+ override fun onRegistrationFailed(errorCode: Int, message: String) {
+ // Something went wrong: handle error code, maybe print the message
+ Log.e("error", message)
+ }
+ }
+ )
+ }
+
+ private fun handleMessage(json: String) {
+ val messageTag = JsonParser().parse(json).asJsonObject.getAsJsonPrimitive("tag").asString
+ when (messageTag) {
+ DisasterResources.MEDICATION -> {
+ val medicationResources = NetworkUtil.gson.fromJson(json, DisasterResources.Medication::class.java)
+ handleMedicationRequest(medicationResources)
+ }
+
+ DisasterResources.FOOD_REQUEST -> {
+ val foodResources = NetworkUtil.gson.fromJson(json, DisasterResources.FoodRequest::class.java)
+ handleFoodRequest(foodResources)
+ }
+
+ DisasterResources.EMERGENCY_CONTACT_TAG -> {
+ val sendMessageResources = NetworkUtil.gson.fromJson(json, DisasterResources.SendEmergencyMessage::class.java)
+ handleEmergencyMessages(sendMessageResources)
+ }
+
+ DisasterResources.FOOD_SERVICE -> {
+ val foodService = NetworkUtil.gson.fromJson(json, DisasterResources.FoodService::class.java)
+ handleFoodService(foodService)
+ }
+ }
+ }
+
+ private fun handleFoodService(foodService: DisasterResources.FoodService) {
+ Toast.makeText(applicationContext, "$foodService", Toast.LENGTH_SHORT).show()
+ foodServiceDao.insertFoodService(
+ FoodServiceEntity(
+ longitude = foodService.longitude,
+ latitude = foodService.latitude,
+ message = foodService.numOfPeople.toString()
+ )
+ )
+ }
+
+ private fun handleFoodRequest(foodResources: DisasterResources.FoodRequest) {
+ Toast.makeText(this, foodResources.toString(), Toast.LENGTH_LONG).show()
+ if (doesProvideFood()) {
+ showNotification(applicationContext, foodResources)
+ } else {
+ if (isNetworkAvailable(applicationContext)) {
+ //Send Api Request
+ } else {
+ if (hasConnectedDevices() and (foodResources.userDeviceId != getDeviceId(applicationContext))) {
+ CommonViewModel.broadcastMessage(foodResources)
+ } else {
+ enqueueTask(foodResources)
+ }
+ }
+ }
+ }
+
+ private fun handleMedicationRequest(medication: DisasterResources.Medication) {
+ Toast.makeText(this, medication.toString(), Toast.LENGTH_LONG).show()
+ if (doesProvideMedication()) {
+ showNotification(applicationContext, medication)
+ } else {
+ if (isNetworkAvailable(applicationContext) and false) {
+ //Send Api Request
+ } else {
+ if (hasConnectedDevices() and (medication.userDeviceId != getDeviceId(applicationContext))) {
+ CommonViewModel.broadcastMessage(medication)
+ } else {
+ enqueueTask(medication)
+ }
+ }
+ }
+ }
+
+ private fun enqueueTask(disasterResoource: DisasterResources) {
+ // try to send it later
+ }
+
+
+ private fun handleEmergencyMessages(emergencyRequest: DisasterResources.SendEmergencyMessage) {
+ Toast.makeText(this, emergencyRequest.toString(), Toast.LENGTH_LONG).show()
+ smsSendMessage(emergencyRequest)
+ }
+
+ private fun smsSendMessage(emergencyRequest: DisasterResources.SendEmergencyMessage) {
+ try {
+ val smsManager = SmsManager.getDefault()
+ smsManager.sendTextMessage(emergencyRequest.emergencyContact.toString() , null, emergencyRequest.message, null, null)
+ Toast.makeText(applicationContext, "Message Sent",
+ Toast.LENGTH_LONG).show()
+ } catch (ex: Exception) {
+ Toast.makeText(applicationContext, ex.message.toString(),
+ Toast.LENGTH_LONG).show()
+ ex.printStackTrace()
+ }
+ }
+
+ private fun doesProvideFood(): Boolean {
+ return getSharedPreferences("Settings", Context.MODE_PRIVATE)
+ .getBoolean(SettingsFragment.FOOD_AVAILABLE, false)
+ }
+
+ private fun doesProvideMedication(): Boolean {
+ return getSharedPreferences("Settings", Context.MODE_PRIVATE)
+ .getBoolean(SettingsFragment.MEDICINE_AVAILABLE, false)
+ }
+
+ private fun createNotificationChannel() {
+ // Create the NotificationChannel, but only on API 26+ because
+ // the NotificationChannel class is new and not in the support library
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val name = getString(R.string.channel_name)
+ val importance = NotificationManager.IMPORTANCE_DEFAULT
+ val channel = NotificationChannel("100", name, importance)
+ // Register the channel with the system
+ val notificationManager: NotificationManager =
+ getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ notificationManager.createNotificationChannel(channel)
+ }
+ }
+
+ private fun hasConnectedDevices(): Boolean {
+ return availableDevices.size > 0
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/UtilitiesFragment.kt b/app/src/main/java/com/example/myapplication/UtilitiesFragment.kt
new file mode 100644
index 00000000..be99c9f3
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/UtilitiesFragment.kt
@@ -0,0 +1,19 @@
+package com.example.myapplication
+
+import androidx.appcompat.app.AppCompatActivity
+import androidx.fragment.app.Fragment
+
+import android.content.Context
+import android.os.Bundle
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+
+class UtilitiesFragment : Fragment() {
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.activity_utilities, container)
+
+ }
+}
diff --git a/app/src/main/java/com/example/myapplication/VolunteeringFragment.kt b/app/src/main/java/com/example/myapplication/VolunteeringFragment.kt
new file mode 100644
index 00000000..de81fe14
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/VolunteeringFragment.kt
@@ -0,0 +1,16 @@
+package com.example.myapplication
+
+import androidx.appcompat.app.AppCompatActivity
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+
+class VolunteeringFragment : Fragment() {
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.activity_volunteering, container)
+ }
+}
diff --git a/app/src/main/java/com/example/myapplication/ui/login/LoginFragment.kt b/app/src/main/java/com/example/myapplication/ui/login/LoginFragment.kt
new file mode 100644
index 00000000..491aa43c
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/ui/login/LoginFragment.kt
@@ -0,0 +1,56 @@
+package com.example.myapplication.ui.login
+
+import androidx.lifecycle.ViewModelProviders
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.navigation.fragment.findNavController
+import com.example.myapplication.BridegfyVictim.Dao.AppDatabaseInstance
+import com.example.myapplication.BridegfyVictim.Dao.user.UserDetail
+
+import com.example.myapplication.R
+import kotlinx.android.synthetic.main.login_fragment.*
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+class LoginFragment : Fragment() {
+
+ companion object {
+ fun newInstance() = LoginFragment()
+ }
+
+ private lateinit var viewModel: LoginViewModel
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.login_fragment, container, false)
+ }
+
+ override fun onActivityCreated(savedInstanceState: Bundle?) {
+ super.onActivityCreated(savedInstanceState)
+ viewModel = ViewModelProviders.of(this.requireActivity()).get(LoginViewModel::class.java)
+ register.setOnClickListener {
+ val name = name.editableText.toString()
+ val phoneNumber = number.editableText.toString().toLong()
+ val gender = UserDetail.Gender.NONE
+
+ val user = UserDetail(
+ userName = name,
+ phoneNumber = phoneNumber,
+ gender = gender,
+ emergencyContact = UserDetail.EmergencyContact(
+ contact1 = 0,
+ contact2 = 0
+ )
+ )
+ viewModel.userDetail = user
+ findNavController().navigate(R.id.action_loginFragment_to_registerFragment)
+
+ }
+ }
+
+}
diff --git a/app/src/main/java/com/example/myapplication/ui/login/LoginViewModel.kt b/app/src/main/java/com/example/myapplication/ui/login/LoginViewModel.kt
new file mode 100644
index 00000000..5a654bca
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/ui/login/LoginViewModel.kt
@@ -0,0 +1,11 @@
+package com.example.myapplication.ui.login
+
+import androidx.lifecycle.ViewModel
+import com.example.myapplication.BridegfyVictim.Dao.user.UserDetail
+
+class LoginViewModel : ViewModel() {
+
+ var userDetail: UserDetail = UserDetail(
+ 0, "", 0, emergencyContact = UserDetail.EmergencyContact(0, 0)
+ )
+}
diff --git a/app/src/main/java/com/example/myapplication/ui/login/NativeLocationFragment.kt b/app/src/main/java/com/example/myapplication/ui/login/NativeLocationFragment.kt
new file mode 100644
index 00000000..9241fa05
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/ui/login/NativeLocationFragment.kt
@@ -0,0 +1,236 @@
+package com.example.myapplication.ui.login
+
+
+import android.Manifest
+import android.app.Activity
+import android.content.Intent
+import android.content.IntentSender
+import android.content.pm.PackageManager
+import android.location.Location
+import android.os.Bundle
+import androidx.core.content.ContextCompat
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.MutableLiveData
+import com.example.myapplication.BridegfyVictim.model.Failure
+import com.example.myapplication.BridegfyVictim.model.OneOf
+import com.google.android.gms.common.api.ResolvableApiException
+import com.google.android.gms.location.*
+
+/**
+ * This Fragment represents the base Location class, any fragment which needs access to the
+ * native location feature will extend from this Fragment
+ * */
+abstract class NativeLocationFragment : Fragment() {
+
+ private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
+
+ /**
+ * [locationLiveData] will expose the current location obtained from the device,
+ * [OneOf.Success] represents the location has been successfully obtained
+ * [OneOf.Failure] is used if the location cannot be obtained due to lack of permission
+ * or required setting is not available/enabled in the device
+ * */
+ val locationLiveData: MutableLiveData> =
+ MutableLiveData()
+
+ private val locationRequest = LocationRequest.create().apply {
+ interval = 10
+ priority = LocationRequest.PRIORITY_HIGH_ACCURACY
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ fusedLocationProviderClient =
+ LocationServices.getFusedLocationProviderClient(requireContext())
+ }
+
+ /**
+ *call this method to update the location value in [locationLiveData].The execution is as follows,
+ * [isLocationPermissionGranted] -> [checkRequiredLocationSettings] (if success) -> [fetchLastKnownLocation]
+ * (if failure) -> open settings screen to enable location
+ */
+ fun updateLocation() {
+
+ if (isLocationPermissionGranted()) {
+ checkRequiredLocationSettings(
+ successListener = {
+ fetchLastKnownLocation()
+
+ },
+ failureListener = { exception ->
+ if (exception is ResolvableApiException) {
+ // Location settings are not satisfied
+ try {
+ // Show the dialog by calling startIntentSenderForResult(),
+ // and check the result in onActivityResult().
+ startIntentSenderForResult(
+ exception.resolution.intentSender,
+ REQUEST_CHECK_SETTINGS,
+ null,
+ 0,
+ 0,
+ 0,
+ null
+ )
+ } catch (sendEx: IntentSender.SendIntentException) {
+ //Ignore
+ }
+ }
+ }
+ )
+ } else {
+ requestLocationPermission()
+ }
+ }
+
+ /**
+ * check if the location permission is granted or not
+ */
+ private fun isLocationPermissionGranted(): Boolean {
+ return ContextCompat.checkSelfPermission(
+ requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION
+ ) == PackageManager.PERMISSION_GRANTED
+ }
+
+ /**
+ * request the runtime permission for location, for devices above android 6
+ */
+ private fun requestLocationPermission() {
+ requestPermissions(
+ arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
+ LOCATION_PERMISSION_CHECK
+ )
+ }
+
+ /**
+ * check if the current devices settings match the required settings needed to obtain the location
+ * [successListener] is a lambda with a param [LocationSettingsResponse] will be executed if the current settings
+ * match the required settings
+ * [failureListener] will be invoked if the current settings and the required settings doesn't match
+ */
+ private fun checkRequiredLocationSettings(
+ successListener: (LocationSettingsResponse) -> Unit,
+ failureListener: (Exception) -> Unit
+ ) {
+ val locationSettingRequest = LocationSettingsRequest.Builder()
+ .addLocationRequest(locationRequest)
+ .build()
+
+ val settingsClient = LocationServices.getSettingsClient(requireContext())
+
+ settingsClient.checkLocationSettings(locationSettingRequest)
+ .addOnSuccessListener(successListener)
+ .addOnFailureListener(failureListener)
+ }
+
+ /**
+ * this method is used to post the last know location using [fusedLocationProviderClient.lastLocation]
+ * returns [OneOf.Success] if the location value is not null and [OneOf.Failure] if the operation fails
+ * if the [Location] value returned is null, a new locationUpdateRequest is subscribed by calling [requestNewLocationUpdates]
+ */
+ private fun fetchLastKnownLocation() {
+ fusedLocationProviderClient.lastLocation
+ .addOnSuccessListener { location: Location? ->
+ if (location != null) {
+ locationLiveData.postValue(
+ OneOf.Success(
+ location,
+ OneOf.Success.DataState.FRESH_DATA
+ )
+ )
+ } else {
+ requestNewLocationUpdates()
+ }
+ }
+ .addOnFailureListener {
+ locationLiveData.postValue(
+ OneOf.Failure(
+ Failure.LocationFailure.UnknownLocationFailure
+ )
+ )
+ }
+ }
+
+ /**
+ * call this method if the [fusedLocationProviderClient.lastLocation] returns null.
+ * this method will setup a new location update callback with single update for location.
+ */
+ private fun requestNewLocationUpdates() {
+ fusedLocationProviderClient.requestLocationUpdates(
+ locationRequest.apply {
+ numUpdates = 1
+ },
+ object : LocationCallback() {
+ override fun onLocationResult(locations: LocationResult?) {
+ super.onLocationResult(locations)
+ locations?.let {
+ locationLiveData.postValue(
+ OneOf.Success(
+ it.lastLocation,
+ OneOf.Success.DataState.FRESH_DATA
+ )
+ )
+ } ?: run {
+ // this block is executed if the location is null
+ locationLiveData.postValue(
+ OneOf.Failure(
+ Failure.LocationFailure.UnknownLocationFailure
+ )
+ )
+ }
+ }
+ },
+ null
+ )
+
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+
+ when (requestCode) {
+ REQUEST_CHECK_SETTINGS -> {
+ if (resultCode == Activity.RESULT_OK) {
+ //the users has changed the current location settings to meet the requirements, retry getting location
+ updateLocation()
+ } else {
+ //the user failed to update the location settings to meet the requirement
+ locationLiveData.postValue(
+ OneOf.Failure(
+ Failure.LocationFailure.LocationNotEnabledFailure
+ )
+ )
+ }
+ }
+ }
+ }
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array,
+ grantResults: IntArray
+ ) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+
+ when (requestCode) {
+ LOCATION_PERMISSION_CHECK -> {
+ if (grantResults.isNotEmpty() and (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
+ //the user has granted the location permission, hence retry to obtain the current location
+ updateLocation()
+ } else {
+ //the user has denied the location permission
+ locationLiveData.postValue(
+ OneOf.Failure(
+ Failure.LocationFailure.LocationPermissionDeniedFailure
+ )
+ )
+ }
+ }
+ }
+ }
+
+ companion object {
+ private const val REQUEST_CHECK_SETTINGS = 100
+ private const val LOCATION_PERMISSION_CHECK = 101
+ }
+}
+
diff --git a/app/src/main/java/com/example/myapplication/ui/login/register/RegisterFragment.kt b/app/src/main/java/com/example/myapplication/ui/login/register/RegisterFragment.kt
new file mode 100644
index 00000000..73b3a720
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/ui/login/register/RegisterFragment.kt
@@ -0,0 +1,60 @@
+package com.example.myapplication.ui.login.register
+
+import android.content.Context
+import android.net.Uri
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.lifecycle.ViewModelProviders
+import androidx.navigation.fragment.findNavController
+import com.example.myapplication.BridegfyVictim.Dao.AppDatabaseInstance
+import com.example.myapplication.BridegfyVictim.Dao.user.UserDetail
+
+import com.example.myapplication.R
+import com.example.myapplication.ui.login.LoginViewModel
+import kotlinx.android.synthetic.main.fragment_register.*
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+class RegisterFragment : Fragment() {
+
+ private lateinit var viewModel: LoginViewModel
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ // Inflate the layout for this fragment
+ return inflater.inflate(R.layout.fragment_register, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ viewModel = ViewModelProviders.of(this.requireActivity()).get(LoginViewModel::class.java)
+
+ save.setOnClickListener {
+ val emergencyContact1 = number_one.editableText.toString().toLong()
+ val emergencyContact2 = number_two.editableText.toString().toLong()
+
+ CoroutineScope(Dispatchers.IO).launch {
+ val userDao = AppDatabaseInstance.getDb(requireContext()).userDao()
+ userDao.updateUser(
+ viewModel.userDetail.copy(
+ emergencyContact = UserDetail.EmergencyContact(
+ emergencyContact1, emergencyContact2
+ )
+ )
+ )
+ withContext(Dispatchers.Main) {
+ findNavController().navigate(R.id.action_registerFragment_to_mainFragment)
+ }
+ }
+ }
+ }
+}
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 00000000..1f6bb290
--- /dev/null
+++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/border.xml b/app/src/main/res/drawable/border.xml
new file mode 100644
index 00000000..68c64e53
--- /dev/null
+++ b/app/src/main/res/drawable/border.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/button_round_mehroon.xml b/app/src/main/res/drawable/button_round_mehroon.xml
new file mode 100644
index 00000000..d18a39e8
--- /dev/null
+++ b/app/src/main/res/drawable/button_round_mehroon.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/gradient.xml b/app/src/main/res/drawable/gradient.xml
new file mode 100644
index 00000000..ba7e2ba3
--- /dev/null
+++ b/app/src/main/res/drawable/gradient.xml
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 00000000..0d025f9b
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_settings_black_24dp.xml b/app/src/main/res/drawable/ic_settings_black_24dp.xml
new file mode 100644
index 00000000..68ce9103
--- /dev/null
+++ b/app/src/main/res/drawable/ic_settings_black_24dp.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/icon_alert.xml b/app/src/main/res/drawable/icon_alert.xml
new file mode 100644
index 00000000..d1e45a88
--- /dev/null
+++ b/app/src/main/res/drawable/icon_alert.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/icon_back.xml b/app/src/main/res/drawable/icon_back.xml
new file mode 100644
index 00000000..fe59cb4c
--- /dev/null
+++ b/app/src/main/res/drawable/icon_back.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/icon_phone.xml b/app/src/main/res/drawable/icon_phone.xml
new file mode 100644
index 00000000..ee487ebe
--- /dev/null
+++ b/app/src/main/res/drawable/icon_phone.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/icon_round_add.xml b/app/src/main/res/drawable/icon_round_add.xml
new file mode 100644
index 00000000..e73aeb5d
--- /dev/null
+++ b/app/src/main/res/drawable/icon_round_add.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/icon_user.xml b/app/src/main/res/drawable/icon_user.xml
new file mode 100644
index 00000000..9e938543
--- /dev/null
+++ b/app/src/main/res/drawable/icon_user.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/rectangle.xml b/app/src/main/res/drawable/rectangle.xml
new file mode 100644
index 00000000..8a86d6af
--- /dev/null
+++ b/app/src/main/res/drawable/rectangle.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/round_border_white.xml b/app/src/main/res/drawable/round_border_white.xml
new file mode 100644
index 00000000..0bcbd623
--- /dev/null
+++ b/app/src/main/res/drawable/round_border_white.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/round_mehroon.xml b/app/src/main/res/drawable/round_mehroon.xml
new file mode 100644
index 00000000..03a0c010
--- /dev/null
+++ b/app/src/main/res/drawable/round_mehroon.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/round_white.xml b/app/src/main/res/drawable/round_white.xml
new file mode 100644
index 00000000..27ff1945
--- /dev/null
+++ b/app/src/main/res/drawable/round_white.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/font/montserrat.ttf b/app/src/main/res/font/montserrat.ttf
new file mode 100644
index 00000000..626355a2
Binary files /dev/null and b/app/src/main/res/font/montserrat.ttf differ
diff --git a/app/src/main/res/layout/activity_bridgefy.xml b/app/src/main/res/layout/activity_bridgefy.xml
new file mode 100644
index 00000000..857cc6a4
--- /dev/null
+++ b/app/src/main/res/layout/activity_bridgefy.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_emergencyactivity.xml b/app/src/main/res/layout/activity_emergencyactivity.xml
new file mode 100644
index 00000000..6a057762
--- /dev/null
+++ b/app/src/main/res/layout/activity_emergencyactivity.xml
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_food.xml b/app/src/main/res/layout/activity_food.xml
new file mode 100644
index 00000000..e2544de1
--- /dev/null
+++ b/app/src/main/res/layout/activity_food.xml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..916443dc
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_medication.xml b/app/src/main/res/layout/activity_medication.xml
new file mode 100644
index 00000000..dc20b707
--- /dev/null
+++ b/app/src/main/res/layout/activity_medication.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_utilities.xml b/app/src/main/res/layout/activity_utilities.xml
new file mode 100644
index 00000000..9ea8bd21
--- /dev/null
+++ b/app/src/main/res/layout/activity_utilities.xml
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_volunteering.xml b/app/src/main/res/layout/activity_volunteering.xml
new file mode 100644
index 00000000..d4f8b8ff
--- /dev/null
+++ b/app/src/main/res/layout/activity_volunteering.xml
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/dashboard.xml b/app/src/main/res/layout/dashboard.xml
new file mode 100644
index 00000000..916443dc
--- /dev/null
+++ b/app/src/main/res/layout/dashboard.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_native_location.xml b/app/src/main/res/layout/fragment_native_location.xml
new file mode 100644
index 00000000..3509b841
--- /dev/null
+++ b/app/src/main/res/layout/fragment_native_location.xml
@@ -0,0 +1,6 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_register.xml b/app/src/main/res/layout/fragment_register.xml
new file mode 100644
index 00000000..cab22ca6
--- /dev/null
+++ b/app/src/main/res/layout/fragment_register.xml
@@ -0,0 +1,266 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml
new file mode 100644
index 00000000..0e7a9bd4
--- /dev/null
+++ b/app/src/main/res/layout/fragment_settings.xml
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/login_fragment.xml b/app/src/main/res/layout/login_fragment.xml
new file mode 100644
index 00000000..9c51f832
--- /dev/null
+++ b/app/src/main/res/layout/login_fragment.xml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 00000000..eca70cfe
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 00000000..eca70cfe
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 00000000..898f3ed5
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 00000000..dffca360
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 00000000..64ba76f7
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 00000000..dae5e082
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..e5ed4659
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..14ed0af3
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..b0907cac
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..d8ae0315
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 00000000..2c18de9e
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..beed3cdd
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/navigation/main_nav.xml b/app/src/main/res/navigation/main_nav.xml
new file mode 100644
index 00000000..eb187f33
--- /dev/null
+++ b/app/src/main/res/navigation/main_nav.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 00000000..a4c28630
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,11 @@
+
+
+ #936b6a
+ #00574B
+ #D81B60
+ #ff9900
+ #135058
+ #000000
+ #ffffff
+ #80FFFFFF
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 00000000..752a5ddf
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,17 @@
+
+ Emergency Contact
+ Food and Water
+ Medication
+ Volunteering
+ Helfy
+ disaster_channel
+
+
+ Hello blank fragment
+
+
+ - Male
+ - Female
+ - Other
+
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 00000000..0eb88fe3
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/app/src/test/java/com/example/myapplication/ExampleUnitTest.java b/app/src/test/java/com/example/myapplication/ExampleUnitTest.java
new file mode 100644
index 00000000..bf43ee59
--- /dev/null
+++ b/app/src/test/java/com/example/myapplication/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.example.myapplication;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 00000000..a8d5645f
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,29 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ ext.kotlin_version = '1.3.50'
+ repositories {
+ google()
+ jcenter()
+
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.5.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 00000000..199d16ed
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,20 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..f6b961fd
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..7bf53fb6
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Sat Oct 12 14:38:52 IST 2019
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
diff --git a/gradlew b/gradlew
new file mode 100755
index 00000000..cccdd3d5
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 00000000..f9553162
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 00000000..e9b2b1e5
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name='My Application'