Location requests through foreground service
This commit is contained in:
parent
f87cff7a7e
commit
f4b6d7a332
@ -60,6 +60,10 @@
|
|||||||
android:name=".LocationUpdatesService"
|
android:name=".LocationUpdatesService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
<service
|
||||||
|
android:name=".LocationRequestService"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="false" />
|
||||||
<receiver android:name=".NotificationActionReceiver" android:exported="true">
|
<receiver android:name=".NotificationActionReceiver" android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,6 @@ import android.os.IBinder;
|
|||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.work.BackoffPolicy;
|
|
||||||
import androidx.work.Constraints;
|
import androidx.work.Constraints;
|
||||||
import androidx.work.Data;
|
import androidx.work.Data;
|
||||||
import androidx.work.ExistingWorkPolicy;
|
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.LocationResult;
|
||||||
import com.google.android.gms.location.LocationServices;
|
import com.google.android.gms.location.LocationServices;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
public class LocationUpdatesService extends Service {
|
public class LocationUpdatesService extends Service {
|
||||||
|
|
||||||
private static final String TAG = LocationUpdatesService.class.getSimpleName();
|
private static final String TAG = LocationUpdatesService.class.getSimpleName();
|
||||||
@ -77,7 +74,7 @@ public class LocationUpdatesService extends Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
Log.i(TAG, "Service started");
|
Log.i(TAG, "Service started. startId="+startId);
|
||||||
|
|
||||||
requestLocationUpdates();
|
requestLocationUpdates();
|
||||||
|
|
||||||
@ -110,9 +107,10 @@ public class LocationUpdatesService extends Service {
|
|||||||
} else {
|
} else {
|
||||||
priority = LocationRequest.PRIORITY_HIGH_ACCURACY;
|
priority = LocationRequest.PRIORITY_HIGH_ACCURACY;
|
||||||
}
|
}
|
||||||
|
Log.i(TAG, "Requesting location updates. Every " + requestInterval + "ms with priority of " + priority);
|
||||||
mLocationRequest.setPriority(priority);
|
mLocationRequest.setPriority(priority);
|
||||||
mLocationRequest.setInterval(requestInterval);
|
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));
|
startForeground(LocationUtils.SERVICE_NOTIFICATION_ID, LocationUtils.getNotification(this, null, LocationUtils.SERVICE_NOTIFICATION_CHANNEL_ID));
|
||||||
try {
|
try {
|
||||||
mFusedLocationClient.requestLocationUpdates(mLocationRequest,
|
mFusedLocationClient.requestLocationUpdates(mLocationRequest,
|
||||||
@ -125,7 +123,11 @@ public class LocationUpdatesService extends Service {
|
|||||||
private void onNewLocation(Location location) {
|
private void onNewLocation(Location location) {
|
||||||
Log.i(TAG, "New 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()
|
Constraints constraints = new Constraints.Builder()
|
||||||
.setRequiredNetworkType(NetworkType.CONNECTED)
|
.setRequiredNetworkType(NetworkType.CONNECTED)
|
||||||
|
@ -28,6 +28,8 @@ class LocationUtils {
|
|||||||
static final int WORKER_NOTIFICATION_ID = 954322;
|
static final int WORKER_NOTIFICATION_ID = 954322;
|
||||||
static final String SERVICE_NOTIFICATION_CHANNEL_ID = "location_service";
|
static final String SERVICE_NOTIFICATION_CHANNEL_ID = "location_service";
|
||||||
static final int SERVICE_NOTIFICATION_ID = 954311;
|
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";
|
static final String REQUEST_LOCATION_NOTIFICATION = "request_location_update";
|
||||||
|
|
||||||
@ -89,15 +91,17 @@ class LocationUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void requestLocationOnce(Context context) {
|
static void requestLocationOnce(Context context) {
|
||||||
OneTimeWorkRequest oneTimeWork = new OneTimeWorkRequest.Builder(LocationUpdatesWorker.class)
|
Intent myService = new Intent(context, LocationRequestService.class);
|
||||||
.build();
|
context.startService(myService);
|
||||||
WorkManager.getInstance(context).enqueueUniqueWork(LocationUtils.LOCATION_REQUEST_NAME, ExistingWorkPolicy.REPLACE, oneTimeWork);
|
//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) {
|
static Notification getNotification(Context context, Location location, String channelId) {
|
||||||
CharSequence title = "Location tracking";
|
CharSequence title = "Location tracking";
|
||||||
CharSequence text = location == null ? "Accuracy: unknown" : "Accuracy: " + location.getAccuracy() + " m";
|
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") + "Accuracy: " + location.getAccuracy() + " m" +
|
||||||
System.getProperty("line.separator") + "Location: " + location.getLatitude() + ", " + location.getLongitude();
|
System.getProperty("line.separator") + "Location: " + location.getLatitude() + ", " + location.getLongitude();
|
||||||
|
|
||||||
@ -117,4 +121,23 @@ class LocationUtils {
|
|||||||
|
|
||||||
return builder.build();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user