package com.amazonaws.mobileconnectors.geo.tracker; import android.annotation.SuppressLint; import android.app.ActivityManager; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.location.Location; import android.location.LocationManager; import android.os.Binder; 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.NonNull; import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import com.amazonaws.services.geo.R; 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; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; public class TrackingService extends Service { private static final String TAG = TrackingService.class.getSimpleName(); private static final String CHANNEL_ID = "AWS_TRACKING_CHANNEL_ID"; private static final int NOTIFICATION_ID = 14789124; private final IBinder binder = new LocalBinder(); private NotificationManager notificationManager; private FusedLocationProviderClient fusedLocationProviderClient; private LocationCallback locationCallback; @Override public void onCreate() { super.onCreate(); Log.d(TAG, "TrackingService onCreate triggered"); notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel notificationChannel = new NotificationChannel( CHANNEL_ID, "AWS Location Tracking Service", NotificationManager.IMPORTANCE_DEFAULT); notificationManager.createNotificationChannel(notificationChannel); } } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "TrackingService onStartCommand triggered"); super.onStartCommand(intent, flags, startId); return START_NOT_STICKY; } @Override public void onDestroy() { Log.d(TAG, "TrackingService onDestroy triggered"); super.onDestroy(); stopLocationUpdates(); } @Nullable @Override public IBinder onBind(Intent intent) { Log.d(TAG, "TrackingService onBind triggered"); return binder; } @Override public boolean onUnbind(Intent intent) { Log.d(TAG, "TrackingService onUnbind triggered"); return super.onUnbind(intent); } @SuppressLint("MissingPermission") // Developer's responsibility to add location permissions to their app. public void startLocationUpdates(final Long interval, final TrackingServiceListener listener) { // Bring the service to the foreground, displaying the proper notification startForeground(NOTIFICATION_ID, getNotification()); try { // Make a getLastKnownLocation call on the location manager to simply detect if proper permissions // are present LocationManager locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE); locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(getApplicationContext()); LocationRequest request = new LocationRequest(); request.setInterval(interval); request.setFastestInterval(interval); request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); locationCallback = new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { super.onLocationResult(locationResult); listener.onLocationReceived(locationResult.getLastLocation()); } }; fusedLocationProviderClient.requestLocationUpdates(request, locationCallback, Looper.myLooper()); } catch (Exception exception) { listener.onError(TrackingError.missingLocationPermissions()); } } public void stopLocationUpdates() { try { fusedLocationProviderClient.removeLocationUpdates(locationCallback); stopForeground(true); } catch (SecurityException unlikely) { // Location permissions were manually revoked and thus were unable to stop location updates. // However we currently don't have a callback for stopTracking and don't think this is worth // adding one for. } } private Notification getNotification() { NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setContentTitle("Location tracking") .setOngoing(true) .setPriority(Notification.PRIORITY_HIGH) .setWhen(System.currentTimeMillis()); // Set the Channel ID for Android O. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { builder.setChannelId(CHANNEL_ID); // Channel ID } return builder.build(); } public class LocalBinder extends Binder { public TrackingService getService() { return TrackingService.this; } } }