From f4b6d7a33233b6b51d2b17d4ef1dccdd32582541 Mon Sep 17 00:00:00 2001 From: estevez-dev Date: Mon, 20 Jul 2020 16:23:12 +0300 Subject: [PATCH] Location requests through foreground service --- android/app/src/main/AndroidManifest.xml | 4 + .../hassclient/LocationRequestService.java | 146 ++++++++++++++++++ .../hassclient/LocationUpdatesService.java | 14 +- .../hassclient/LocationUtils.java | 31 +++- 4 files changed, 185 insertions(+), 10 deletions(-) create mode 100644 android/app/src/main/java/com/keyboardcrumbs/hassclient/LocationRequestService.java diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index a36dfda..688d50b 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -60,6 +60,10 @@ android:name=".LocationUpdatesService" android:enabled="true" android:exported="false" /> + diff --git a/android/app/src/main/java/com/keyboardcrumbs/hassclient/LocationRequestService.java b/android/app/src/main/java/com/keyboardcrumbs/hassclient/LocationRequestService.java new file mode 100644 index 0000000..f617756 --- /dev/null +++ b/android/app/src/main/java/com/keyboardcrumbs/hassclient/LocationRequestService.java @@ -0,0 +1,146 @@ +package com.keyboardcrumbs.hassclient; + +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.Service; +import android.content.Intent; +import android.location.Location; +import android.os.Build; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.os.Looper; +import android.util.Log; + +import androidx.annotation.Nullable; +import androidx.work.Constraints; +import androidx.work.Data; +import androidx.work.ExistingWorkPolicy; +import androidx.work.NetworkType; +import androidx.work.OneTimeWorkRequest; +import androidx.work.WorkManager; + +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.LocationServices; + +public class LocationRequestService extends Service { + + private static final String TAG = LocationRequestService.class.getSimpleName(); + + private NotificationManager mNotificationManager; + + private LocationRequest mLocationRequest; + + private FusedLocationProviderClient mFusedLocationClient; + + private LocationCallback mLocationCallback; + + private Handler mServiceHandler; + + public LocationRequestService() { + } + + @Override + public void onCreate() { + mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this); + + mLocationCallback = new LocationCallback() { + @Override + public void onLocationResult(LocationResult locationResult) { + super.onLocationResult(locationResult); + onNewLocation(locationResult.getLastLocation()); + } + }; + + mLocationRequest = new LocationRequest(); + + HandlerThread handlerThread = new HandlerThread(TAG); + handlerThread.start(); + mServiceHandler = new Handler(handlerThread.getLooper()); + mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + CharSequence name = "Location requests"; + NotificationChannel mChannel = + new NotificationChannel(LocationUtils.ONETIME_NOTIFICATION_CHANNEL_ID, name, NotificationManager.IMPORTANCE_LOW); + + mNotificationManager.createNotificationChannel(mChannel); + } + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Log.i(TAG, "Service started. startId="+startId); + + requestLocationUpdates(); + + return START_STICKY; + } + + @Override + public void onDestroy() { + try { + mFusedLocationClient.removeLocationUpdates(mLocationCallback); + } catch (SecurityException unlikely) { + //When we lost permission + Log.i(TAG, "No location permission"); + } + mServiceHandler.removeCallbacksAndMessages(null); + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } + + private void requestLocationUpdates() { + Log.i(TAG, "Requesting location update in 5 seconds."); + mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); + mLocationRequest.setInterval(5000); + + startForeground(LocationUtils.ONETIME_NOTIFICATION_ID, LocationUtils.getRequestNotification(this, null, LocationUtils.ONETIME_NOTIFICATION_CHANNEL_ID)); + try { + mFusedLocationClient.requestLocationUpdates(mLocationRequest, + mLocationCallback, Looper.myLooper()); + } catch (SecurityException unlikely) { + stopSelf(); + } + } + + private void onNewLocation(Location location) { + Log.i(TAG, "New location: " + location); + + mNotificationManager.notify(LocationUtils.ONETIME_NOTIFICATION_ID, LocationUtils.getRequestNotification( + this, + location, + LocationUtils.ONETIME_NOTIFICATION_CHANNEL_ID + )); + + Constraints constraints = new Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build(); + + Data locationData = new Data.Builder() + .putInt(SendDataHomeWorker.DATA_TYPE_KEY, SendDataHomeWorker.DATA_TYPE_LOCATION) + .putDouble("Lat", location.getLatitude()) + .putDouble("Long", location.getLongitude()) + .putFloat("Acc", location.getAccuracy()) + .build(); + + + OneTimeWorkRequest uploadWorkRequest = + new OneTimeWorkRequest.Builder(SendDataHomeWorker.class) + .setConstraints(constraints) + .setInputData(locationData) + .build(); + + WorkManager + .getInstance(getApplicationContext()) + .enqueueUniqueWork("SendLocationUpdate", ExistingWorkPolicy.REPLACE, uploadWorkRequest); + stopSelf(); + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/keyboardcrumbs/hassclient/LocationUpdatesService.java b/android/app/src/main/java/com/keyboardcrumbs/hassclient/LocationUpdatesService.java index 365a46e..fed23c9 100644 --- a/android/app/src/main/java/com/keyboardcrumbs/hassclient/LocationUpdatesService.java +++ b/android/app/src/main/java/com/keyboardcrumbs/hassclient/LocationUpdatesService.java @@ -12,7 +12,6 @@ import android.os.IBinder; import android.os.Looper; import androidx.annotation.Nullable; -import androidx.work.BackoffPolicy; import androidx.work.Constraints; import androidx.work.Data; import androidx.work.ExistingWorkPolicy; @@ -28,8 +27,6 @@ import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationResult; import com.google.android.gms.location.LocationServices; -import java.util.concurrent.TimeUnit; - public class LocationUpdatesService extends Service { private static final String TAG = LocationUpdatesService.class.getSimpleName(); @@ -77,7 +74,7 @@ public class LocationUpdatesService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { - Log.i(TAG, "Service started"); + Log.i(TAG, "Service started. startId="+startId); requestLocationUpdates(); @@ -110,9 +107,10 @@ public class LocationUpdatesService extends Service { } else { priority = LocationRequest.PRIORITY_HIGH_ACCURACY; } + Log.i(TAG, "Requesting location updates. Every " + requestInterval + "ms with priority of " + priority); mLocationRequest.setPriority(priority); mLocationRequest.setInterval(requestInterval); - Log.i(TAG, "Requesting location updates. Every " + requestInterval + "ms with priority of " + priority); + startForeground(LocationUtils.SERVICE_NOTIFICATION_ID, LocationUtils.getNotification(this, null, LocationUtils.SERVICE_NOTIFICATION_CHANNEL_ID)); try { mFusedLocationClient.requestLocationUpdates(mLocationRequest, @@ -125,7 +123,11 @@ public class LocationUpdatesService extends Service { private void onNewLocation(Location location) { Log.i(TAG, "New location: " + location); - mNotificationManager.notify(LocationUtils.SERVICE_NOTIFICATION_ID, LocationUtils.getNotification(this, location, LocationUtils.SERVICE_NOTIFICATION_CHANNEL_ID)); + mNotificationManager.notify(LocationUtils.SERVICE_NOTIFICATION_ID, LocationUtils.getNotification( + this, + location, + LocationUtils.SERVICE_NOTIFICATION_CHANNEL_ID + )); Constraints constraints = new Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) diff --git a/android/app/src/main/java/com/keyboardcrumbs/hassclient/LocationUtils.java b/android/app/src/main/java/com/keyboardcrumbs/hassclient/LocationUtils.java index e1fcaeb..a0e024d 100644 --- a/android/app/src/main/java/com/keyboardcrumbs/hassclient/LocationUtils.java +++ b/android/app/src/main/java/com/keyboardcrumbs/hassclient/LocationUtils.java @@ -28,6 +28,8 @@ class LocationUtils { static final int WORKER_NOTIFICATION_ID = 954322; static final String SERVICE_NOTIFICATION_CHANNEL_ID = "location_service"; static final int SERVICE_NOTIFICATION_ID = 954311; + static final String ONETIME_NOTIFICATION_CHANNEL_ID = "location_request"; + static final int ONETIME_NOTIFICATION_ID = 954333; static final String REQUEST_LOCATION_NOTIFICATION = "request_location_update"; @@ -89,15 +91,17 @@ class LocationUtils { } static void requestLocationOnce(Context context) { - OneTimeWorkRequest oneTimeWork = new OneTimeWorkRequest.Builder(LocationUpdatesWorker.class) - .build(); - WorkManager.getInstance(context).enqueueUniqueWork(LocationUtils.LOCATION_REQUEST_NAME, ExistingWorkPolicy.REPLACE, oneTimeWork); + Intent myService = new Intent(context, LocationRequestService.class); + context.startService(myService); + //OneTimeWorkRequest oneTimeWork = new OneTimeWorkRequest.Builder(LocationUpdatesWorker.class) + // .build(); + //WorkManager.getInstance(context).enqueueUniqueWork(LocationUtils.LOCATION_REQUEST_NAME, ExistingWorkPolicy.REPLACE, oneTimeWork); } static Notification getNotification(Context context, Location location, String channelId) { CharSequence title = "Location tracking"; CharSequence text = location == null ? "Accuracy: unknown" : "Accuracy: " + location.getAccuracy() + " m"; - CharSequence bigText = location == null ? "Waiting for location..." : "Location updated at " + DateFormat.getDateTimeInstance().format(new Date(location.getTime())) + + CharSequence bigText = location == null ? "Waiting for location..." : "Time: " + DateFormat.getDateTimeInstance().format(new Date(location.getTime())) + System.getProperty("line.separator") + "Accuracy: " + location.getAccuracy() + " m" + System.getProperty("line.separator") + "Location: " + location.getLatitude() + ", " + location.getLongitude(); @@ -117,4 +121,23 @@ class LocationUtils { return builder.build(); } + + static Notification getRequestNotification(Context context, Location location, String channelId) { + CharSequence title = "Updating location..."; + CharSequence text = location == null ? "Waiting for location..." : "Accuracy: " + location.getAccuracy() + " m"; + + PendingIntent activityPendingIntent = PendingIntent.getActivity(context, 0, + new Intent(context, MainActivity.class), 0); + + NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId) + .setContentIntent(activityPendingIntent) + .setContentTitle(title) + .setContentText(text) + .setPriority(-1) + .setOngoing(true) + .setSmallIcon(R.drawable.mini_icon_location) + .setWhen(System.currentTimeMillis()); + + return builder.build(); + } }