From d3d3aa9f9a708dc63c04cd5f662c55a3f9198d38 Mon Sep 17 00:00:00 2001 From: 14Sandee Date: Mon, 23 Oct 2023 18:22:06 +0530 Subject: [PATCH] . --- .idea/deploymentTargetDropDown.xml | 12 ++ .idea/misc.xml | 1 - app/src/main/AndroidManifest.xml | 6 +- .../simplitend/apputils/SimpliTendApp.java | 15 +++ .../DefaultLocationClient.java | 86 ++++++++++++++ .../locationupdates/LocationClient.java | 21 ++++ .../locationupdates/LocationService.java | 112 ++++++++++++++++++ .../patient_dashboard/DashBoardActivity.java | 12 +- .../PatientMainViewModel.java | 46 +++---- .../GeoFenceBroadcastReceiver.java | 14 +++ .../PatientLocationUpdatesReceiver.java | 2 +- .../layout/activity_cg_profile_progress.xml | 2 +- 12 files changed, 295 insertions(+), 34 deletions(-) create mode 100644 app/src/main/java/com/app/simplitend/locationupdates/DefaultLocationClient.java create mode 100644 app/src/main/java/com/app/simplitend/locationupdates/LocationClient.java create mode 100644 app/src/main/java/com/app/simplitend/locationupdates/LocationService.java diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 03d9c98..a6ac57b 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -1,6 +1,18 @@ + + + + + + + + + + + + diff --git a/.idea/misc.xml b/.idea/misc.xml index f920ea0..00aa3b7 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ - diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 95533dc..ba1f396 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,8 +6,9 @@ - + + + + diff --git a/app/src/main/java/com/app/simplitend/apputils/SimpliTendApp.java b/app/src/main/java/com/app/simplitend/apputils/SimpliTendApp.java index d5ef75f..6aee3d7 100644 --- a/app/src/main/java/com/app/simplitend/apputils/SimpliTendApp.java +++ b/app/src/main/java/com/app/simplitend/apputils/SimpliTendApp.java @@ -1,10 +1,15 @@ package com.app.simplitend.apputils; +import static com.app.simplitend.locationupdates.LocationService.LOCATION_NOTIFICATION_CHANNEL_ID; + import android.app.Application; +import android.app.NotificationChannel; +import android.app.NotificationManager; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; +import android.os.Build; import android.provider.MediaStore; import android.provider.Telephony; import android.util.Log; @@ -40,6 +45,16 @@ public class SimpliTendApp extends Application { } })); + // creating notification channel for location share location updates from patient side + // using a foreground service + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ + NotificationChannel channel = new NotificationChannel(LOCATION_NOTIFICATION_CHANNEL_ID, + "Location updates", + NotificationManager.IMPORTANCE_LOW); + + NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + notificationManager.createNotificationChannel(channel); + } } } \ No newline at end of file diff --git a/app/src/main/java/com/app/simplitend/locationupdates/DefaultLocationClient.java b/app/src/main/java/com/app/simplitend/locationupdates/DefaultLocationClient.java new file mode 100644 index 0000000..dc92668 --- /dev/null +++ b/app/src/main/java/com/app/simplitend/locationupdates/DefaultLocationClient.java @@ -0,0 +1,86 @@ +package com.app.simplitend.locationupdates; + +import static com.app.simplitend.patientgeofencing.PatientLocationUpdatesReceiver.LOCATION_REQUEST_TAG; + +import android.Manifest; +import android.content.Context; +import android.content.pm.PackageManager; +import android.location.Location; +import android.location.LocationManager; +import android.os.Looper; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; + +import com.google.android.gms.location.FusedLocationProviderClient; +import com.google.android.gms.location.LocationCallback; +import com.google.android.gms.location.LocationRequest; +import com.google.android.gms.location.LocationResult; +import com.google.android.gms.location.Priority; + +public class DefaultLocationClient implements LocationClient{ + + private final Context context; + private final FusedLocationProviderClient fusedLocationProviderClient; + + private LocationRequest locationRequest; + private LocationCallback locationCallback; + + public DefaultLocationClient(Context context, FusedLocationProviderClient fusedLocationProviderClient) { + this.context = context; + this.fusedLocationProviderClient = fusedLocationProviderClient; + } + + @Override + public void getLocationUpdates(long interval, @NonNull DefaultLocationUpdates defaultLocationUpdates) throws LocationException { + if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED + || ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + Log.e(LOCATION_REQUEST_TAG, "getLocationUpdates: NO LOCATION PERMISSION"); + throw new LocationException("NO LOCATION PERMISSION FROM USER"); + } + + LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + boolean isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); + boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); + + if (!isGpsEnabled && !isNetworkEnabled) { + LocationException locationException = new LocationException("GPS is off"); + Log.e(LOCATION_REQUEST_TAG, "getLocationUpdates: ", locationException); + throw locationException; + } + + locationRequest = new LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, interval) + .build(); + + locationCallback = new LocationCallback() { + @Override + public void onLocationResult(@NonNull LocationResult locationResult) { + super.onLocationResult(locationResult); + Location location; + if (locationResult.getLocations().isEmpty()) { + location = null; + } else { + location = locationResult.getLocations().get(locationResult.getLocations().size() - 1); + } + + defaultLocationUpdates.locationUpdates(location); + } + }; + + fusedLocationProviderClient.requestLocationUpdates(locationRequest, + locationCallback, Looper.getMainLooper()); + Log.d(LOCATION_REQUEST_TAG, "getLocationUpdates: RECEIVING LOCATION UPDATES AT EVERY " + interval + " millis"); + } + + public void removeLocationUpdates(){ + if (locationRequest != null && fusedLocationProviderClient != null && locationCallback != null){ + fusedLocationProviderClient.removeLocationUpdates(locationCallback) + .addOnCompleteListener(task -> { + if (task.isSuccessful()) { + Log.v(LOCATION_REQUEST_TAG, "onComplete: LOCATION UPDATES REMOVED"); + } + }); + } + } +} diff --git a/app/src/main/java/com/app/simplitend/locationupdates/LocationClient.java b/app/src/main/java/com/app/simplitend/locationupdates/LocationClient.java new file mode 100644 index 0000000..4d92097 --- /dev/null +++ b/app/src/main/java/com/app/simplitend/locationupdates/LocationClient.java @@ -0,0 +1,21 @@ +package com.app.simplitend.locationupdates; + +import android.location.Location; + +import androidx.annotation.NonNull; + +import kotlinx.coroutines.flow.Flow; + +public interface LocationClient { + void getLocationUpdates(long interval, @NonNull DefaultLocationUpdates defaultLocationUpdates) throws LocationException; + + class LocationException extends Exception{ + public LocationException(String message){ + super(message); + } + } + + interface DefaultLocationUpdates{ + void locationUpdates(Location location); + } +} diff --git a/app/src/main/java/com/app/simplitend/locationupdates/LocationService.java b/app/src/main/java/com/app/simplitend/locationupdates/LocationService.java new file mode 100644 index 0000000..54822c6 --- /dev/null +++ b/app/src/main/java/com/app/simplitend/locationupdates/LocationService.java @@ -0,0 +1,112 @@ +package com.app.simplitend.locationupdates; + +import static com.app.simplitend.patientgeofencing.PatientLocationUpdatesReceiver.LOCATION_EXTRA_KEY; +import static com.app.simplitend.patientgeofencing.PatientLocationUpdatesReceiver.LOCATION_REQUEST_TAG; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.Service; +import android.content.Intent; +import android.location.Location; +import android.os.IBinder; +import android.util.Log; + +import androidx.annotation.Nullable; +import androidx.core.app.NotificationCompat; + +import com.app.simplitend.R; +import com.app.simplitend.patientgeofencing.PatientLocationUpdatesReceiver; +import com.google.android.gms.location.LocationServices; + +public class LocationService extends Service implements LocationClient.DefaultLocationUpdates { + + public static final String ACTION_START_LOCATION_UPDATES = "com.simplitent.action_start_lu"; + public static final String ACTION_STOP_LOCATION_UPDATES = "com.simplitent.action.stop_lu"; + public static final String LOCATION_NOTIFICATION_CHANNEL_ID = "location"; + + public static final String LOCATION_UPDATE_MIN_INTERVAL = "min_interval"; + + public static final int LOCATION_INTERVAL_BASE_TIME = 25 * 1000; + + private DefaultLocationClient locationClient; + + @Override + public void onCreate() { + super.onCreate(); + locationClient = new DefaultLocationClient(this, + LocationServices.getFusedLocationProviderClient(this)); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + if (intent != null && intent.getAction() != null){ + switch (intent.getAction()){ + case ACTION_START_LOCATION_UPDATES: + int minInterval = intent.getIntExtra(LOCATION_UPDATE_MIN_INTERVAL, 0); + if (minInterval != 0){ + removeLocationUpdates(); + startLocationUpdates(minInterval); + } + break; + case ACTION_STOP_LOCATION_UPDATES: + stopLocationUpdates(); + break; + } + } + return super.onStartCommand(intent, flags, startId); + } + + private void stopLocationUpdates() { + stopForeground(true); + stopSelf(); + removeLocationUpdates(); + } + + private void startLocationUpdates(int minInterval){ + Notification notification = new NotificationCompat.Builder(this, LOCATION_NOTIFICATION_CHANNEL_ID) + .setContentTitle("SimpliTend is sharing your current location") + .setSmallIcon(R.mipmap.ic_launcher_round) + .setOngoing(true) + .build(); + + NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + + try { + locationClient.getLocationUpdates(minInterval, this); + } catch (LocationClient.LocationException e) { + // do nothing + } + + startForeground(1, notification); + notificationManager.notify(1, notification); + } + + @Override + public void onDestroy() { + super.onDestroy(); + Log.d(LOCATION_REQUEST_TAG, "onDestroy: SERVICE DESTROYED"); + // stop the location updates + stopForeground(true); + stopSelf(); + removeLocationUpdates(); + } + + public void removeLocationUpdates(){ + if (locationClient != null){ + locationClient.removeLocationUpdates(); + } + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public void locationUpdates(Location location) { + Intent intent = new Intent(this, PatientLocationUpdatesReceiver.class); + intent.putExtra(LOCATION_EXTRA_KEY, location); + sendBroadcast(intent); + } +} diff --git a/app/src/main/java/com/app/simplitend/patient_dashboard/DashBoardActivity.java b/app/src/main/java/com/app/simplitend/patient_dashboard/DashBoardActivity.java index 405e99f..cbd62de 100644 --- a/app/src/main/java/com/app/simplitend/patient_dashboard/DashBoardActivity.java +++ b/app/src/main/java/com/app/simplitend/patient_dashboard/DashBoardActivity.java @@ -24,6 +24,7 @@ import com.app.simplitend.apputils.AppUtil; import com.app.simplitend.apputils.PatientDataCache; import com.app.simplitend.caregiverdashboard.mvvm.CgHomeContracts; import com.app.simplitend.caregiverdashboard.mvvm.models.GeoFenceDetails; +import com.app.simplitend.locationupdates.LocationService; public class DashBoardActivity extends AppCompatActivity implements CgHomeContracts.GetGeoFenceCallback { @@ -60,6 +61,9 @@ public class DashBoardActivity extends AppCompatActivity implements CgHomeContra } else { setGeofenceAndLocationUpdates(); } + + // getting location updates + viewModel.addLocationUpdates(this); } else { // permission denied AppUtil.showAlert(this, @@ -106,15 +110,9 @@ public class DashBoardActivity extends AppCompatActivity implements CgHomeContra viewModel.getGeoFenceDetails(AppUtil.getPatientUid(this) + "", "", "Bearer " + AppUtil.getPatientToken(this), this); - - if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - return; - } - - viewModel.addLocationUpdates(this); } - private void validateAndAddGeofence(GeoFenceDetails geoFenceDetails) { + public void validateAndAddGeofence(GeoFenceDetails geoFenceDetails) { if (geoFenceDetails.radius != null && geoFenceDetails.type != null) { PatientDataCache.getPatientData(this, (patientData -> { if (patientData != null) { 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 ab8a1bf..2218c60 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 @@ -1,5 +1,8 @@ package com.app.simplitend.patient_dashboard; +import static android.content.Context.*; +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_ID; import static com.app.simplitend.patientgeofencing.GeoFenceHelper.GEOFENCE_TAG; import static com.app.simplitend.patientgeofencing.PatientLocationUpdatesReceiver.LOCATION_REQUEST_TAG; @@ -7,13 +10,16 @@ import static com.app.simplitend.patientgeofencing.PatientLocationUpdatesReceive import android.Manifest; import android.app.Activity; +import android.app.ActivityManager; import android.app.PendingIntent; +import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.util.Log; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.RequiresPermission; @@ -28,6 +34,7 @@ import com.app.simplitend.caregiverdashboard.mvvm.CgHomeContracts; import com.app.simplitend.caregiverdashboard.mvvm.CgHomeRepository; import com.app.simplitend.caregiverdashboard.mvvm.NotificationApiService; import com.app.simplitend.caregiverdashboard.mvvm.models.GeoFenceDetails; +import com.app.simplitend.locationupdates.LocationService; import com.app.simplitend.patientgeofencing.GeoFenceHelper; import com.app.simplitend.patientgeofencing.PatientLocationUpdatesReceiver; import com.app.simplitend.patientprofile.PatientProfileAPIService; @@ -99,31 +106,24 @@ public class PatientMainViewModel extends ViewModel { @RequiresPermission(Manifest.permission.ACCESS_FINE_LOCATION) public void addLocationUpdates(Activity activity) { - Log.d(LOCATION_REQUEST_TAG, "REQUESTING LOCATION UPDATES"); - FusedLocationProviderClient fusedLocationClient = LocationServices.getFusedLocationProviderClient(activity); - - LocationRequest locationRequest = new LocationRequest(); - locationRequest.setInterval(10_000); - locationRequest.setSmallestDisplacement(15); - locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); - - Intent intent = new Intent(activity, PatientLocationUpdatesReceiver.class); - PendingIntent pendingIntent ; - - if(Build.VERSION.SDK_INT > 30){ - pendingIntent = PendingIntent.getBroadcast(activity, LOCATION_UPDATES_REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); - } else{ - pendingIntent = PendingIntent.getBroadcast(activity, LOCATION_UPDATES_REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT); + if (!isLocationServiceRunning(activity)) { + Log.d(LOCATION_REQUEST_TAG, "REQUESTING LOCATION UPDATES"); + Toast.makeText(activity, "Location updates started", Toast.LENGTH_SHORT).show(); + Intent intent = new Intent(activity, LocationService.class); + intent.setAction(LocationService.ACTION_START_LOCATION_UPDATES); + intent.putExtra(LOCATION_UPDATE_MIN_INTERVAL, LOCATION_INTERVAL_BASE_TIME); + activity.startService(intent); } + } - fusedLocationClient.requestLocationUpdates(locationRequest, pendingIntent) - .addOnCompleteListener(task -> { - if (task.isSuccessful() && task.getException() == null){ - Log.d(LOCATION_REQUEST_TAG, "LOCATION UPDATES ADDED"); - }else{ - Log.d(LOCATION_REQUEST_TAG, "CANNOT ADD LOCATION UPDATES " + task.getException()); - } - }); + public boolean isLocationServiceRunning(Activity activity){ + ActivityManager activityManager = (ActivityManager) activity.getSystemService(ACTIVITY_SERVICE); + for(ActivityManager.RunningServiceInfo service: activityManager.getRunningServices(Integer.MAX_VALUE)) { + if(LocationService.class.getName().equals(service.service.getClassName())) { + return true; + } + } + return false; } public void getGeoFenceDetails(String p_id, 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 8af0e19..4fa4cff 100644 --- a/app/src/main/java/com/app/simplitend/patientgeofencing/GeoFenceBroadcastReceiver.java +++ b/app/src/main/java/com/app/simplitend/patientgeofencing/GeoFenceBroadcastReceiver.java @@ -5,6 +5,7 @@ import android.content.Context; import android.content.Intent; 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 com.app.simplitend.apputils.AppUtil; @@ -12,6 +13,8 @@ import com.app.simplitend.apputils.RetrofitHelper; import com.app.simplitend.caregiverdashboard.mvvm.NotificationApiService; 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 java.util.HashMap; @@ -40,6 +43,11 @@ public class GeoFenceBroadcastReceiver extends BroadcastReceiver { break; case Geofence.GEOFENCE_TRANSITION_ENTER: 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 + ); + context.startService(locationServiceIntent); break; case Geofence.GEOFENCE_TRANSITION_EXIT: Log.d(GEOFENCE_TAG, "onReceive: EXIT"); @@ -72,5 +80,11 @@ public class GeoFenceBroadcastReceiver extends BroadcastReceiver { } }); + // 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 + context.startService(intent); + } } \ No newline at end of file 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 cb1678d..c37d66b 100644 --- a/app/src/main/java/com/app/simplitend/patientgeofencing/PatientLocationUpdatesReceiver.java +++ b/app/src/main/java/com/app/simplitend/patientgeofencing/PatientLocationUpdatesReceiver.java @@ -26,7 +26,7 @@ import retrofit2.Response; public class PatientLocationUpdatesReceiver extends BroadcastReceiver { public static final String LOCATION_REQUEST_TAG = "LOCATION_REQUEST_TAG"; - private static final String LOCATION_EXTRA_KEY = "com.google.android.location.LOCATION"; + public static final String LOCATION_EXTRA_KEY = "com.google.android.location.LOCATION"; public static final int LOCATION_UPDATES_REQUEST_CODE = 1010; @Override diff --git a/app/src/main/res/layout/activity_cg_profile_progress.xml b/app/src/main/res/layout/activity_cg_profile_progress.xml index 5cdcb28..9ed2f93 100644 --- a/app/src/main/res/layout/activity_cg_profile_progress.xml +++ b/app/src/main/res/layout/activity_cg_profile_progress.xml @@ -36,7 +36,7 @@