From 0e80984719e72a128d1bb580b93dcc1022d87ff9 Mon Sep 17 00:00:00 2001 From: 14Sandee Date: Fri, 17 Nov 2023 21:06:30 +0530 Subject: [PATCH] , --- .idea/deploymentTargetDropDown.xml | 2 +- .../com/app/simplitend/apputils/AppUtil.java | 59 ++++++- .../apputils/NotificationService.java | 12 +- .../simplitend/apputils/RetrofitHelper.java | 5 + .../mvvm/CaregiverMainViewModel.java | 4 +- .../cg_geofencing/CgGeoFencingActivity.java | 68 ++++---- .../DefaultLocationClient.java | 1 - .../locationupdates/LocationService.java | 7 + .../DirectionToHomeActivity.java | 26 ++- .../PatientMainViewModel.java | 6 +- .../patient_dashboard/chats/ChatFragment.java | 4 +- .../patient_dashboard/chats/SocketHelper.java | 1 - .../fragments/PatientDashboardFragment.java | 31 +++- .../GeoFenceBroadcastReceiver.java | 150 ++++++++++++++---- .../PatientLocationUpdatesReceiver.java | 96 +++++------ .../medreminder/ReminderFragment.java | 8 + .../medreminder/mvvm/ReminderAdapter.java | 2 +- .../setuproutine/RoutineFragment.java | 7 + .../fragments/SignInFragment.java | 1 - app/src/main/res/drawable/ic_cup.png | Bin 14711 -> 0 bytes app/src/main/res/drawable/ic_med_cup.png | Bin 0 -> 21483 bytes 21 files changed, 348 insertions(+), 142 deletions(-) delete mode 100644 app/src/main/res/drawable/ic_cup.png create mode 100644 app/src/main/res/drawable/ic_med_cup.png diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index cfdcd92..72d9d97 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -12,7 +12,7 @@ - + diff --git a/app/src/main/java/com/app/simplitend/apputils/AppUtil.java b/app/src/main/java/com/app/simplitend/apputils/AppUtil.java index 5550be7..9c20911 100644 --- a/app/src/main/java/com/app/simplitend/apputils/AppUtil.java +++ b/app/src/main/java/com/app/simplitend/apputils/AppUtil.java @@ -96,6 +96,7 @@ public abstract class AppUtil { public static final String CG_REGISTRATION_COMPLETE = "cg_registration_complete"; public static final String PATIENT_UID = "patient_uid"; + public static final String IS_PATIENT_LOGGED_IN = "patient_logged_in"; public static final String WHITE_LISTED_CONTACTS = "white_listed_contacts"; @@ -502,12 +503,21 @@ public abstract class AppUtil { title = patient_name + " requested for directions to home"; body = "Current location:"; - String senior_address = intent.getStringExtra(NOTIFICATION_SENIOR_ADDRESS_KEY); + String doh_distance = intent.getStringExtra(NOTIFICATION_SENIOR_ADDRESS_KEY); + + try { + double distance = Double.parseDouble(doh_distance); + if (distance == 0) throw new Exception(); + + doh_distance = distance + " miles away from home"; + }catch (Exception e){ + doh_distance = "Unable to locate"; + } setupBottomSheet(binding, R.drawable.img_directioin_requested, title, body, - senior_address, "Call senior", + doh_distance, "Call senior", v -> { CaregiverDataCache.getCaregiverData(context, (careGiverData -> { bsd.dismiss(); @@ -681,7 +691,8 @@ public abstract class AppUtil { setWhiteListedContacts(context, null); // geofence details clear - updatePatientGeofence(context, null, null, null, null); + updatePatientGeofence(context, null, null, null, null, null); + updatePatientGeofenceChatsCred(context, -1, -1); // removing geofence of same tag removeGeofence(context); @@ -807,8 +818,42 @@ public abstract class AppUtil { private static final String PATIENT_GEOFENCE_RADIUS_UNIT = "patient_geofence_radius_unit"; private static final String PATIENT_GEOFENCE_LATITUDE = "patient_geofence_latitude"; private static final String PATIENT_GEOFENCE_LONGITUDE = "patient_geofence_longitude"; + private static final String PATIENT_GEOFENCE_MESSAGE = "patient_geofence_message"; - public static void updatePatientGeofence(Context context, String lat, String lng, String radius, String radius_unit) { + private static final String PATIENT_GEOFENCE_CG_ID = "pg_cg_uid"; + private static final String PATIENT_GEOFENCE_CHANNEL_ID = "pg_channel_uid"; + + public static void updatePatientGeofenceChatsCred(Context context, + int cg_id, + int channel_id){ + SharedPreferences sp = context.getSharedPreferences(PATIENT_DETAILS, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sp.edit(); + + editor.putInt(PATIENT_GEOFENCE_CG_ID, cg_id); + editor.putInt(PATIENT_GEOFENCE_CHANNEL_ID, channel_id); + + editor.apply(); + } + + // return array of size 3 + // index content + // 0 -> patient_id + // 1 -> caregiver_id + // 2 -> channel_id + @NonNull + public static int[] getPatientGeofenceChatCred(Context context){ + SharedPreferences sp = context.getSharedPreferences(PATIENT_DETAILS, Context.MODE_PRIVATE); + return new int[]{sp.getInt(PATIENT_UID, -1), + sp.getInt(PATIENT_GEOFENCE_CG_ID, -1), + sp.getInt(PATIENT_GEOFENCE_CHANNEL_ID, -1)}; + } + + public static void updatePatientGeofence(Context context, + String lat, + String lng, + String radius, + String radius_unit, + String message) { SharedPreferences sp = context.getSharedPreferences(PATIENT_DETAILS, Context.MODE_PRIVATE); SharedPreferences.Editor editor = sp.edit(); @@ -816,6 +861,7 @@ public abstract class AppUtil { editor.putString(PATIENT_GEOFENCE_LONGITUDE, lng); editor.putString(PATIENT_GEOFENCE_RADIUS, radius); editor.putString(PATIENT_GEOFENCE_RADIUS_UNIT, radius_unit); + editor.putString(PATIENT_GEOFENCE_MESSAGE, message); editor.apply(); Log.d(GEOFENCE_TAG, "updatePatientGeofence: UPDATED"); @@ -836,6 +882,11 @@ public abstract class AppUtil { return sp.getString(PATIENT_GEOFENCE_RADIUS_UNIT, null); } + public static String getPatientGeofenceMessage(Context context) { + SharedPreferences sp = context.getSharedPreferences(PATIENT_DETAILS, Context.MODE_PRIVATE); + return sp.getString(PATIENT_GEOFENCE_MESSAGE, null); + } + public static void setWhiteListedContacts(Context context, List contactList){ Set contactSet; diff --git a/app/src/main/java/com/app/simplitend/apputils/NotificationService.java b/app/src/main/java/com/app/simplitend/apputils/NotificationService.java index b8aba65..4d030cb 100644 --- a/app/src/main/java/com/app/simplitend/apputils/NotificationService.java +++ b/app/src/main/java/com/app/simplitend/apputils/NotificationService.java @@ -82,12 +82,18 @@ public class NotificationService implements INotificationServiceExtension { double lat = extras.getDouble("lat"); double lng = extras.getDouble("lng"); double radius = extras.getDouble("radius"); + String message; + try { + message = extras.getString("message"); + } catch (JSONException e) { + message = null; + } Log.d(GEOFENCE_TAG, "DATA RECEIVED WITH NOTIFICATION : Lat/Lng: " + lat + "," + lng + " Radius: " + radius); if (radius >= 0){ addGeoFence(new LatLng(lat, lng), - radius, iNotificationReceivedEvent.getContext()); + radius, message, iNotificationReceivedEvent.getContext()); } }catch (Exception e){ Log.e(GEOFENCE_TAG, "COULDN'T CREATE GEOFENCE: " + e); @@ -100,7 +106,7 @@ public class NotificationService implements INotificationServiceExtension { } @RequiresPermission(Manifest.permission.ACCESS_FINE_LOCATION) - private void addGeoFence(@NonNull LatLng latLng, double GEOFENCING_RADIUS , Context context) { + private void addGeoFence(@NonNull LatLng latLng, double GEOFENCING_RADIUS, String message, Context context) { AppUtil.removeGeofence(context); GeoFenceHelper geoFenceHelper = new GeoFenceHelper(context); @@ -123,7 +129,7 @@ public class NotificationService implements INotificationServiceExtension { .addOnSuccessListener(aVoid -> { Log.d(GEOFENCE_TAG, "Geofence added successfully."); AppUtil.updatePatientGeofence(context, latLng.latitude+"", latLng.longitude+"", - GEOFENCING_RADIUS+"", "kms"); + GEOFENCING_RADIUS+"", "kms", message); }) .addOnFailureListener(e -> Log.d(GEOFENCE_TAG, "onFailure: Geofence couldn't be added: " + e.getLocalizedMessage() + " " + latLng + " Radius: " + GEOFENCING_RADIUS)); diff --git a/app/src/main/java/com/app/simplitend/apputils/RetrofitHelper.java b/app/src/main/java/com/app/simplitend/apputils/RetrofitHelper.java index 32d823a..7af21f3 100644 --- a/app/src/main/java/com/app/simplitend/apputils/RetrofitHelper.java +++ b/app/src/main/java/com/app/simplitend/apputils/RetrofitHelper.java @@ -11,8 +11,13 @@ import retrofit2.converter.gson.GsonConverterFactory; public abstract class RetrofitHelper { // urls + + // Testing BASE URL private static final String BASE_URL = "https://simplitend.betadelivery.com/"; + // Staging BASE URL +// private static final String BASE_URL = "https://simplitendapp.betadelivery.com/"; + public static final String CREATE_CONTACT = "api/contact-create"; public static final String UPDATE_CONTACT = "api/patient-contact-update/"; diff --git a/app/src/main/java/com/app/simplitend/caregiverdashboard/mvvm/CaregiverMainViewModel.java b/app/src/main/java/com/app/simplitend/caregiverdashboard/mvvm/CaregiverMainViewModel.java index 1eb087a..076fc01 100644 --- a/app/src/main/java/com/app/simplitend/caregiverdashboard/mvvm/CaregiverMainViewModel.java +++ b/app/src/main/java/com/app/simplitend/caregiverdashboard/mvvm/CaregiverMainViewModel.java @@ -40,8 +40,8 @@ public class CaregiverMainViewModel extends ViewModel { public String ongoingActivityText, upcomingActivityText; public String upcomingReminderText, dailyReminderText; - public List remindersList; - public List activityList; + public static List remindersList; + public static List activityList; public CaregiverMainViewModel(){ this.cgHomeRepository = CgHomeRepository.getHomeRepository(); diff --git a/app/src/main/java/com/app/simplitend/cg_geofencing/CgGeoFencingActivity.java b/app/src/main/java/com/app/simplitend/cg_geofencing/CgGeoFencingActivity.java index 19ce07f..953cd78 100644 --- a/app/src/main/java/com/app/simplitend/cg_geofencing/CgGeoFencingActivity.java +++ b/app/src/main/java/com/app/simplitend/cg_geofencing/CgGeoFencingActivity.java @@ -164,7 +164,7 @@ public class CgGeoFencingActivity extends AppCompatActivity implements OnMapRead protected void onDestroy() { super.onDestroy(); if (careGiverData != null) { - SocketHelper.getInstance().removeLocationUpdateListener(careGiverData.patientId+""); + SocketHelper.getInstance().removeLocationUpdateListener(careGiverData.patientId + ""); } SocketHelper.getInstance().closeConnection(); @@ -172,20 +172,20 @@ public class CgGeoFencingActivity extends AppCompatActivity implements OnMapRead private void establishSocketConnection() { CaregiverDataCache.getCaregiverData(this, (careGiverData1 -> { - if (careGiverData1 != null){ + if (careGiverData1 != null) { this.careGiverData = careGiverData1; SocketHelper socketHelper = SocketHelper.getInstance(); socketHelper.establishConnection(null); Log.d(LOCATION_REQUEST_TAG, "CG STARTED LISTENING TO LOCATION UPDATES"); - socketHelper.getLocationUpdates(careGiverData1.patientId+"", new SocketHelper.Callback() { + socketHelper.getLocationUpdates(careGiverData1.patientId + "", new SocketHelper.Callback() { @Override public void onMessageReceived(Location result) { Log.d(LOCATION_REQUEST_TAG, "LOCATION RECEIVED: " + result); - if (result != null){ + if (result != null) { // running on main thread - new Handler(Looper.getMainLooper()).post(()-> { + new Handler(Looper.getMainLooper()).post(() -> { pat_cur_latLng = new LatLng(result.getLatitude(), result.getLongitude()); updateCurrentLocationPatientMarker(); updatePatientCurrentLocationDetails(); @@ -224,11 +224,10 @@ public class CgGeoFencingActivity extends AppCompatActivity implements OnMapRead } } - if (geoFenceDetails.type == null){ + if (geoFenceDetails.type == null) { // default geofence_bs_binding.unitSpinner.selectItemByIndex(1); - } - else if (MILES.equals(geoFenceDetails.type)) { + } else if (MILES.equals(geoFenceDetails.type)) { geofence_bs_binding.unitSpinner.selectItemByIndex(1); radius = radius / 1609.34f; } else { @@ -262,10 +261,10 @@ public class CgGeoFencingActivity extends AppCompatActivity implements OnMapRead binding.backBtn.setOnClickListener(v -> onBackPressed()); binding.changeBtn.setOnClickListener(v -> { - if (binding.search.getVisibility() == View.VISIBLE){ + if (binding.search.getVisibility() == View.VISIBLE) { binding.search.setVisibility(View.GONE); binding.changeBtn.setText(getString(R.string.change)); - }else{ + } else { binding.changeBtn.setText(getString(R.string.close_)); binding.search.setVisibility(View.VISIBLE); } @@ -282,7 +281,7 @@ public class CgGeoFencingActivity extends AppCompatActivity implements OnMapRead }); geofence_bs_binding.cancelSetGf.setOnClickListener(v -> { - if (bottomSheetDialog != null){ + if (bottomSheetDialog != null) { bottomSheetDialog.dismiss(); } }); @@ -313,21 +312,22 @@ public class CgGeoFencingActivity extends AppCompatActivity implements OnMapRead getString(R.string.ok), ((dialogInterface, i) -> { updatePatientAddress(); }), - "Cancel", ((dialogInterface, i) -> {})); + "Cancel", ((dialogInterface, i) -> { + })); } else { Toast.makeText(this, "Cannot update address.", Toast.LENGTH_SHORT).show(); } }); binding.homeLocationBtn.setOnClickListener(v -> { - if (mMap != null && home_loc_marker != null){ + if (mMap != null && home_loc_marker != null) { mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(home_loc_marker.getPosition(), 16)); isTrackingSenior = false; } }); binding.cgLocationBtn.setOnClickListener(v -> { - if (mMap != null && curr_loc_marker != null){ + if (mMap != null && curr_loc_marker != null) { mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(curr_loc_marker.getPosition(), 16)); isTrackingSenior = true; } @@ -338,7 +338,7 @@ public class CgGeoFencingActivity extends AppCompatActivity implements OnMapRead if (patientData == null) return; try { - if (pat_cur_latLng != null){ + if (pat_cur_latLng != null) { // calculating distance LatLng homeLatLng = new LatLng(Double.parseDouble(patientData.lat), Double.parseDouble(patientData.lng)); @@ -353,9 +353,9 @@ public class CgGeoFencingActivity extends AppCompatActivity implements OnMapRead double distance = homeL.distanceTo(currL); distance /= 1609.34; // converting to Miles - if (distance <= 0.015){ + if (distance <= 0.015) { binding.distanceAwayTxt.setText(patientData.first_name + " is at Home"); - }else{ + } else { binding.distanceAwayTxt.setText(String.format(patientData.first_name + " is %.2f miles away", distance)); } } @@ -366,19 +366,19 @@ public class CgGeoFencingActivity extends AppCompatActivity implements OnMapRead StringBuilder senior_address = new StringBuilder(""); - if (patientData.address_line1 != null){ + if (patientData.address_line1 != null) { senior_address.append(patientData.address_line1).append(", "); } - if (patientData.city != null){ + if (patientData.city != null) { senior_address.append(patientData.city).append(", "); } - if (patientData.state != null){ + if (patientData.state != null) { senior_address.append(patientData.state).append(", "); } - if (patientData.country != null){ + if (patientData.country != null) { senior_address.append(patientData.country).append("."); } @@ -403,19 +403,18 @@ public class CgGeoFencingActivity extends AppCompatActivity implements OnMapRead Map body = new HashMap<>(); - String addressLine; - addressLine = (address.getThoroughfare() != null ? address.getThoroughfare() : address.getSubThoroughfare()); - - if (addressLine == null || addressLine.isEmpty()){ - addressLine = ""; - if (address.getMaxAddressLineIndex() >= 0 && address.getAddressLine(0) != null){ - String[] addressLines = address.getAddressLine(0).split(","); - for (int i = 0; i < Math.min(2, addressLines.length); i++) { - addressLine = addressLine.concat(addressLines[i]); - } + String addressLine = ""; + if (address.getMaxAddressLineIndex() >= 0 && address.getAddressLine(0) != null) { + String[] addressLines = address.getAddressLine(0).split(","); + for (int i = 0; i < Math.min(1, addressLines.length); i++) { + addressLine = addressLine.concat(addressLines[i]); } } + if (addressLine.isEmpty()){ + addressLine = (address.getThoroughfare() != null ? address.getThoroughfare() : address.getSubThoroughfare()); + } + body.put("town", (address.getSubLocality() != null ? address.getSubLocality() : address.getLocality())); body.put("street", addressLine); body.put("state", address.getAdminArea()); @@ -529,7 +528,7 @@ public class CgGeoFencingActivity extends AppCompatActivity implements OnMapRead updateCurrentLocationPatientMarker(); mMap.setOnMapClickListener(latLng1 -> { - if (binding.search.getVisibility() != View.VISIBLE){ + if (binding.search.getVisibility() != View.VISIBLE) { // search bar is not visible // user is not intending to change the home location return; @@ -548,7 +547,7 @@ public class CgGeoFencingActivity extends AppCompatActivity implements OnMapRead } private void updateCurrentLocationPatientMarker() { - if (pat_cur_latLng != null){ + if (pat_cur_latLng != null) { String name; if (patientData != null) name = patientData.first_name; else name = "Senior's location"; @@ -562,7 +561,7 @@ public class CgGeoFencingActivity extends AppCompatActivity implements OnMapRead if (curr_loc_marker != null) curr_loc_marker.remove(); curr_loc_marker = mMap.addMarker(options); - if (isTrackingSenior){ + if (isTrackingSenior) { mMap.animateCamera(CameraUpdateFactory.newLatLng(pat_cur_latLng)); } } @@ -621,7 +620,6 @@ public class CgGeoFencingActivity extends AppCompatActivity implements OnMapRead private void registerMapSearchResultLauncher() { // initializing places - // Initialize the SDK Places.initialize(this, getString(R.string.GOOGLE_MAPS_API_KEY)); diff --git a/app/src/main/java/com/app/simplitend/locationupdates/DefaultLocationClient.java b/app/src/main/java/com/app/simplitend/locationupdates/DefaultLocationClient.java index 1a5abe1..dc92668 100644 --- a/app/src/main/java/com/app/simplitend/locationupdates/DefaultLocationClient.java +++ b/app/src/main/java/com/app/simplitend/locationupdates/DefaultLocationClient.java @@ -51,7 +51,6 @@ public class DefaultLocationClient implements LocationClient{ } locationRequest = new LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, interval) - .setMinUpdateIntervalMillis(2000) // get fasted updates if available every 2 sec .build(); locationCallback = new LocationCallback() { diff --git a/app/src/main/java/com/app/simplitend/locationupdates/LocationService.java b/app/src/main/java/com/app/simplitend/locationupdates/LocationService.java index 54822c6..050d00f 100644 --- a/app/src/main/java/com/app/simplitend/locationupdates/LocationService.java +++ b/app/src/main/java/com/app/simplitend/locationupdates/LocationService.java @@ -15,6 +15,7 @@ import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; import com.app.simplitend.R; +import com.app.simplitend.patient_dashboard.chats.SocketHelper; import com.app.simplitend.patientgeofencing.PatientLocationUpdatesReceiver; import com.google.android.gms.location.LocationServices; @@ -35,6 +36,8 @@ public class LocationService extends Service implements LocationClient.DefaultLo super.onCreate(); locationClient = new DefaultLocationClient(this, LocationServices.getFusedLocationProviderClient(this)); + + SocketHelper.getInstance().establishConnection(null); } @Override @@ -60,9 +63,12 @@ public class LocationService extends Service implements LocationClient.DefaultLo stopForeground(true); stopSelf(); removeLocationUpdates(); + SocketHelper.getInstance().closeConnection(); } private void startLocationUpdates(int minInterval){ + SocketHelper.getInstance().establishConnection(null); + Notification notification = new NotificationCompat.Builder(this, LOCATION_NOTIFICATION_CHANNEL_ID) .setContentTitle("SimpliTend is sharing your current location") .setSmallIcon(R.mipmap.ic_launcher_round) @@ -89,6 +95,7 @@ public class LocationService extends Service implements LocationClient.DefaultLo stopForeground(true); stopSelf(); removeLocationUpdates(); + SocketHelper.getInstance().closeConnection(); } public void removeLocationUpdates(){ diff --git a/app/src/main/java/com/app/simplitend/patient_dashboard/DirectionToHomeActivity.java b/app/src/main/java/com/app/simplitend/patient_dashboard/DirectionToHomeActivity.java index a9db7d4..559272c 100644 --- a/app/src/main/java/com/app/simplitend/patient_dashboard/DirectionToHomeActivity.java +++ b/app/src/main/java/com/app/simplitend/patient_dashboard/DirectionToHomeActivity.java @@ -48,7 +48,6 @@ import com.google.maps.android.PolyUtil; import com.google.maps.model.DirectionsResult; import com.google.maps.model.DirectionsRoute; -import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -123,13 +122,30 @@ public class DirectionToHomeActivity extends AppCompatActivity startActivity(intent); - String current_address = AppUtil.getCompleteAddress(this, pat_lat, pat_lng); - if (current_address == null){ - current_address = "Unable to locate"; +// String current_address = AppUtil.getCompleteAddress(this, pat_lat, pat_lng); +// if (current_address == null){ +// current_address = "Unable to locate"; +// } + + double distance; + try { + + Location homeLocation = new Location("homeLatLng"); + homeLocation.setLatitude(pat_lat); + homeLocation.setLongitude(pat_lng); + + Location currLocation = new Location("currentLocation"); + currLocation.setLatitude(pat_cur_lat); + currLocation.setLongitude(pat_cur_lng); + + distance = homeLocation.distanceTo(currLocation); + distance /= 1609; // converting to miles + }catch (Exception e){ + distance = 0; } viewModel.notifyRequestedDirections(AppUtil.getPatientUid(this)+"", - current_address, + String.format(Locale.getDefault(),"%.2f", distance), AppUtil.getPatientToken(this)); }); diff --git a/app/src/main/java/com/app/simplitend/patient_dashboard/PatientMainViewModel.java b/app/src/main/java/com/app/simplitend/patient_dashboard/PatientMainViewModel.java index 403c24d..c64c5bf 100644 --- a/app/src/main/java/com/app/simplitend/patient_dashboard/PatientMainViewModel.java +++ b/app/src/main/java/com/app/simplitend/patient_dashboard/PatientMainViewModel.java @@ -100,7 +100,7 @@ public class PatientMainViewModel extends ViewModel { return; } - addGeoFence(latLng, radius, activity, geoFenceDetails.type); + addGeoFence(latLng, radius, activity, geoFenceDetails.type, geoFenceDetails.message); } } @@ -134,7 +134,7 @@ public class PatientMainViewModel extends ViewModel { } @RequiresPermission(Manifest.permission.ACCESS_FINE_LOCATION) - private void addGeoFence(@NonNull LatLng latLng, float GEOFENCING_RADIUS , Activity activity, String unit) { + private void addGeoFence(@NonNull LatLng latLng, float GEOFENCING_RADIUS , Activity activity, String unit, String message) { AppUtil.removeGeofence(activity); GeoFenceHelper geoFenceHelper = new GeoFenceHelper(activity); @@ -157,7 +157,7 @@ public class PatientMainViewModel extends ViewModel { .addOnSuccessListener(aVoid -> { Log.d(GEOFENCE_TAG, "Geofence added successfully. " + latLng + " Radius: " + GEOFENCING_RADIUS + " meters"); AppUtil.updatePatientGeofence(activity, latLng.latitude+"", latLng.longitude+"", - GEOFENCING_RADIUS+"", unit); + GEOFENCING_RADIUS+"", unit, message); }) .addOnFailureListener(e -> { Log.d(GEOFENCE_TAG, "onFailure: Geofence couldn't be added: " + e.getLocalizedMessage() + " " + latLng + " Radius: " + GEOFENCING_RADIUS); diff --git a/app/src/main/java/com/app/simplitend/patient_dashboard/chats/ChatFragment.java b/app/src/main/java/com/app/simplitend/patient_dashboard/chats/ChatFragment.java index 1ac48ce..d8369ba 100644 --- a/app/src/main/java/com/app/simplitend/patient_dashboard/chats/ChatFragment.java +++ b/app/src/main/java/com/app/simplitend/patient_dashboard/chats/ChatFragment.java @@ -110,12 +110,12 @@ public class ChatFragment extends Fragment implements SocketHelper.Callback= 4) { String received_sender_id = (String) args[1]; String message_txt = (String) args[2]; diff --git a/app/src/main/java/com/app/simplitend/patient_dashboard/fragments/PatientDashboardFragment.java b/app/src/main/java/com/app/simplitend/patient_dashboard/fragments/PatientDashboardFragment.java index f5a466e..168b05d 100644 --- a/app/src/main/java/com/app/simplitend/patient_dashboard/fragments/PatientDashboardFragment.java +++ b/app/src/main/java/com/app/simplitend/patient_dashboard/fragments/PatientDashboardFragment.java @@ -32,7 +32,6 @@ import androidx.navigation.Navigation; import com.app.simplitend.R; import com.app.simplitend.appblocking.FUAActivity; import com.app.simplitend.apputils.AppUtil; -import com.app.simplitend.apputils.CaregiverDataCache; import com.app.simplitend.apputils.Constants; import com.app.simplitend.apputils.PatientDataCache; import com.app.simplitend.caregiverdashboard.mvvm.CaregiverMainViewModel; @@ -139,6 +138,36 @@ public class PatientDashboardFragment extends Fragment implements ProfileContrac this.patientData = patientData; setDetails(); + + // updating chats credentials to send message when geofence is triggered when patient is out of geofence + // to send message to patient on behalf of caregiver + + if (patientData != null && patientData.link_id == null){ + PatientDataCache.setPatientData(null); // to load new fresh data + } + + try { + PatientDataCache.getPatientData(requireContext(), (patientData1 -> { + try { + if (patientData != null){ + int cg_id = Integer.parseInt(patientData.caregiverId); + int channel_id = Integer.parseInt(patientData.link_id); + + AppUtil.updatePatientGeofenceChatsCred( + requireContext(), + cg_id, + channel_id + ); + } + + }catch (Exception e){ + // do nothing + } + }), false); + } catch (Exception e) { + // do nothing + } + }), true); PatientDataCache.getContactList(requireContext(), "Bearer " + AppUtil.getPatientToken(requireContext()), diff --git a/app/src/main/java/com/app/simplitend/patientgeofencing/GeoFenceBroadcastReceiver.java b/app/src/main/java/com/app/simplitend/patientgeofencing/GeoFenceBroadcastReceiver.java index 186c019..b4af6ce 100644 --- a/app/src/main/java/com/app/simplitend/patientgeofencing/GeoFenceBroadcastReceiver.java +++ b/app/src/main/java/com/app/simplitend/patientgeofencing/GeoFenceBroadcastReceiver.java @@ -1,22 +1,28 @@ package com.app.simplitend.patientgeofencing; +import static com.app.simplitend.locationupdates.LocationService.LOCATION_INTERVAL_BASE_TIME; +import static com.app.simplitend.locationupdates.LocationService.LOCATION_UPDATE_MIN_INTERVAL; +import static com.app.simplitend.patientgeofencing.GeoFenceHelper.GEOFENCE_TAG; + import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.location.Location; +import android.os.AsyncTask; import android.util.Log; -import com.app.simplitend.locationupdates.LocationService; -import com.google.android.gms.location.Geofence; -import com.google.android.gms.location.GeofencingEvent; +import androidx.annotation.NonNull; + import com.app.simplitend.apputils.AppUtil; import com.app.simplitend.apputils.RetrofitHelper; import com.app.simplitend.caregiverdashboard.mvvm.NotificationApiService; +import com.app.simplitend.locationupdates.LocationService; +import com.app.simplitend.patient_dashboard.chats.SocketHelper; +import com.app.simplitend.patient_dashboard.chats.mvvm.Message; import com.app.simplitend.welcome.welcomepatient.mvvm.models.CallResponse; - -import static com.app.simplitend.locationupdates.LocationService.LOCATION_INTERVAL_BASE_TIME; -import static com.app.simplitend.locationupdates.LocationService.LOCATION_UPDATE_MIN_INTERVAL; -import static com.app.simplitend.patientgeofencing.GeoFenceHelper.GEOFENCE_TAG; +import com.google.android.gms.location.Geofence; +import com.google.android.gms.location.GeofencingEvent; +import com.onesignal.OneSignal; import java.util.HashMap; import java.util.Locale; @@ -31,14 +37,12 @@ public class GeoFenceBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent); - + if (geofencingEvent == null || geofencingEvent.hasError()) { Log.d(GEOFENCE_TAG, "onReceive: Couldn't add geofence"); return; } - Log.d(GEOFENCE_TAG, "onReceive: " + intent.getExtras()); - int transition_type = geofencingEvent.getGeofenceTransition(); Location location = geofencingEvent.getTriggeringLocation(); @@ -63,7 +67,7 @@ public class GeoFenceBroadcastReceiver extends BroadcastReceiver { distance = homeLocation.distanceTo(location); distance /= 1609; // converting to miles - }catch (Exception e){ + } catch (Exception e) { distance = 0; } @@ -75,17 +79,104 @@ public class GeoFenceBroadcastReceiver extends BroadcastReceiver { Log.d(GEOFENCE_TAG, "onReceive: ENTER"); Intent locationServiceIntent = new Intent(context, LocationService.class); locationServiceIntent.setAction(LocationService.ACTION_START_LOCATION_UPDATES); - locationServiceIntent.putExtra(LOCATION_UPDATE_MIN_INTERVAL, LOCATION_INTERVAL_BASE_TIME - ); + locationServiceIntent.putExtra(LOCATION_UPDATE_MIN_INTERVAL, LOCATION_INTERVAL_BASE_TIME); context.startService(locationServiceIntent); break; case Geofence.GEOFENCE_TRANSITION_EXIT: Log.d(GEOFENCE_TAG, "onReceive: EXIT"); - notifyOutOfGeofence(context, String.format(Locale.getDefault(),"%.2f", distance)); + notifyOutOfGeofence(context, String.format(Locale.getDefault(), "%.2f", distance)); + + notifyPatient(context); break; } } + private void notifyPatient(Context context) { + Log.d(GEOFENCE_TAG, "notifyPatient: SENDING MESSAGE TO SENIOR PHONE FROM CAREGIVER PHONE"); + + String message = AppUtil.getPatientGeofenceMessage(context); + if (message == null || message.trim().isEmpty()) { + message = "You are too far from home"; + } + + int[] chatsCred = AppUtil.getPatientGeofenceChatCred(context); + if (chatsCred[0] == -1 || chatsCred[1] == -1 || chatsCred[2] == -1) { + Log.d(GEOFENCE_TAG, "notifyPatient: CANNOT SEND MESSAGE AS EITHER PAT_ID, CG_ID OR CHANNEL_ID IS NOT AVAILABLE"); + return; + } + + // sending message + new SendMessageTask(message, chatsCred[0], chatsCred[1], chatsCred[2]).execute(); + } + + public static class SendMessageTask extends AsyncTask { + @NonNull + private final String message; + private final int patientId, cg_id, channel_id; + + public SendMessageTask(@NonNull String message, int patientId, int cg_id, int channel_id) { + this.patientId = patientId; + this.cg_id = cg_id; + this.channel_id = channel_id; + this.message = message; + } + + @Override + protected Void doInBackground(Void... voids) { + SocketHelper socketHelper = SocketHelper.getInstance(); + + socketHelper.getMessage(new SocketHelper.Callback() { + @Override + public void onMessageReceived(Message result) { + Log.d(GEOFENCE_TAG, "doInBackground: MESSAGE SENT"); + socketHelper.stopMessages(channel_id + ""); + socketHelper.closeConnection(); + } + + @Override + public void onMessageSentSuccessfully() { + socketHelper.stopMessages(channel_id + ""); + socketHelper.closeConnection(); + } + + @Override + public void onError(Exception e) { + Log.d(GEOFENCE_TAG, "doInBackground: MESSAGE NOT SENT " + e); + socketHelper.stopMessages(channel_id + ""); + socketHelper.closeConnection(); + } + }, cg_id + "", channel_id + "", patientId + "", null); + + if (socketHelper.isConnected()) { + Log.d(GEOFENCE_TAG, "doInBackground: ALREADY CONNECTED TO SOCKET"); + socketHelper.sendMessage(message, cg_id + "", patientId + "", channel_id + ""); + } else { + Log.d(GEOFENCE_TAG, "doInBackground: CONNECTING TO SOCKET"); + + socketHelper.establishConnection(new SocketHelper.SockCallBack() { + @Override + public void onSocketConnected() { + Log.d(GEOFENCE_TAG, "doInBackground: SOCKET CONNECTED"); + socketHelper.sendMessage(message, cg_id + "", patientId + "", channel_id + ""); + } + + @Override + public void onConnectionError(Exception e) { + Log.d(GEOFENCE_TAG, "doInBackground: SOCKET CONNECTION ERROR " + e); + } + + @Override + public void onDisconnected() { + Log.d(GEOFENCE_TAG, "doInBackground: SOCKET DISCONNECTED"); + } + }); + + } + + return null; + } + } + private void notifyOutOfGeofence(Context context, String senior_address) { Log.d(GEOFENCE_TAG, "Sending notification to patient"); Log.d(GEOFENCE_TAG, "Current location: " + senior_address); @@ -95,27 +186,26 @@ public class GeoFenceBroadcastReceiver extends BroadcastReceiver { body.put("patient_id", AppUtil.getPatientUid(context) + ""); body.put("address", senior_address); - apiService.notifyOutOfGeoFence(body, "Bearer " + AppUtil.getPatientToken(context)) - .enqueue(new Callback>() { - @Override - public void onResponse(Call> call, Response> response) { - if (response.code() == 200){ - Log.d(GEOFENCE_TAG, "OUT OF GEOFENCE NOTIFICATION SENT SUCCESSFULLY."); - }else{ - Log.d(GEOFENCE_TAG, "Couldn't notify patient " + response.message()); - } - } + apiService.notifyOutOfGeoFence(body, "Bearer " + AppUtil.getPatientToken(context)).enqueue(new Callback>() { + @Override + public void onResponse(Call> call, Response> response) { + if (response.code() == 200) { + Log.d(GEOFENCE_TAG, "OUT OF GEOFENCE NOTIFICATION SENT SUCCESSFULLY."); + } else { + Log.d(GEOFENCE_TAG, "Couldn't notify patient " + response.message()); + } + } - @Override - public void onFailure(Call> call, Throwable t) { - Log.d(GEOFENCE_TAG, "Couldn't notify patient due to " + t); - } - }); + @Override + public void onFailure(Call> call, Throwable t) { + Log.d(GEOFENCE_TAG, "Couldn't notify patient due to " + t); + } + }); // getting faster location updates as patient is out of geofence Intent intent = new Intent(context, LocationService.class); intent.setAction(LocationService.ACTION_START_LOCATION_UPDATES); - intent.putExtra(LOCATION_UPDATE_MIN_INTERVAL, 10 * 1000); // every 10 seconds + intent.putExtra(LOCATION_UPDATE_MIN_INTERVAL, 5 * 1000); // every 5 seconds context.startService(intent); } diff --git a/app/src/main/java/com/app/simplitend/patientgeofencing/PatientLocationUpdatesReceiver.java b/app/src/main/java/com/app/simplitend/patientgeofencing/PatientLocationUpdatesReceiver.java index 22271b3..89dd9be 100644 --- a/app/src/main/java/com/app/simplitend/patientgeofencing/PatientLocationUpdatesReceiver.java +++ b/app/src/main/java/com/app/simplitend/patientgeofencing/PatientLocationUpdatesReceiver.java @@ -3,6 +3,7 @@ package com.app.simplitend.patientgeofencing; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.location.Address; import android.location.Location; import android.os.AsyncTask; import android.util.Log; @@ -39,13 +40,13 @@ public class PatientLocationUpdatesReceiver extends BroadcastReceiver { int patient_id = AppUtil.getPatientUid(context); String token = AppUtil.getPatientToken(context); - if (patient_id != -1 && token != null){ + if (patient_id != -1 && token != null) { updateRemoteCurrLocation(location, patient_id, "Bearer " + token); - }else{ - Log.e(LOCATION_REQUEST_TAG, "CANNOT UPDATE REMOTE LOCATION AS PATIENT_ID OR TOKEN IS -1 OR NULL RESP." ); + } else { + Log.e(LOCATION_REQUEST_TAG, "CANNOT UPDATE REMOTE LOCATION AS PATIENT_ID OR TOKEN IS -1 OR NULL RESP."); } - }else{ + } else { Log.e(LOCATION_REQUEST_TAG, "LOCATION RECEIVED IS NULL"); } } @@ -55,7 +56,7 @@ public class PatientLocationUpdatesReceiver extends BroadcastReceiver { PatientProfileAPIService apiService = RetrofitHelper.getRetrofit().create(PatientProfileAPIService.class); Map body = new HashMap<>(); - body.put("patient_id", patient_id+""); + body.put("patient_id", patient_id + ""); body.put("lat", location.getLatitude() + ""); body.put("lng", location.getLongitude() + ""); @@ -63,13 +64,13 @@ public class PatientLocationUpdatesReceiver extends BroadcastReceiver { .enqueue(new Callback>() { @Override public void onResponse(Call> call, Response> response) { - if (response.body() != null){ - if (response.code() == 200 && response.body().error_code == 0){ + if (response.body() != null) { + if (response.code() == 200 && response.body().error_code == 0) { Log.d(LOCATION_REQUEST_TAG, "LOCATION REMOTE UPDATED."); - }else{ + } else { Log.e(LOCATION_REQUEST_TAG, "LOCATION REMOTE UPDATE FAILED" + response.body().message); } - }else{ + } else { Log.e(LOCATION_REQUEST_TAG, "LOCATION REMOTE UPDATE FAILED" + response.message()); } } @@ -83,11 +84,11 @@ public class PatientLocationUpdatesReceiver extends BroadcastReceiver { new UpdateRemoteLocationTask(patient_id + "").execute(location); } - public static class UpdateRemoteLocationTask extends AsyncTask{ + public static class UpdateRemoteLocationTask extends AsyncTask { @NonNull private final String patientId; - public UpdateRemoteLocationTask(@NonNull String patientId){ + public UpdateRemoteLocationTask(@NonNull String patientId) { this.patientId = patientId; } @@ -95,53 +96,44 @@ public class PatientLocationUpdatesReceiver extends BroadcastReceiver { protected Void doInBackground(Location... locations) { SocketHelper socketHelper = SocketHelper.getInstance(); - if (socketHelper.isConnected()){ - Log.d(LOCATION_REQUEST_TAG, "doInBackground: ALREADY CONNECTED TO SOCKET"); - socketHelper.getLocationUpdates(patientId, null); - socketHelper.sendLocationUpdates(locations[0], patientId); - }else{ - Log.d(LOCATION_REQUEST_TAG, "doInBackground: CONNECTING TO SOCKET"); - socketHelper.getLocationUpdates(patientId, new SocketHelper.Callback() { - @Override - public void onMessageReceived(Location result) { - Log.d(LOCATION_REQUEST_TAG, "LOCATION SENT " + result); - socketHelper.removeLocationUpdateListener(patientId); - socketHelper.closeConnection(); - } + Log.d(LOCATION_REQUEST_TAG, "doInBackground: CONNECTING TO SOCKET"); - @Override - public void onMessageSentSuccessfully() { - socketHelper.removeLocationUpdateListener(patientId); - socketHelper.closeConnection(); - } + socketHelper.getLocationUpdates(patientId, new SocketHelper.Callback() { + @Override + public void onMessageReceived(Location result) { + Log.d(LOCATION_REQUEST_TAG, "LOCATION SENT " + result); + socketHelper.removeLocationUpdateListener(patientId); + } - @Override - public void onError(Exception e) { - Log.e(LOCATION_REQUEST_TAG, "LOCATION SENDING PROBLEM", e); - socketHelper.removeLocationUpdateListener(patientId); - socketHelper.closeConnection(); - } - }); + @Override + public void onMessageSentSuccessfully() { + socketHelper.removeLocationUpdateListener(patientId); + } - socketHelper.establishConnection(new SocketHelper.SockCallBack() { - @Override - public void onSocketConnected() { - Log.d(LOCATION_REQUEST_TAG, "doInBackground: SOCKET CONNECTED"); - socketHelper.sendLocationUpdates(locations[0], patientId); - } + @Override + public void onError(Exception e) { + Log.e(LOCATION_REQUEST_TAG, "LOCATION SENDING PROBLEM", e); + socketHelper.removeLocationUpdateListener(patientId); + } + }); - @Override - public void onConnectionError(Exception e) { - Log.d(LOCATION_REQUEST_TAG, "doInBackground: SOCKET CONNECTION ERROR"); - } + socketHelper.establishConnection(new SocketHelper.SockCallBack() { + @Override + public void onSocketConnected() { + Log.d(LOCATION_REQUEST_TAG, "doInBackground: SOCKET CONNECTED"); + socketHelper.sendLocationUpdates(locations[0], patientId); + } - @Override - public void onDisconnected() { - Log.d(LOCATION_REQUEST_TAG, "doInBackground: SOCKET DISCONNECTED"); - } - }); + @Override + public void onConnectionError(Exception e) { + Log.d(LOCATION_REQUEST_TAG, "doInBackground: SOCKET CONNECTION ERROR" + e); + } - } + @Override + public void onDisconnected() { + Log.d(LOCATION_REQUEST_TAG, "doInBackground: SOCKET DISCONNECTED"); + } + }); return null; } diff --git a/app/src/main/java/com/app/simplitend/patientprofile/medreminder/ReminderFragment.java b/app/src/main/java/com/app/simplitend/patientprofile/medreminder/ReminderFragment.java index 0f813f8..0813a6d 100644 --- a/app/src/main/java/com/app/simplitend/patientprofile/medreminder/ReminderFragment.java +++ b/app/src/main/java/com/app/simplitend/patientprofile/medreminder/ReminderFragment.java @@ -16,6 +16,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import com.app.simplitend.R; import com.app.simplitend.apputils.AppUtil; +import com.app.simplitend.caregiverdashboard.mvvm.CaregiverMainViewModel; import com.app.simplitend.databinding.RemindersFragmentBinding; import com.app.simplitend.patientprofile.ProfileContracts; import com.app.simplitend.patientprofile.medreminder.mvvm.ReminderAdapter; @@ -327,6 +328,13 @@ public class ReminderFragment extends Fragment implements RecyclerTouchListener. if (reminderResultList != null && reminderResultList.size() > 0) { // reminders are present + + // updating global list of reminders + if (reminderViewModel.selected_dow == 0){ + // only updating global list of reminders with current day's reminder list + CaregiverMainViewModel.remindersList = reminderResultList; + } + binding.remindersRv.setVisibility(View.VISIBLE); binding.noData.setVisibility(View.GONE); diff --git a/app/src/main/java/com/app/simplitend/patientprofile/medreminder/mvvm/ReminderAdapter.java b/app/src/main/java/com/app/simplitend/patientprofile/medreminder/mvvm/ReminderAdapter.java index cc1154f..0c5414b 100644 --- a/app/src/main/java/com/app/simplitend/patientprofile/medreminder/mvvm/ReminderAdapter.java +++ b/app/src/main/java/com/app/simplitend/patientprofile/medreminder/mvvm/ReminderAdapter.java @@ -136,7 +136,7 @@ public class ReminderAdapter extends RecyclerView.Adapter 0) { // reminders are present + + // updating global list of activities for today's day + if (routineViewModel.selected_dow == 0) { + CaregiverMainViewModel.activityList = routineList; + } + binding.routineRv.setVisibility(View.VISIBLE); binding.noData.setVisibility(View.GONE); diff --git a/app/src/main/java/com/app/simplitend/welcome/welcomepatient/fragments/SignInFragment.java b/app/src/main/java/com/app/simplitend/welcome/welcomepatient/fragments/SignInFragment.java index 95eb96d..66b440f 100644 --- a/app/src/main/java/com/app/simplitend/welcome/welcomepatient/fragments/SignInFragment.java +++ b/app/src/main/java/com/app/simplitend/welcome/welcomepatient/fragments/SignInFragment.java @@ -186,7 +186,6 @@ public class SignInFragment extends Fragment implements WelcomeContracts.Registe public void onResponse(PatientData patientResult, String token) { // caching user data PatientDataCache.setPatientData(patientResult); - AppUtil.savePatientData(token, patientResult.patientId, requireContext(), true); progressDialog.dismiss(); diff --git a/app/src/main/res/drawable/ic_cup.png b/app/src/main/res/drawable/ic_cup.png deleted file mode 100644 index df2110a4b8c82262dd62270ac94b9e1d930b8634..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14711 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 diff --git a/app/src/main/res/drawable/ic_med_cup.png b/app/src/main/res/drawable/ic_med_cup.png new file mode 100644 index 0000000000000000000000000000000000000000..e961f65ba4e591a87d710392b0b9e6381d1d4b9e GIT binary patch literal 21483 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 Cu#XV{ literal 0 HcmV?d00001