From a6ae73521d4bfd8b0a0d24e643b16dfefc083e8f Mon Sep 17 00:00:00 2001 From: udhay24 Date: Sun, 13 Oct 2019 11:27:36 +0530 Subject: [PATCH 01/39] initial commit --- .gitignore | 14 + .idea/vcs.xml | 6 + app/.gitignore | 1 + app/build.gradle | 82 ++++++ app/proguard-rules.pro | 32 +++ .../ExampleInstrumentedTest.java | 27 ++ app/src/main/AndroidManifest.xml | 37 +++ .../BridegfyVictim/BridgefyActivity.kt | 86 ++++++ .../BridegfyVictim/CommonViewModel.kt | 18 ++ .../BridegfyVictim/Repo/SmsRepo.kt | 28 ++ .../BridegfyVictim/SettingsFragment.kt | 88 +++++++ .../myapplication/BridegfyVictim/Util.kt | 66 +++++ .../BridegfyVictim/model/DisasterResources.kt | 51 ++++ .../BridegfyVictim/model/Failure.kt | 56 ++++ .../model/NativeLocationFragment.kt | 245 ++++++++++++++++++ .../BridegfyVictim/model/OneOf.kt | 44 ++++ .../myapplication/EmergencyFragment.kt | 40 +++ .../com/example/myapplication/FoodFragment.kt | 66 +++++ .../com/example/myapplication/MainFragment.kt | 37 +++ .../myapplication/MedicationFragment.kt | 43 +++ .../example/myapplication/MyApplication.kt | 206 +++++++++++++++ .../myapplication/UtilitiesFragment.kt | 19 ++ .../myapplication/VolunteeringFragment.kt | 16 ++ .../drawable-v24/ic_launcher_foreground.xml | 34 +++ app/src/main/res/drawable/border.xml | 17 ++ .../res/drawable/ic_launcher_background.xml | 170 ++++++++++++ .../res/drawable/ic_settings_black_24dp.xml | 5 + app/src/main/res/drawable/rectangle.xml | 31 +++ app/src/main/res/layout/activity_bridgefy.xml | 19 ++ .../res/layout/activity_emergencyactivity.xml | 53 ++++ app/src/main/res/layout/activity_food.xml | 80 ++++++ app/src/main/res/layout/activity_main.xml | 106 ++++++++ .../main/res/layout/activity_medication.xml | 79 ++++++ .../main/res/layout/activity_utilities.xml | 77 ++++++ .../main/res/layout/activity_volunteering.xml | 75 ++++++ .../res/layout/fragment_native_location.xml | 6 + app/src/main/res/layout/fragment_settings.xml | 126 +++++++++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2963 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 4905 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2060 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2783 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4490 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 6895 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6387 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 10413 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9128 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 15132 bytes app/src/main/res/navigation/main_nav.xml | 42 +++ app/src/main/res/values/colors.xml | 11 + app/src/main/res/values/strings.xml | 12 + app/src/main/res/values/styles.xml | 11 + .../myapplication/ExampleUnitTest.java | 17 ++ build.gradle | 29 +++ gradle.properties | 20 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 172 ++++++++++++ gradlew.bat | 84 ++++++ settings.gradle | 2 + 61 files changed, 2602 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/vcs.xml create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/proguard-rules.pro create mode 100644 app/src/androidTest/java/com/example/myapplication/ExampleInstrumentedTest.java create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/java/com/example/myapplication/BridegfyVictim/BridgefyActivity.kt create mode 100644 app/src/main/java/com/example/myapplication/BridegfyVictim/CommonViewModel.kt create mode 100644 app/src/main/java/com/example/myapplication/BridegfyVictim/Repo/SmsRepo.kt create mode 100644 app/src/main/java/com/example/myapplication/BridegfyVictim/SettingsFragment.kt create mode 100644 app/src/main/java/com/example/myapplication/BridegfyVictim/Util.kt create mode 100644 app/src/main/java/com/example/myapplication/BridegfyVictim/model/DisasterResources.kt create mode 100644 app/src/main/java/com/example/myapplication/BridegfyVictim/model/Failure.kt create mode 100644 app/src/main/java/com/example/myapplication/BridegfyVictim/model/NativeLocationFragment.kt create mode 100644 app/src/main/java/com/example/myapplication/BridegfyVictim/model/OneOf.kt create mode 100644 app/src/main/java/com/example/myapplication/EmergencyFragment.kt create mode 100644 app/src/main/java/com/example/myapplication/FoodFragment.kt create mode 100644 app/src/main/java/com/example/myapplication/MainFragment.kt create mode 100644 app/src/main/java/com/example/myapplication/MedicationFragment.kt create mode 100644 app/src/main/java/com/example/myapplication/MyApplication.kt create mode 100644 app/src/main/java/com/example/myapplication/UtilitiesFragment.kt create mode 100644 app/src/main/java/com/example/myapplication/VolunteeringFragment.kt create mode 100644 app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 app/src/main/res/drawable/border.xml create mode 100644 app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 app/src/main/res/drawable/ic_settings_black_24dp.xml create mode 100644 app/src/main/res/drawable/rectangle.xml create mode 100644 app/src/main/res/layout/activity_bridgefy.xml create mode 100644 app/src/main/res/layout/activity_emergencyactivity.xml create mode 100644 app/src/main/res/layout/activity_food.xml create mode 100644 app/src/main/res/layout/activity_main.xml create mode 100644 app/src/main/res/layout/activity_medication.xml create mode 100644 app/src/main/res/layout/activity_utilities.xml create mode 100644 app/src/main/res/layout/activity_volunteering.xml create mode 100644 app/src/main/res/layout/fragment_native_location.xml create mode 100644 app/src/main/res/layout/fragment_settings.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/navigation/main_nav.xml create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/styles.xml create mode 100644 app/src/test/java/com/example/myapplication/ExampleUnitTest.java create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle 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/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/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..1466b2be --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,82 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +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' + 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" + annotationProcessor "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" + +} +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..5efe73a8 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..38cf1f83 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/BridgefyActivity.kt @@ -0,0 +1,86 @@ +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 com.example.myapplication.R + +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() + } + + 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/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..57a523d3 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/SettingsFragment.kt @@ -0,0 +1,88 @@ +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) + + switch1.setOnClickListener { + sharedPreferences.edit() + .putBoolean(FOOD_AVAILABLE, switch1.isChecked) + .apply() + if (switch1.isChecked) { + detectLocation() + } + } + + switch2.setOnClickListener { + sharedPreferences.edit() + .putBoolean(FOOD_AVAILABLE, switch2.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" + } +} 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..6aa12d62 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/Util.kt @@ -0,0 +1,66 @@ +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}" + } +} + +fun getTitle(disasterResources: DisasterResources): String { + return when (disasterResources) { + is DisasterResources.SendEmergencyMessage -> "Send emergency contact" + is DisasterResources.FoodRequest -> "Food Request" + is DisasterResources.Medication -> " Medication Request" + } +} + + +fun getDeviceId(context: Context): String { + return Settings.Secure.getString(context.contentResolver, + Settings.Secure.ANDROID_ID) +} + +object NetworkUtil { + + val gson = Gson() +} \ 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..b30c6fa2 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/BridegfyVictim/model/DisasterResources.kt @@ -0,0 +1,51 @@ +package com.example.myapplication.BridegfyVictim.model + +import com.bridgefy.sdk.client.Bridgefy + +sealed class DisasterResources( + val userDeviceId: String +) { + + data class SendEmergencyMessage( + val emergencyContact1: Long, + val emergencyContact2: Long, + val emergencyContact3: 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..ee1cc3fb --- /dev/null +++ b/app/src/main/java/com/example/myapplication/EmergencyFragment.kt @@ -0,0 +1,40 @@ +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_emergencyactivity.* + +class EmergencyFragment : Fragment() { + + 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) + send_emergency_message_button.setOnClickListener { + val message = message.editableText.toString().trim() + val disasterResources = DisasterResources.SendEmergencyMessage( + emergencyContact1 = 7010065028, + emergencyContact2 = 7010065028, + emergencyContact3 = 7010065028, + message = message, + deviceId = getDeviceId(requireContext()) + ) + broadcastMessage(disasterResources) + } + } +} 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..97fa4790 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/FoodFragment.kt @@ -0,0 +1,66 @@ +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..a1e9b735 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/MainFragment.kt @@ -0,0 +1,37 @@ +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) + emergency_button.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..0898dc1a --- /dev/null +++ b/app/src/main/java/com/example/myapplication/MyApplication.kt @@ -0,0 +1,206 @@ +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 com.example.myapplication.BridegfyVictim.* + +class MyApplication : Application() { + + val availableDevices: MutableList = mutableListOf() + + 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") + } + + 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) + availableDevices.add(device) + } + + override fun onDeviceLost(device: Device?) { + super.onDeviceLost(device) + availableDevices.removeAll { + it?.userId == device?.userId + } + } + } + + override fun onCreate() { + super.onCreate() + + createNotificationChannel() + Bridgefy.initialize(applicationContext, "610fd8bb-54e6-4a21-9554-00740a7a1ba8", object : RegistrationListener() { + + override fun onRegistrationSuccessful(bridgefyClient: BridgefyClient) { + // BridgefyActivity is ready to start + val builder = Config.Builder() + builder.setEnergyProfile(BFEnergyProfile.HIGH_PERFORMANCE) + builder.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) { + + } + + 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.emergencyContact1.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/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/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/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/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..0ce1f1e3 --- /dev/null +++ b/app/src/main/res/layout/activity_emergencyactivity.xml @@ -0,0 +1,53 @@ + + + + + + + + + +