I am really stuck at this point.Geofence really works fine when app is in forground that is notification comes properly. but when app goes is in background notification not comes.
I want like this when app is in background my geofence never expired and and get notified if user is outside the fence.
Also attached the code below:-
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener,
ResultCallback<Status> {
protected static final int REQUEST_CHECK_SETTINGS = 0x1;
GoogleApiClient googleApiClient;
private MapFragment mapFragment;
private static final String TAG = MainActivity.class.getSimpleName();
private GoogleMap map;
private Location lastLocation;
private static final String NOTIFICATION_MSG = "NOTIFICATION MSG";
SharedPreferences pref;
SharedPreferences.Editor editor;
public static Intent makeNotificationIntent(Context context, String msg) {
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra(NOTIFICATION_MSG, msg);
return intent;
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_geofence);
pref = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
editor = pref.edit();
initGMaps();
createGoogleApi();
}
private void initGMaps() {
//mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
//mapFragment.getMapAsync(this);
}
private void createGoogleApi() {
Log.d(TAG, "createGoogleApi()");
if (googleApiClient == null) {
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
}
#Override
protected void onStart() {
super.onStart();
googleApiClient.connect();
settingsrequest();
}
public void settingsrequest() {
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(30 * 1000);
locationRequest.setFastestInterval(5 * 1000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
builder.setAlwaysShow(true); //this is the key ingredient
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
final LocationSettingsStates state = result.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
break;
}
}
});
}
#Override
protected void onStop() {
super.onStop();
// Disconnect GoogleApiClient when stopping Activity
googleApiClient.disconnect();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
// Check for the integer request code originally supplied to startResolutionForResult().
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
startLocationUpdates();
break;
case Activity.RESULT_CANCELED:
settingsrequest();//keep asking if imp or do whatever
break;
}
break;
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
// googleApiClient.disconnect();
Log.i(TAG, "onConnected()");
getLastKnownLocation();
//recoverGeofenceMarker();
startGeofence();
}
private final int REQ_PERMISSION = 999;
// Check for permission to access Location
private boolean checkPermission() {
Log.d(TAG, "checkPermission()");
// Ask for permission if it wasn't granted yet
return (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED);
}
// Asks for permission
private void askPermission() {
Log.d(TAG, "askPermission()");
ActivityCompat.requestPermissions(
this,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
REQ_PERMISSION
);
}
private void getLastKnownLocation() {
Log.d(TAG, "getLastKnownLocation()");
if (checkPermission()) {
lastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (lastLocation != null) {
Log.i(TAG, "LasKnown location. " +
"Long: " + lastLocation.getLongitude() +
" | Lat: " + lastLocation.getLatitude());
writeLastLocation();
startLocationUpdates();
} else {
Log.w(TAG, "No location retrieved yet");
startLocationUpdates();
}
} else askPermission();
}
private void writeActualLocation(Location location) {
//textLat.setText("Lat: " + location.getLatitude());
//textLong.setText("Long: " + location.getLongitude());
markerLocation(new LatLng(location.getLatitude(), location.getLongitude()));
}
private void writeLastLocation() {
writeActualLocation(lastLocation);
}
private Marker locationMarker;
private void markerLocation(LatLng latLng) {
Log.i(TAG, "markerLocation(" + latLng + ")");
String title = latLng.latitude + ", " + latLng.longitude;
MarkerOptions markerOptions = new MarkerOptions()
.position(latLng)
.title(title);
if (map != null) {
if (locationMarker != null)
locationMarker.remove();
locationMarker = map.addMarker(markerOptions);
float zoom = 14f;
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, zoom);
map.animateCamera(cameraUpdate);
}
}
// Start Geofence creation process
private void startGeofence() {
Log.i(TAG, "startGeofence()");
Geofence geofence = createGeofence();
GeofencingRequest geofenceRequest = createGeofenceRequest(geofence);
addGeofence(geofenceRequest);
}
private static final long GEO_DURATION = 60 * 60 * 1000;
private static final String GEOFENCE_REQ_ID = "My Geofence";
private static final float GEOFENCE_RADIUS = 500.0f; // in meters
// Create a Geofence
private Geofence createGeofence() {
Log.d(TAG, "createGeofence");
//Intent i = getIntent();
//double la = i.getDoubleExtra("latitude", 0);
//double lo = i.getDoubleExtra("longitude", 0);
return new Geofence.Builder()
.setRequestId(GEOFENCE_REQ_ID)
.setCircularRegion(18.457532, 73.867746, GEOFENCE_RADIUS)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_EXIT)
.build();
}
// Create a Geofence Request
private GeofencingRequest createGeofenceRequest(Geofence geofence) {
Log.d(TAG, "createGeofenceRequest");
return new GeofencingRequest.Builder()
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_EXIT)
.addGeofence(geofence)
.build();
}
private PendingIntent geoFencePendingIntent;
private static final int GEOFENCE_REQ_CODE = 0;
private PendingIntent createGeofencePendingIntent() {
Log.d(TAG, "createGeofencePendingIntent");
if (geoFencePendingIntent != null)
return geoFencePendingIntent;
Intent intent = new Intent("com.aol.android.geofence.ACTION_RECEIVE_GEOFENCE");
return PendingIntent.getBroadcast(
this, GEOFENCE_REQ_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
// Add the created GeofenceRequest to the device's monitoring list
private void addGeofence(GeofencingRequest request) {
Log.d(TAG, "addGeofence");
if (checkPermission())
LocationServices.GeofencingApi.addGeofences(
googleApiClient,
request,
createGeofencePendingIntent()
).setResultCallback(this);
}
#Override
public void onConnectionSuspended(int i) {
Log.w(TAG, "onConnectionSuspended()");
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.w(TAG, "onConnectionFailed()");
}
private LocationRequest locationRequest;
// Defined in mili seconds.
// This number in extremely low, and should be used only for debug
private final int UPDATE_INTERVAL = 1000;
private final int FASTEST_INTERVAL = 900;
// Start location Updates
private void startLocationUpdates() {
Log.i(TAG, "startLocationUpdates()");
locationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(UPDATE_INTERVAL)
.setFastestInterval(FASTEST_INTERVAL);
if (checkPermission())
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "onLocationChanged [" + location + "]");
lastLocation = location;
writeActualLocation(location);
}
#Override
public void onResult(#NonNull Status status) {
Log.i(TAG, "onResult: " + status);
if (status.isSuccess()) {
// saveGeofence();
//drawGeofence();
} else {
// inform about fail
}
}
}
also attached Reciever code:-
public class GeofenceReciever extends BroadcastReceiver {
private static final String TAG = "BootReceiver";
Context contextBootReceiver;
Intent intent;
public static final int GEOFENCE_NOTIFICATION_ID = 0;
SharedPreferences pref;
SharedPreferences.Editor editor;
#Override
public void onReceive(Context context, Intent intent) {
this.contextBootReceiver = context;
this.intent = intent;
pref = PreferenceManager.getDefaultSharedPreferences(context);
editor = pref.edit();
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
// Handling errors
if (geofencingEvent.hasError()) {
String errorMsg = getErrorString(geofencingEvent.getErrorCode());
Log.e(TAG, errorMsg);
return;
}
int geoFenceTransition = geofencingEvent.getGeofenceTransition();
// Check if the transition type is of interest
if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
// Get the geofence that were triggered
Log.d("Trnsition", "Exited");
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
String geofenceTransitionDetails = getGeofenceTrasitionDetails(geoFenceTransition, triggeringGeofences);
// Send notification details as a String
//if (feedback.equalsIgnoreCase("F;1;")) {
// String temp = feedback;
sendNotification(geofenceTransitionDetails);
}
}
private String getGeofenceTrasitionDetails(int geoFenceTransition, List<Geofence> triggeringGeofences) {
// get the ID of each geofence triggered
ArrayList<String> triggeringGeofencesList = new ArrayList<>();
for (Geofence geofence : triggeringGeofences) {
triggeringGeofencesList.add(geofence.getRequestId());
}
String status = "Some switches are on";
if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER)
System.out.println(status);
return status + TextUtils.join(", ", triggeringGeofencesList);
}
private void sendNotification(String msg) {
//intent = new Intent(contextBootReceiver, MainActivity.class);
//intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
//contextBootReceiver.startActivity(intent);
Log.i(TAG, "sendNotification: " + msg);
// Intent to start the main Activity
Intent notificationIntent = MainActivity.makeNotificationIntent(
contextBootReceiver, msg
);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(contextBootReceiver);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(notificationIntent);
PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
// Creating and sending Notification
NotificationManager notificatioMng =
(NotificationManager) contextBootReceiver.getSystemService(Context.NOTIFICATION_SERVICE);
notificatioMng.notify(
GEOFENCE_NOTIFICATION_ID,
createNotification(msg, notificationPendingIntent));
}
// Create notification
private Notification createNotification(String msg, PendingIntent notificationPendingIntent) {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(contextBootReceiver);
notificationBuilder
.setSmallIcon(R.drawable.ic_action_location)
.setColor(Color.RED)
.setContentTitle(msg)
.setContentText("Droidhomes Notification!")
.setContentIntent(notificationPendingIntent)
.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND)
.setAutoCancel(true);
return notificationBuilder.build();
}
private static String getErrorString(int errorCode) {
switch (errorCode) {
case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE:
return "GeoFence not available";
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
return "Too many GeoFences";
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
return "Too many pending intents";
default:
return "Unknown error.";
}
}
}
Write your service like this:
public class GeoFencingService extends Service{
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//write your notification code here
//use START_STICKY if you want your service keep running else use START_NOT_STICKY
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
//use this method to communicate with your activity
return null;
}
}
for detailed explanation have a look at these two links:
https://developer.android.com/guide/components/services.html
http://www.vogella.com/tutorials/AndroidServices/article.html
Let me know if any more help is required
Related
I am updating the location in the background every 5 minutes.
I checked below code in Android Oreo and above in Samsung and Motorola Devices. It is working fine. But when I checked in MI, OPPO and VIVO, location is not updating if I remove an application from recent task.
I checked this solution but didn't work.
public class GpsTracker extends Service
implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks, LocationListener {
final static int REQUEST_LOCATION = 199;
private static final String TAG = GpsTracker.class.getSimpleName();
private static final int PERMISSIONS_REQUEST_PLAYLOCATION = 2000;
private static final int PERMISSIONS_REQUEST_LOCATION = 2001;
public static boolean IS_SERVICE_RUNNING = false;
protected LocationManager locationManager;
private PowerManager pm;
private PowerManager.WakeLock wl;
private Handler handler = new Handler();
private boolean mPlayLocationPermissionGranted;
private boolean mLocationPermissionGranted;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private Location mCurrentLocation;
private LocationTypes locationTypes = LocationTypes.HEARTBEAT;
private GPSTrackerVM gpsTrackerVM;
private boolean noConnect = true;
private Runnable periodicUpdate = new Runnable() {
#Override
public void run() {
handler.postDelayed(periodicUpdate, 5 * 60 * 1000 - SystemClock.elapsedRealtime() % 1000);
// whatever you want to do below
Utils.Log(TAG, "run: Service");
locationTypes = LocationTypes.HEARTBEAT;
buildGoogleApiClient();
}
};
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction() != null) {
showNotification();
Utils.Log(TAG, "onStartCommand: " + intent.getAction());
switch (intent.getAction()) {
case AppConfig.ACTION.START_FOREGROUND_ACTION:
Utils.Log(TAG, "Uploading Start");
locationTypes = LocationTypes.HEARTBEAT;
handler.post(periodicUpdate);
break;
case AppConfig.ACTION.START_DAY:
locationTypes = LocationTypes.IN;
buildGoogleApiClient();
break;
case AppConfig.ACTION.END_DAY:
locationTypes = LocationTypes.OUT;
buildGoogleApiClient();
break;
}
}
return START_STICKY;
}
#Override
public void onCreate() {
gpsTrackerVM = new GPSTrackerVM(MyApp.getInstance());
pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyApp:GpsTracker");
wl.acquire();
}
#Override
public void onDestroy() {
IS_SERVICE_RUNNING = false;
super.onDestroy();
wl.release();
}
private void mStopService() {
Utils.Log(TAG, "Sync Stop");
if (handler != null) {
handler.removeCallbacks(periodicUpdate);
}
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
stopForeground(true);
stopSelf();
}
private void showNotification() {
if (!IS_SERVICE_RUNNING) {
String channelId = AppConfig.NOTIFICATION_ID.SYNC_CHANNEL;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
channelId = createmNotificationChannel();
}
Intent notificationIntent = new Intent();
notificationIntent.setAction(AppConfig.ACTION.MAIN_ACTION);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Bitmap icon = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_logo_notification);
Notification notification = new NotificationCompat.Builder(this, channelId)
.setContentTitle(getString(R.string.app_name))
.setTicker(getString(R.string.res_sync))
.setContentText(getString(R.string.res_sync))
.setSmallIcon(R.drawable.ic_logo_notification)
.setPriority(Notification.PRIORITY_DEFAULT)
.setLargeIcon(Bitmap.createScaledBitmap(icon, 128, 128, false))
.setContentIntent(pendingIntent)
.setOngoing(true)
.build();
startForeground(AppConfig.NOTIFICATION_ID.FOREGROUND_SERVICE_SYNC,
notification);
IS_SERVICE_RUNNING = true;
}
}
#RequiresApi(api = Build.VERSION_CODES.O)
private String createmNotificationChannel() {
String channelId = AppConfig.NOTIFICATION_ID.SYNC_CHANNEL;
String channelName = AppConfig.NOTIFICATION_ID.SYNC_CHANNEL;
NotificationChannel chan = new NotificationChannel(channelId,
channelName, NotificationManager.IMPORTANCE_DEFAULT);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
NotificationManager service = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
service.createNotificationChannel(chan);
return channelId;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
public synchronized void buildGoogleApiClient() {
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
retrieveCurrentLocation();
return;
}
mGoogleApiClient = new GoogleApiClient.Builder(MyApp.getInstance())
.addConnectionCallbacks(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
mGoogleApiClient.connect();
}
public synchronized void stopLocationUpdates() {
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
// mGoogleApiClient.disconnect();
}
}
private void createLocationRequest() {
long UPDATE_INTERVAL_IN_MILLISECONDS = 100000;
long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
UPDATE_INTERVAL_IN_MILLISECONDS / 2;
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
#Override
public void onConnected(#Nullable Bundle bundle) {
retrieveCurrentLocation();
}
private void retrieveCurrentLocation() {
Log.d(TAG, "retrieveCurrentLocation: 11");
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
// get GPS status
boolean checkGPS = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!checkGPS) {
Utils.Log(TAG, "retrieveCurrentLocation: GPS is Off");
updateCurrentLocation(null, "GPS is Turned Off");
return;
}
if (!hasLocationPermissions()) {
Utils.Log(TAG, "retrieveCurrentLocation: Location Permission Denied");
updateCurrentLocation(null, "Location Permission Denied");
return;
}
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient,
builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(#NonNull LocationSettingsResult result) {
mPlayLocationPermissionGranted = false;
final Status status = result.getStatus();
final LocationSettingsStates states = result.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
mPlayLocationPermissionGranted = true;
requestLocations();
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
mPlayLocationPermissionGranted = false;
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
Utils.Log(TAG, "retrieveCurrentLocation: GPS is On, but they need to allow location access from Settings");
updateCurrentLocation(null, "GPS is On, but they need to allow location access from Settings");
break;
}
}
});
}
private void requestLocations() {
Log.d(TAG, "requestLocations: 11");
try {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mCurrentLocation == null) {
noConnect = true;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (noConnect) {
updateCurrentLocation(null, "GPS is On, but your device needs one restart to continue locating the device.");
}
}
}, 1000);
}
// updateCurrentLocation(mCurrentLocation);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
mLocationRequest, this);
} catch (SecurityException ex) {
ex.printStackTrace();
}
}
private boolean hasLocationPermissions() {
if (ActivityCompat.checkSelfPermission(MyApp.getInstance(),
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED
&&
ActivityCompat.checkSelfPermission(MyApp.getInstance(),
Manifest.permission.ACCESS_COARSE_LOCATION)
== PackageManager.PERMISSION_GRANTED
) {
mLocationPermissionGranted = true;
} else {
mLocationPermissionGranted = false;
}
return mLocationPermissionGranted;
}
#Override
public void onLocationChanged(Location location) {
Utils.LogW(TAG, "onLocationChanged: " + location.toString());
if (noConnect) {
noConnect = false;
}
updateCurrentLocation(location, "None");
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.d(TAG, "onConnectionFailed: ");
}
#Override
public void onConnectionSuspended(int i) {
Log.d(TAG, "onConnectionSuspended: ");
}
public void updateCurrentLocation(Location location, String remark) {
mCurrentLocation = location;
GPSData gpsData = new GPSData(UUID.randomUUID().toString());
gpsData.setLatitude(location == null ? 0 : location.getLatitude());
gpsData.setLongitude(location == null ? 0 : location.getLongitude());
gpsData.setAddress("None");
gpsData.setRemarks(remark);
gpsData.setTimeStamp(System.currentTimeMillis() / 1000L);
gpsData.setLocationType(locationTypes.getValue());
// Log.w(TAG, "updateCurrentLocation: " + location);
stopLocationUpdates();
if (locationTypes == LocationTypes.IN) {
Utils.Log(TAG, "In Success ");
Intent startIntent = new Intent(this, GpsTracker.class);
startIntent.setAction(AppConfig.ACTION.START_FOREGROUND_ACTION);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(startIntent);
} else {
startService(startIntent);
}
} else if (locationTypes == LocationTypes.OUT) {
Utils.Log(TAG, "out Success ");
mStopService();
} else if (locationTypes == LocationTypes.HEARTBEAT) {
Utils.Log(TAG, "HEARTBEAT Success ");
}
serverUpdate(gpsData);
}
private void serverUpdate(GPSData gpsData) {
gpsTrackerVM.updateLocation(gpsData);
}
public void onPermissionGrantStatus(boolean isGratned) {
Log.d(TAG, "onPermissionGrantStatus() called with: isGratned = [" + isGratned + "]");
}
}
In AndroidManifest.xml
<service android:name=".services.GpsTracker" />
I am trying to implement Geofencing notifications, but they are not working, please help me identify the cause :
Here is my code :
This is my MainActivity :
public class MainActivity extends AppCompatActivity
implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener,
OnMapReadyCallback,
GoogleMap.OnMapClickListener,
GoogleMap.OnMarkerClickListener,
ResultCallback<Status> {
private static final String TAG = MainActivity.class.getSimpleName();
private GoogleMap map;
private GoogleApiClient googleApiClient;
private Location lastLocation;
private TextView textLat, textLong;
private MapFragment mapFragment;
private static final String NOTIFICATION_MSG = "NOTIFICATION MSG";
// Create a Intent send by the notification
public static Intent makeNotificationIntent(Context context, String msg) {
Intent intent = new Intent( context, MainActivity.class );
intent.putExtra( NOTIFICATION_MSG, msg );
return intent;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textLat = (TextView) findViewById(R.id.lat);
textLong = (TextView) findViewById(R.id.lon);
// initialize GoogleMaps
initGMaps();
// create GoogleApiClient
createGoogleApi();
}
// Create GoogleApiClient instance
private void createGoogleApi() {
Log.d(TAG, "createGoogleApi()");
if ( googleApiClient == null ) {
googleApiClient = new GoogleApiClient.Builder( this )
.addConnectionCallbacks( this )
.addOnConnectionFailedListener( this )
.addApi( LocationServices.API )
.build();
}
}
#Override
protected void onStart() {
super.onStart();
// Call GoogleApiClient connection when starting the Activity
googleApiClient.connect();
}
#Override
protected void onStop() {
super.onStop();
// Disconnect GoogleApiClient when stopping Activity
googleApiClient.disconnect();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate( R.menu.main_menu, menu );
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch ( item.getItemId() ) {
case R.id.geofence: {
startGeofence();
return true;
}
case R.id.clear: {
clearGeofence();
return true;
}
}
return super.onOptionsItemSelected(item);
}
private final int REQ_PERMISSION = 999;
// Check for permission to access Location
private boolean checkPermission() {
Log.d(TAG, "checkPermission()");
// Ask for permission if it wasn't granted yet
return (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED );
}
// Asks for permission
private void askPermission() {
Log.d(TAG, "askPermission()");
ActivityCompat.requestPermissions(
this,
new String[] { Manifest.permission.ACCESS_FINE_LOCATION },
REQ_PERMISSION
);
}
// Verify user's response of the permission requested
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
Log.d(TAG, "onRequestPermissionsResult()");
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch ( requestCode ) {
case REQ_PERMISSION: {
if ( grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED ){
// Permission granted
getLastKnownLocation();
} else {
// Permission denied
permissionsDenied();
}
break;
}
}
}
// App cannot work without the permissions
private void permissionsDenied() {
Log.w(TAG, "permissionsDenied()");
// TODO close app and warn user
}
// Initialize GoogleMaps
private void initGMaps(){
mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
// Callback called when Map is ready
#Override
public void onMapReady(GoogleMap googleMap) {
Log.d(TAG, "onMapReady()");
map = googleMap;
map.setOnMapClickListener(this);
map.setOnMarkerClickListener(this);
}
#Override
public void onMapClick(LatLng latLng) {
Log.d(TAG, "onMapClick("+latLng +")");
markerForGeofence(latLng);
}
#Override
public boolean onMarkerClick(Marker marker) {
Log.d(TAG, "onMarkerClickListener: " + marker.getPosition() );
return false;
}
private LocationRequest locationRequest;
// Defined in mili seconds.
// This number in extremely low, and should be used only for debug
private final int UPDATE_INTERVAL = 1000;
private final int FASTEST_INTERVAL = 900;
// Start location Updates
private void startLocationUpdates(){
Log.i(TAG, "startLocationUpdates()");
locationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(UPDATE_INTERVAL)
.setFastestInterval(FASTEST_INTERVAL);
if ( checkPermission() )
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "onLocationChanged ["+location+"]");
lastLocation = location;
writeActualLocation(location);
}
// GoogleApiClient.ConnectionCallbacks connected
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.i(TAG, "onConnected()");
getLastKnownLocation();
recoverGeofenceMarker();
}
// GoogleApiClient.ConnectionCallbacks suspended
#Override
public void onConnectionSuspended(int i) {
Log.w(TAG, "onConnectionSuspended()");
}
// GoogleApiClient.OnConnectionFailedListener fail
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.w(TAG, "onConnectionFailed()");
}
// Get last known location
private void getLastKnownLocation() {
Log.d(TAG, "getLastKnownLocation()");
if ( checkPermission() ) {
lastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if ( lastLocation != null ) {
Log.i(TAG, "LasKnown location. " +
"Long: " + lastLocation.getLongitude() +
" | Lat: " + lastLocation.getLatitude());
writeLastLocation();
startLocationUpdates();
} else {
Log.w(TAG, "No location retrieved yet");
startLocationUpdates();
}
}
else askPermission();
}
private void writeActualLocation(Location location) {
textLat.setText( "Lat: " + location.getLatitude() );
textLong.setText( "Long: " + location.getLongitude() );
markerLocation(new LatLng(location.getLatitude(), location.getLongitude()));
}
private void writeLastLocation() {
writeActualLocation(lastLocation);
}
private Marker locationMarker;
private void markerLocation(LatLng latLng) {
Log.i(TAG, "markerLocation("+latLng+")");
String title = latLng.latitude + ", " + latLng.longitude;
MarkerOptions markerOptions = new MarkerOptions()
.position(latLng)
.title(title);
if ( map!=null ) {
if ( locationMarker != null )
locationMarker.remove();
locationMarker = map.addMarker(markerOptions);
float zoom = 14f;
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, zoom);
map.animateCamera(cameraUpdate);
}
}
private Marker geoFenceMarker;
private void markerForGeofence(LatLng latLng) {
Log.i(TAG, "markerForGeofence("+latLng+")");
String title = latLng.latitude + ", " + latLng.longitude;
// Define marker options
MarkerOptions markerOptions = new MarkerOptions()
.position(latLng)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE))
.title(title);
if ( map!=null ) {
// Remove last geoFenceMarker
if (geoFenceMarker != null)
geoFenceMarker.remove();
geoFenceMarker = map.addMarker(markerOptions);
}
}
// Start Geofence creation process
private void startGeofence() {
Log.i(TAG, "startGeofence()");
if( geoFenceMarker != null ) {
Geofence geofence = createGeofence( geoFenceMarker.getPosition(), GEOFENCE_RADIUS );
GeofencingRequest geofenceRequest = createGeofenceRequest( geofence );
addGeofence( geofenceRequest );
} else {
Log.e(TAG, "Geofence marker is null");
}
}
private static final long GEO_DURATION = 60 * 60 * 1000;
private static final String GEOFENCE_REQ_ID = "My Geofence";
private static final float GEOFENCE_RADIUS = 25.0f; // in meters
// Create a Geofence
private Geofence createGeofence( LatLng latLng, float radius ) {
Log.d(TAG, "createGeofence");
return new Geofence.Builder()
.setRequestId(GEOFENCE_REQ_ID)
.setCircularRegion( latLng.latitude, latLng.longitude, radius)
.setExpirationDuration( GEO_DURATION )
.setTransitionTypes( Geofence.GEOFENCE_TRANSITION_ENTER
| Geofence.GEOFENCE_TRANSITION_EXIT )
.build();
}
// Create a Geofence Request
private GeofencingRequest createGeofenceRequest( Geofence geofence ) {
Log.d(TAG, "createGeofenceRequest");
return new GeofencingRequest.Builder()
.setInitialTrigger( GeofencingRequest.INITIAL_TRIGGER_ENTER )
.addGeofence( geofence )
.build();
}
private PendingIntent geoFencePendingIntent;
private final int GEOFENCE_REQ_CODE = 0;
private PendingIntent createGeofencePendingIntent() {
Log.d(TAG, "createGeofencePendingIntent");
if ( geoFencePendingIntent != null )
return geoFencePendingIntent;
Intent intent = new Intent( this, GeofenceTransitionService.class);
return PendingIntent.getService(
this, GEOFENCE_REQ_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT );
}
// Add the created GeofenceRequest to the device's monitoring list
private void addGeofence(GeofencingRequest request) {
Log.d(TAG, "addGeofence");
if (checkPermission())
LocationServices.GeofencingApi.addGeofences(
googleApiClient,
request,
createGeofencePendingIntent()
).setResultCallback(this);
}
#Override
public void onResult(#NonNull Status status) {
Log.i(TAG, "onResult: " + status);
if ( status.isSuccess() ) {
saveGeofence();
drawGeofence();
} else {
// inform about fail
}
}
// Draw Geofence circle on GoogleMap
private Circle geoFenceLimits;
private void drawGeofence() {
Log.d(TAG, "drawGeofence()");
if ( geoFenceLimits != null )
geoFenceLimits.remove();
CircleOptions circleOptions = new CircleOptions()
.center( geoFenceMarker.getPosition())
.strokeColor(Color.argb(50, 70,70,70))
.fillColor( Color.argb(100, 150,150,150) )
.radius( GEOFENCE_RADIUS );
geoFenceLimits = map.addCircle( circleOptions );
}
private final String KEY_GEOFENCE_LAT = "GEOFENCE LATITUDE";
private final String KEY_GEOFENCE_LON = "GEOFENCE LONGITUDE";
// Saving GeoFence marker with prefs mng
private void saveGeofence() {
Log.d(TAG, "saveGeofence()");
SharedPreferences sharedPref = getPreferences( Context.MODE_PRIVATE );
SharedPreferences.Editor editor = sharedPref.edit();
editor.putLong( KEY_GEOFENCE_LAT, Double.doubleToRawLongBits( geoFenceMarker.getPosition().latitude ));
editor.putLong( KEY_GEOFENCE_LON, Double.doubleToRawLongBits( geoFenceMarker.getPosition().longitude ));
editor.apply();
}
// Recovering last Geofence marker
private void recoverGeofenceMarker() {
Log.d(TAG, "recoverGeofenceMarker");
SharedPreferences sharedPref = getPreferences( Context.MODE_PRIVATE );
if ( sharedPref.contains( KEY_GEOFENCE_LAT ) && sharedPref.contains( KEY_GEOFENCE_LON )) {
double lat = Double.longBitsToDouble( sharedPref.getLong( KEY_GEOFENCE_LAT, -1 ));
double lon = Double.longBitsToDouble( sharedPref.getLong( KEY_GEOFENCE_LON, -1 ));
LatLng latLng = new LatLng( lat, lon );
markerForGeofence(latLng);
drawGeofence();
}
}
// Clear Geofence
private void clearGeofence() {
Log.d(TAG, "clearGeofence()");
LocationServices.GeofencingApi.removeGeofences(
googleApiClient,
createGeofencePendingIntent()
).setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(#NonNull Status status) {
if ( status.isSuccess() ) {
// remove drawing
removeGeofenceDraw();
}
}
});
}
private void removeGeofenceDraw() {
Log.d(TAG, "removeGeofenceDraw()");
if ( geoFenceMarker != null)
geoFenceMarker.remove();
if ( geoFenceLimits != null )
geoFenceLimits.remove();
}
}
and this is service class for transitions and notifications :
public class GeofenceTransitionService extends IntentService {
private static final String TAG = GeofenceTransitionService.class.getSimpleName();
public static final int GEOFENCE_NOTIFICATION_ID = 0;
public GeofenceTransitionService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
// Handling errors
if ( geofencingEvent.hasError() ) {
String errorMsg = getErrorString(geofencingEvent.getErrorCode() );
Log.e( TAG, errorMsg );
return;
}
int geoFenceTransition = geofencingEvent.getGeofenceTransition();
// Check if the transition type is of interest
Log.d(TAG,String.valueOf(geoFenceTransition));
Toast.makeText(this, String.valueOf(geoFenceTransition), Toast.LENGTH_SHORT).show();
if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT ) {
// Get the geofence that were triggered
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
String geofenceTransitionDetails = getGeofenceTransitionDetails(geoFenceTransition, triggeringGeofences );
// Send notification details as a String
sendNotification( geofenceTransitionDetails );
}
}
private String getGeofenceTransitionDetails(int geoFenceTransition, List<Geofence> triggeringGeofences) {
// get the ID of each geofence triggered
ArrayList<String> triggeringGeofencesList = new ArrayList<>();
for ( Geofence geofence : triggeringGeofences ) {
triggeringGeofencesList.add( geofence.getRequestId() );
}
String status = null;
if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER )
status = "Entering ";
else if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT )
status = "Exiting ";
return status + TextUtils.join( ", ", triggeringGeofencesList);
}
private void sendNotification( String msg ) {
Toast.makeText(this, "msg", Toast.LENGTH_SHORT).show();
Log.i(TAG, "sendNotification: " + msg );
// Intent to start the main Activity
Intent notificationIntent = MainActivity.makeNotificationIntent(
getApplicationContext(), msg
);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(notificationIntent);
PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
// Creating and sending Notification
NotificationManager notificatioMng =
(NotificationManager) getSystemService( Context.NOTIFICATION_SERVICE );
notificatioMng.notify(
GEOFENCE_NOTIFICATION_ID,
createNotification(msg, notificationPendingIntent));
}
// Create notification
private Notification createNotification(String msg, PendingIntent notificationPendingIntent) {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
notificationBuilder
.setSmallIcon(R.drawable.ic_action_location)
.setColor(Color.RED)
.setContentTitle(msg)
.setContentText("Geofence Notification!")
.setContentIntent(notificationPendingIntent)
.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND)
.setAutoCancel(true);
return notificationBuilder.build();
}
private static String getErrorString(int errorCode) {
switch (errorCode) {
case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE:
return "GeoFence not available";
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
return "Too many GeoFences";
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
return "Too many pending intents";
default:
return "Unknown error.";
}
}
}
Thanks in advance.
I have read various tutorials, forums and the official Google documentation and still cannot understand why my code does not work as expected. There are the relevant parts:
Activity
public class MainMap extends FragmentActivity implements OnMarkerClickListener, OnMapReadyCallback,
ConnectionCallbacks, OnConnectionFailedListener, LocationListener, ActivityCompat.OnRequestPermissionsResultCallback, ResultCallback<Status> {
private static final int REQUEST_ACCESS_FINE_LOCATION = 0;
protected GoogleApiClient mGoogleApiClient;
protected Location mCurrentLocation;
protected LocationRequest mLocationRequest;
private GoogleMap m_map;
private SupportMapFragment m_map_fragment;
protected ArrayList<Geofence> mGeofenceList;
private PendingIntent mGeofencePendingIntent;
private boolean m_geofences_added;
private SharedPreferences m_preferences;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_map);
m_preferences = this.getSharedPreferences("com.example",Context.MODE_PRIVATE);
// map fragment
m_map_fragment= (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
m_map_fragment.getMapAsync(this);
}
#Override
protected void onStart() {
super.onStart();
// location and geofences
add_location_and_geofences();
mGoogleApiClient.connect();
}
#Override
protected void onStop() {
// remove geofences
LocationServices.GeofencingApi.removeGeofences(mGoogleApiClient, getGeofencePendingIntent());
super.onStop();
mGoogleApiClient.disconnect();
}
#Override
public void onConnected(Bundle connectionHint) {
// permissions
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
request_fine_location_permission();
}
// location
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
// geofencing
try {
LocationServices.GeofencingApi.addGeofences(
mGoogleApiClient,
getGeofencingRequest(),
getGeofencePendingIntent()
).setResultCallback(this);
} catch (SecurityException securityException) {
Log.e(TAG, "Invalid location permission. " +
"You need to use ACCESS_FINE_LOCATION with geofences", securityException);
}
}
public void onResult(Status status) {
if (status.isSuccess()) {
} else {
String errorMessage = GeofenceErrorMessages.getErrorString(this,
status.getStatusCode());
Log.e(TAG, errorMessage);
}
}
private void add_location_and_geofences() {
for (int i =0; i < 3; i++) {
mGeofencePendingIntent = null;
mGeofenceList = new ArrayList<>();
mGeofenceList.add(new Geofence.Builder()
.setRequestId(Integer.toString(i)) // request id is the index so that I can later retrieve it
.setCircularRegion( /* I set coordinates here and a radius of 10meters*/)
.setExpirationDuration(NEVER_EXPIRE)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_DWELL)
.setLoiteringDelay(4000)
.build());
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(500);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
}
private PendingIntent getGeofencePendingIntent() {
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
private GeofencingRequest getGeofencingRequest() {
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_DWELL);
builder.addGeofences(mGeofenceList);
return builder.build();
}
}
my Service:
public class GeofenceTransitionsIntentService extends IntentService {
private Intent m_intent;
#Override
public void onCreate() {
super.onCreate();
m_intent = new Intent(this, Guide.class);
}
#Override
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
String errorMessage = GeofenceErrorMessages.getErrorString(this,
geofencingEvent.getErrorCode());
Log.e(TAG, errorMessage);
} else {
if (debug_mode) {
Log.i(TAG, "something has been received");
}
int geofenceTransition = geofencingEvent.getGeofenceTransition();
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_DWELL) {
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
for (Geofence geofence : triggeringGeofences) {
Log.i(TAG, "INSIDE GEOFENCE");
}
} else {
Log.e(TAG, getString(R.string.geofence_transition_invalid_type, geofenceTransition));
}
}
}
}
and my manifest
<service android:name="com.example.GeofenceTransitionsIntentService" />
With this code geofencing silently fails - my service is never triggered, both using wifi indoors and using 3G/4G networks outdoors.
Are you looking only for dwell events, or enter and exit events? If the latter, set your initial trigger to INITIAL_TRIGGER_ENTER, and the transition types to GEOFENCE_TRANSITION_ENTER| GEOFENCE_TRANSITION_EXIT.
If you are looking for dwell events, you need to stay within the geofence for about 5 minutes to get the initial trigger. When you leave, you won't get any event about it, but once you re-enter it, you'll need to stay within your geofence again for another 5 minutes to get your event.
So Far :-
When user in same(under fence area) it gives notification "user enters in area" is ok.But same user leave fence area its not notified.
This is my code:-
public class MainActivity extends AppCompatActivity implements
GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener,
LocationListener, OnMapReadyCallback, GoogleMap.OnMapClickListener, GoogleMap.OnMarkerClickListener,
ResultCallback<Status>
{
private static final String TAG = MainActivity.class.getSimpleName();
private GoogleMap map;
private GoogleApiClient googleApiClient;
private Location lastLocation;
private TextView textLat, textLong;
private MapFragment mapFragment;
private static final String NOTIFICATION_MSG = "NOTIFICATION MSG";
// Create a Intent send by the notification
public static Intent makeNotificationIntent(Context context, String msg) {
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra(NOTIFICATION_MSG, msg);
return intent;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textLat = (TextView) findViewById(R.id.lat);
textLong = (TextView) findViewById(R.id.lon);
// initialize GoogleMaps
initGMaps();
// create GoogleApiClient
createGoogleApi();
}
// Create GoogleApiClient instance
private void createGoogleApi() {
Log.d(TAG, "createGoogleApi()");
if (googleApiClient == null) {
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
}
#Override
protected void onStart() {
super.onStart();
// Call GoogleApiClient connection when starting the Activity
googleApiClient.connect();
}
#Override
protected void onStop() {
super.onStop();
// Disconnect GoogleApiClient when stopping Activity
googleApiClient.disconnect();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.geofence: {
startGeofence();
return true;
}
case R.id.clear: {
clearGeofence();
return true;
}
}
return super.onOptionsItemSelected(item);
}
private final int REQ_PERMISSION = 999;
// Check for permission to access Location
private boolean checkPermission() {
Log.d(TAG, "checkPermission()");
// Ask for permission if it wasn't granted yet
return (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED);
}
// Asks for permission
private void askPermission() {
Log.d(TAG, "askPermission()");
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQ_PERMISSION
);
}
// Verify user's response of the permission requested
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
Log.d(TAG, "onRequestPermissionsResult()");
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQ_PERMISSION: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted
getLastKnownLocation();
} else {
// Permission denied
permissionsDenied();
}
break;
}
}
}
// App cannot work without the permissions
private void permissionsDenied() {
Log.w(TAG, "permissionsDenied()");
// TODO close app and warn user
}
// Initialize GoogleMaps
private void initGMaps() {
mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
// Callback called when Map is ready
#Override
public void onMapReady(GoogleMap googleMap) {
Log.d(TAG, "onMapReady()");
map = googleMap;
map.setOnMapClickListener(this);
map.setOnMarkerClickListener(this);
}
#Override
public void onMapClick(LatLng latLng) {
Log.d(TAG, "onMapClick(" + latLng + ")");
//markerForGeofence(latLng);
}
#Override
public boolean onMarkerClick(Marker marker) {
Log.d(TAG, "onMarkerClickListener: " + marker.getPosition());
return false;
}
private LocationRequest locationRequest;
// Defined in mili seconds.
// This number in extremely low, and should be used only for debug
private final int UPDATE_INTERVAL = 1000;
private final int FASTEST_INTERVAL = 900;
// Start location Updates
private void startLocationUpdates() {
Log.i(TAG, "startLocationUpdates()");
locationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(UPDATE_INTERVAL)
.setFastestInterval(FASTEST_INTERVAL);
if (checkPermission())
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "onLocationChanged [" + location + "]");
lastLocation = location;
writeActualLocation(location);
}
// GoogleApiClient.ConnectionCallbacks connected
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.i(TAG, "onConnected()");
getLastKnownLocation();
recoverGeofenceMarker();
startGeofence();
}
// GoogleApiClient.ConnectionCallbacks suspended
#Override
public void onConnectionSuspended(int i) {
Log.w(TAG, "onConnectionSuspended()");
}
// GoogleApiClient.OnConnectionFailedListener fail
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.w(TAG, "onConnectionFailed()");
}
// Get last known location
private void getLastKnownLocation() {
Log.d(TAG, "getLastKnownLocation()");
if (checkPermission()) {
lastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (lastLocation != null) {
Log.i(TAG, "LasKnown location. " +
"Long: " + lastLocation.getLongitude() +
" | Lat: " + lastLocation.getLatitude());
writeLastLocation();
startLocationUpdates();
} else {
Log.w(TAG, "No location retrieved yet");
startLocationUpdates();
}
} else askPermission();
}
private void writeActualLocation(Location location) {
textLat.setText("Lat: " + location.getLatitude());
textLong.setText("Long: " + location.getLongitude());
markerLocation(new LatLng(location.getLatitude(), location.getLongitude()));
}
private void writeLastLocation() {
writeActualLocation(lastLocation);
}
private Marker locationMarker;
private void markerLocation(LatLng latLng) {
Log.i(TAG, "markerLocation(" + latLng + ")");
String title = latLng.latitude + ", " + latLng.longitude;
MarkerOptions markerOptions = new MarkerOptions()
.position(latLng)
.title(title);
if (map != null) {
if (locationMarker != null)
locationMarker.remove();
locationMarker = map.addMarker(markerOptions);
float zoom = 14f;
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, zoom);
map.animateCamera(cameraUpdate);
}
}
// Start Geofence creation process
private void startGeofence() {
Log.i(TAG, "startGeofence()");
Geofence geofence = createGeofence();
GeofencingRequest geofenceRequest = createGeofenceRequest(geofence);
addGeofence(geofenceRequest);
}
private static final long GEO_DURATION = 60 * 60 * 1000;
private static final String GEOFENCE_REQ_ID = "My Geofence";
private static final float GEOFENCE_RADIUS = 200.0f; // in meters
// Create a Geofence
private Geofence createGeofence() {
Log.d(TAG, "createGeofence");
return new Geofence.Builder()
.setRequestId(GEOFENCE_REQ_ID)
.setCircularRegion(18.478122, 73.890158, GEOFENCE_RADIUS)
.setExpirationDuration(GEO_DURATION)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_EXIT)
.build();
}
// Create a Geofence Request
private GeofencingRequest createGeofenceRequest(Geofence geofence) {
Log.d(TAG, "createGeofenceRequest");
return new GeofencingRequest.Builder()
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
.addGeofence(geofence)
.build();
}
private PendingIntent geoFencePendingIntent;
private static final int GEOFENCE_REQ_CODE = 0;
private PendingIntent createGeofencePendingIntent() {
Log.d(TAG, "createGeofencePendingIntent");
if (geoFencePendingIntent != null)
return geoFencePendingIntent;
Intent intent = new Intent(this, GeofenceTrasitionService.class);
return PendingIntent.getService(
this, GEOFENCE_REQ_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
// Add the created GeofenceRequest to the device's monitoring list
private void addGeofence(GeofencingRequest request) {
Log.d(TAG, "addGeofence");
if (checkPermission())
LocationServices.GeofencingApi.addGeofences(
googleApiClient,
request,
createGeofencePendingIntent()
).setResultCallback(this);
}
#Override
public void onResult(#NonNull Status status) {
Log.i(TAG, "onResult: " + status);
if (status.isSuccess()) {
drawGeofence();
} else {
// inform about fail
}
}
// Draw Geofence circle on GoogleMap
private Circle geoFenceLimits;
private void drawGeofence() {
Log.d(TAG, "drawGeofence()");
if (geoFenceLimits != null)
geoFenceLimits.remove();
CircleOptions circleOptions = new CircleOptions()
.center(new LatLng(18.478122, 73.890158))
.strokeColor(Color.argb(50, 70, 70, 70))
.fillColor(Color.argb(100, 150, 150, 150))
.radius(GEOFENCE_RADIUS);
geoFenceLimits = map.addCircle(circleOptions);
}
private final String KEY_GEOFENCE_LAT = "GEOFENCE LATITUDE";
private final String KEY_GEOFENCE_LON = "GEOFENCE LONGITUDE";
// Saving GeoFence marker with prefs mng
private void saveGeofence() {
Log.d(TAG, "saveGeofence()");
SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
// editor.putLong(KEY_GEOFENCE_LAT, Double.doubleToRawLongBits(geoFenceMarker.getPosition().latitude));
// editor.putLong(KEY_GEOFENCE_LON, Double.doubleToRawLongBits(geoFenceMarker.getPosition().longitude));
editor.apply();
}
// Recovering last Geofence marker
private void recoverGeofenceMarker() {
drawGeofence();
}
// Clear Geofence
private void clearGeofence() {
Log.d(TAG, "clearGeofence()");
LocationServices.GeofencingApi.removeGeofences(
googleApiClient,
createGeofencePendingIntent()
).setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(#NonNull Status status) {
if (status.isSuccess()) {
// remove drawing
removeGeofenceDraw();
}
}
});
}
private void removeGeofenceDraw() {
Log.d(TAG, "removeGeofenceDraw()");
}
}
To get notification:-
public class GeofenceTrasitionService extends IntentService {
private static final String TAG = GeofenceTrasitionService.class.getSimpleName();
public static final int GEOFENCE_NOTIFICATION_ID = 0;
public GeofenceTrasitionService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
// Handling errors
if ( geofencingEvent.hasError() ) {
String errorMsg = getErrorString(geofencingEvent.getErrorCode() );
Log.e( TAG, errorMsg );
return;
}
int geoFenceTransition = geofencingEvent.getGeofenceTransition();
// Check if the transition type is of interest
if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT ) {
// Get the geofence that were triggered
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
String geofenceTransitionDetails = getGeofenceTrasitionDetails(geoFenceTransition, triggeringGeofences );
// Send notification details as a String
sendNotification( geofenceTransitionDetails );
}
}
private String getGeofenceTrasitionDetails(int geoFenceTransition, List<Geofence> triggeringGeofences) {
// get the ID of each geofence triggered
ArrayList<String> triggeringGeofencesList = new ArrayList<>();
for ( Geofence geofence : triggeringGeofences ) {
triggeringGeofencesList.add( geofence.getRequestId() );
}
String status = null;
if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT )
status = "Exiting ";
return status + TextUtils.join( ", ", triggeringGeofencesList);
}
private void sendNotification( String msg ) {
Log.i(TAG, "sendNotification: " + msg );
// Intent to start the main Activity
Intent notificationIntent = MainActivity.makeNotificationIntent(
getApplicationContext(), msg
);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(notificationIntent);
PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
// Creating and sending Notification
NotificationManager notificatioMng =
(NotificationManager) getSystemService( Context.NOTIFICATION_SERVICE );
notificatioMng.notify(
GEOFENCE_NOTIFICATION_ID,
createNotification(msg, notificationPendingIntent));
}
// Create notification
private Notification createNotification(String msg, PendingIntent notificationPendingIntent) {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
notificationBuilder
.setSmallIcon(R.drawable.ic_action_location)
.setColor(Color.RED)
.setContentTitle(msg)
.setContentText("Geofence Notification!")
.setContentIntent(notificationPendingIntent)
.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND)
.setAutoCancel(true);
return notificationBuilder.build();
}
private static String getErrorString(int errorCode) {
switch (errorCode) {
case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE:
return "GeoFence not available";
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
return "Too many GeoFences";
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
return "Too many pending intents";
default:
return "Unknown error.";
}
}
}
As per tutorial i see:- there are 3 notification trigger
1.Enter 2.Dwell 3.Exit
I dont know how did i get notified when it leave the fence so far as in code i tried Exit.But no luck.
Ok i understand so just need to change the function :-
private GeofencingRequest createGeofenceRequest(Geofence geofence) {
Log.d(TAG, "createGeofenceRequest");
return new GeofencingRequest.Builder()
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_EXIT)
.addGeofence(geofence)
.build();
}
Here i did changed My initial trigger with Exit
"GeofencingRequest.INITIAL_TRIGGER_EXIT"
and got perfect output.
This work for both enter and exit
private GeofencingRequest createGeofenceRequest(Geofence geofence) {
return new GeofencingRequest.Builder()
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_EXIT|GeofencingRequest.INITIAL_TRIGGER_ENTER)
.addGeofence(geofence)
.build();
I am building an app to help keep up with your bar tab while you are out on the town. I have a feature where the user can set a proximity alarm (a Geofence) to remind them to close their tab if they leave the bar without closing out. First the map is shown, then a marker is put at the user's location, and then a 100 meter geofence is displayed around the marker. The user's location is updated regularly, so it runs on a background thread.
My problem is that when the user closes their tab, I want to stop disable the location services that the app is using with a button click. This button click takes place in a separate Activity from where the map and geolocation service are started. Any help would be greatly appreciated!
PS - I tried to include as much code as possible, so please forgive my clutter.
The map is initiated from the addBtn in this Activity:
public class Alarm extends ActionBarActivity {
public static String TAG = "lstech.aos.debug";
static public boolean geofencesAlreadyRegistered = false;
Button addBtn, lobbyBtn, startTabBtn, settingsBtn;
boolean mapOpen = false;
double latitude, longitude = 0.0;
protected GoogleMap map;
ActionBar actionBar;
Fragment f;
FragmentManager fragmentManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.alarm_layout);
actionBar = getSupportActionBar();
actionBar.hide();
addBtn = (Button) findViewById(R.id.add_geo_button);
startTabBtn = (Button) findViewById(R.id.calculator_button);
lobbyBtn = (Button) findViewById(R.id.lobby_button);
settingsBtn = (Button) findViewById(R.id.settings_button);
TinyDB tinydb = new TinyDB(this);
mapOpen = tinydb.getBoolean("mapOpen");
if (mapOpen)
addBtn.setText(R.string.view_map_button);
else
addBtn.setText(R.string.set_gps_alert);
fragmentManager = getSupportFragmentManager();
f = fragmentManager.findFragmentByTag("uniqueTag");
// SET MAP MARKER AND GEOFENCE
addBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// create a map instance if one doesn't exist
if (f == null) {
fragmentManager
.beginTransaction()
.replace(android.R.id.content, new MapFragment(),
"uniqueTag").commit();
} // keep instance of map if it's already showing
else {
fragmentManager.beginTransaction()
.replace(android.R.id.content, f, "uniqueTag")
.commit();
}
fragmentManager.executePendingTransactions();
startService(new Intent(getApplicationContext(),
GeolocationService.class));
}
});
The GeolocationService class sets up the location and Geofence object:
public class GeolocationService extends Service implements ConnectionCallbacks,
OnConnectionFailedListener, LocationListener, ResultCallback<Status> {
// TinyDB saved value handles: (boolean)"mapReady"
LocationListener listener;
private static final long GEOFENCE_EXPIRATION_IN_HOURS = 12;
private static final long RADIUS = 100;
public static final long GEOFENCE_EXPIRATION_IN_MILLISECONDS = GEOFENCE_EXPIRATION_IN_HOURS
* DateUtils.HOUR_IN_MILLIS;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 5;
protected GoogleApiClient mGoogleApiClient;
public static GoogleApiClient mGoogleApiClientStatic;
protected LocationRequest mLocationRequest;
private PendingIntent mPendingIntent;
List<Geofence> mGeofenceList;
static public List<Geofence> mGeofenceListPass;
SimpleGeofence simpleGeo;
static public SimpleGeofence geoFence;
Location mLocation, newLocation;
Intent intent;
public static LocationManager mlocManager;
public static LocationListener mlocListener;
public static android.location.LocationListener mlocListenerProvider;
public static PendingIntent pendingIntent;
public static ConnectionCallbacks connCallbacks;
public static OnConnectionFailedListener connFailedListener;
// ON START
// ***********
#Override
public void onStart(Intent intent, int startId) {
buildGoogleApiClient();
mGoogleApiClient.connect();
mGoogleApiClientStatic = mGoogleApiClient;
mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mlocListener = this;
mlocListenerProvider = new android.location.LocationListener() {
#Override
public void onLocationChanged(Location arg0) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
};
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0L,
0f, mlocListenerProvider);
}
// ON DESTROY
// *************
#Override
public void onDestroy() {
super.onDestroy();
if (mGoogleApiClient.isConnected())
mGoogleApiClient.disconnect();
}
// REGISTER GEOFENCES
// *********************
protected void registerGeofences(Location location) {
if (Alarm.geofencesAlreadyRegistered)
return;
Log.d(Alarm.TAG, "Registering Geofences");
String geoId = "geoId";
simpleGeo = new SimpleGeofence(geoId, location.getLatitude(),
location.getLongitude(), RADIUS,
GEOFENCE_EXPIRATION_IN_MILLISECONDS,
Geofence.GEOFENCE_TRANSITION_ENTER
| Geofence.GEOFENCE_TRANSITION_DWELL
| Geofence.GEOFENCE_TRANSITION_EXIT);
// mGeofenceList.add(new Geofence.Builder()
HashMap<String, SimpleGeofence> geofences = SimpleGeofenceStore
.getInstance().getSimpleGeofences();
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
for (Map.Entry<String, SimpleGeofence> item : geofences.entrySet()) {
SimpleGeofence sg = item.getValue();
sg.setLatitude(simpleGeo.getLatitude());
sg.setLongitude(simpleGeo.getLongitude());
builder.addGeofence(sg.toGeofence());
SimpleGeofenceStore store = SimpleGeofenceStore.getInstance();
store.setLatLong(simpleGeo.getLatitude(), simpleGeo.getLongitude());
// Log.d(Alarm.TAG, sg.getLatitude() + " " + sg.getLongitude());
}
TinyDB tinydb = new TinyDB(getApplicationContext());
tinydb.putBoolean("mapReady", false);
GeofencingRequest geofencingRequest = builder.build();
mPendingIntent = requestPendingIntent();
pendingIntent = mPendingIntent;
LocationServices.GeofencingApi.addGeofences(mGoogleApiClient,
geofencingRequest, mPendingIntent).setResultCallback(this);
Alarm.geofencesAlreadyRegistered = true;
} // end registerGeofences()
// REQUEST PENDING INTENT
// *************************
private PendingIntent requestPendingIntent() {
if (null != mPendingIntent)
return mPendingIntent;
Intent intent = new Intent(this, GeofenceReceiver.class);
return PendingIntent.getService(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
} // end requestPendingIntent()
// START LOCATION UPDATES
// *************************
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
} // end startLocationUpdates()
// STOP LOCATION UPDATES
// ************************
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
} // end stopLocationUpdates()
// ON CONNECTED
// ***************
#Override
public void onConnected(Bundle connectionHint) {
Log.i(Alarm.TAG, "Connected to GoogleApiClient");
startLocationUpdates();
} // end onConnected(Bundle connectionHint)
// ON LOCATION CHANGED
// **********************
#Override
public void onLocationChanged(Location location) {
Log.d(Alarm.TAG, "new location : " + location.getLatitude() + ", "
+ location.getLongitude() + ". " + location.getAccuracy());
broadcastLocationFound(location);
if (!Alarm.geofencesAlreadyRegistered)
registerGeofences(location);
} // end onLocationChanged(Location location)
// ON CONNECTION SUSPENDED
// **************************
#Override
public void onConnectionSuspended(int cause) {
Log.i(Alarm.TAG, "Connection suspended");
mGoogleApiClient.connect();
} // end onConnectionSuspended(int cause)
// ON CONNECTION FAILED
// ***********************
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(Alarm.TAG,
"Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
} // end onConnectionFailed(ConnectionResult result)
// BUILD GOOGLE API CLIENT
// **************************
protected synchronized void buildGoogleApiClient() {
Log.i(Alarm.TAG, "Building GoogleApiClient");
mlocListener = this;
connCallbacks = this;
connFailedListener = this;
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
createLocationRequest();
} // end buildGoogleApiClient()
// CREATE LOCATION REQUEST
// **************************
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest
.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
} // end createLocationRequest()
// ON BIND
// **********
#Override
public IBinder onBind(Intent intent) {
return null;
}
// BROADCAST LOCATION FOUND
// ***************************
public void broadcastLocationFound(Location location) {
Intent intent = new Intent(
"com.diligencedojo.tabsitter.geolocation.service");
intent.putExtra("latitude", location.getLatitude());
intent.putExtra("longitude", location.getLongitude());
intent.putExtra("done", 1);
// //
sendBroadcast(intent);
} // end broadcastLocationFound(Location location)
// ON RESULT
// ************
public void onResult(Status status) {
if (status.isSuccess()) {
Toast.makeText(getApplicationContext(),
getString(R.string.geofences_added), Toast.LENGTH_SHORT)
.show();
TinyDB tinydb = new TinyDB(getApplicationContext());
tinydb.putBoolean("mapReady", true);
} else {
Alarm.geofencesAlreadyRegistered = false;
String errorMessage = getErrorString(this, status.getStatusCode());
Toast.makeText(getApplicationContext(), errorMessage,
Toast.LENGTH_SHORT).show();
}
} // end onResult(Status status)
// GET ERROR STRING
// *******************
public static String getErrorString(Context context, int errorCode) {
Resources mResources = context.getResources();
switch (errorCode) {
case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE:
return mResources.getString(R.string.geofence_not_available);
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
return mResources.getString(R.string.geofence_too_many_geofences);
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
return mResources
.getString(R.string.geofence_too_many_pending_intents);
default:
return mResources.getString(R.string.unknown_geofence_error);
} // end switch (errorCode)
} // end getErrorString(Context context, int errorCode)
} // end GeolocationService Class
The MapFragment is where the actual map, marker, and geofence are displayed:
public class MapFragment extends Fragment {
protected SupportMapFragment mapFragment;
protected GoogleMap map;
protected Marker myPositionMarker;
Double latitude, longitude = 0.0;
Integer transition = 0;
float radius = 0;
long expiration = 0;
Handler handler;
HashMap<String, SimpleGeofence> geofences;
Button lobbyBtn, startTabBtn, settingsBtn;
private Bundle savedState = null;
Context mContext;
boolean mapOpen = false;
public static BroadcastReceiver mReceiver;
public static FragmentActivity fAct;
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
int resultCode = bundle.getInt("done");
if (resultCode == 1) {
latitude = bundle.getDouble("latitude");
longitude = bundle.getDouble("longitude");
updateMarker(latitude, longitude, context);
} // end if (resultCode == 1)
} // end if (bundle != null)
} // end onReceive(Context context, Intent intent)
}; // end BroadcastReceiver receiver = new BroadcastReceiver()
#Override
public void onCreate(Bundle savedInstanceState) {
setRetainInstance(true);
setHasOptionsMenu(true);
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_map, container,
false);
mapFragment = SupportMapFragment.newInstance();
FragmentTransaction fragmentTransaction = getChildFragmentManager()
.beginTransaction();
fragmentTransaction.add(R.id.map_container, mapFragment);
fragmentTransaction.commit();
startTabBtn = (Button) rootView.findViewById(R.id.calculator_button);
lobbyBtn = (Button) rootView.findViewById(R.id.lobby_button);
settingsBtn = (Button) rootView.findViewById(R.id.settings_button);
lobbyBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent toLobby = new Intent(v.getContext(), Lobby.class);
startActivity(toLobby);
}
});
startTabBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent toCalc = new Intent(v.getContext(), CurrentTab.class);
startActivity(toCalc);
}
});
settingsBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent toCalc = new Intent(v.getContext(), StartTab.class);
startActivity(toCalc);
}
});
return rootView;
} // end onCreateView
// ON PAUSE
// ***********
#Override
public void onPause() {
super.onPause();
fAct = getActivity();
getActivity().unregisterReceiver(receiver);
}
// ON RESUME
// ************
#Override
public void onResume() {
super.onResume();
if (mapFragment != null) {
if (map != null)
map.animateCamera(CameraUpdateFactory.zoomTo(15));
mapFragment.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap googleMap) {
map = googleMap;
map.animateCamera(CameraUpdateFactory.zoomTo(15));
} // end onMapReady(GoogleMap googleMap)
}); // end mapFragment.getMapAsync(new OnMapReadyCallback()
} // end if (mapFragment != null)
mReceiver = receiver;
getActivity().registerReceiver(
receiver,
new IntentFilter(
"com.diligencedojo.tabsitter.geolocation.service"));
} // end onResume()
// DISPLAY GEOFENCE
// *******************
protected void displayGeofences() {
geofences = SimpleGeofenceStore.getInstance().getSimpleGeofences();
// set circle around marker
for (Map.Entry<String, SimpleGeofence> item : geofences.entrySet()) {
SimpleGeofence sg = item.getValue();
CircleOptions circleOptions1 = new CircleOptions()
.center(new LatLng(sg.getLatitude(), sg.getLongitude()))
.radius(sg.getRadius()).strokeColor(Color.BLACK)
.strokeWidth(2).fillColor(0x500000ff);
map.addCircle(circleOptions1);
}
} // end displayGeofences()
// CREATE MARKER
// ****************
protected void createMarker(Double latitude, Double longitude,
Context context) {
LatLng latLng = new LatLng(latitude, longitude);
myPositionMarker = map.addMarker(new MarkerOptions().position(latLng));
map.moveCamera(CameraUpdateFactory.newLatLng(latLng));
// display the geofence after the marker is placed to ensure that the
// map is being displayed successfully
displayGeofences();
// save the state of the map (if it's open or not)
TinyDB tinydb = new TinyDB(context);
tinydb.putBoolean("mapOpen", true);
tinydb.putDouble("latitude", latitude);
tinydb.putDouble("longitude", longitude);
}
// UPDATE MARKER
// ****************
protected void updateMarker(Double latitude, Double longitude,
Context context) {
if (myPositionMarker == null)
createMarker(latitude, longitude, context);
LatLng latLng = new LatLng(latitude, longitude);
myPositionMarker.setPosition(latLng);
map.moveCamera(CameraUpdateFactory.newLatLng(latLng));
}
// ON CREATE OPTIONS MENU
// *************************
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_map, menu);
}
// ON OPTIONS SELECTED
// **********************
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
} // end MapFragment Class
The CloseTab Activity is where I want to stop any GPS service that the app is using. I have tried a lot of different approaches, so bear with my code.
public class CloseTab extends Activity {
Button numDrinksBtn, estBillBtn, avgCostBtn, tipAmtBtn, totBillBtn,
dismissBtn;
TextView tipExpl;
int currDrinkTotal = 0;
double currTabTotal, currTipTotal, tipAmt = 0.0;
boolean isSobriety, isSaver, isCount = false;
GoogleApiClient mGoogleApiClient;
SimpleGeofence sg;
LocationListener mlocListener;
LocationManager locationManager;
android.location.LocationListener mlocListenerProvider;
PendingIntent mPendingIntent;
ConnectionCallbacks mConnCallbacks;
OnConnectionFailedListener mConnFailedListener;
BroadcastReceiver mReceiver;
FragmentActivity fAct;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.close_tab_layout);
numDrinksBtn = (Button) findViewById(R.id.num_drinks_amout);
estBillBtn = (Button) findViewById(R.id.est_bill_amout);
avgCostBtn = (Button) findViewById(R.id.avg_cost_amout);
tipExpl = (TextView) findViewById(R.id.tip_expl_text);
tipAmtBtn = (Button) findViewById(R.id.total_tip_amount);
totBillBtn = (Button) findViewById(R.id.total_bill_amout);
dismissBtn = (Button) findViewById(R.id.dismiss_button);
getSavedValues(); // populate view with saved values
// DISMISS BUTTON
dismissBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mGoogleApiClient = GeolocationService.mGoogleApiClientStatic;
if (mGoogleApiClient.isConnected()) {
mlocListener = GeolocationService.mlocListener;
locationManager = GeolocationService.mlocManager;
mlocListenerProvider = GeolocationService.mlocListenerProvider;
mPendingIntent = GeolocationService.pendingIntent;
mConnCallbacks = GeolocationService.connCallbacks;
mConnFailedListener = GeolocationService.connFailedListener;
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, mlocListener);
LocationServices.GeofencingApi.removeGeofences(
mGoogleApiClient, mPendingIntent);
locationManager.removeUpdates(mlocListenerProvider);
mGoogleApiClient
.unregisterConnectionCallbacks(mConnCallbacks);
mGoogleApiClient
.unregisterConnectionFailedListener(mConnFailedListener);
// mGoogleApiClient.stopAutoManage(f);
// mReceiver.abortBroadcast();
// fAct = MapFragment.fAct;
// mGoogleApiClient.stopAutoManage(fAct);
// mReceiver = MapFragment.mReceiver;
// fAct.unregisterReceiver(mReceiver);
mGoogleApiClient.disconnect();
}
turnGPSOff();
Intent intent = new Intent(
"android.location.GPS_ENABLED_CHANGE");
intent.putExtra("enabled", false);
sendBroadcast(intent);
ActivityManager am = (ActivityManager) getSystemService(Activity.ACTIVITY_SERVICE);
am.killBackgroundProcesses("com.diligencedojo.tabsitter");
am.getRunningServices(100).clear();
am.getRunningAppProcesses().clear();
// clear all saved values
TinyDB tinydb = new TinyDB(getApplicationContext());
tinydb.clear();
finish();
startActivity(getIntent());
Intent toLobby = new Intent(v.getContext(), Lobby.class);
startActivity(toLobby);
}
});
} // end onCreate
// automatic turn off the gps
public void turnGPSOff() {
Context ctx = getApplicationContext();
// CloseTab.this
String provider = Settings.Secure.getString(ctx.getContentResolver(),
Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
if (provider.contains("gps")) { // if gps is enabled
// Toast.makeText(getApplicationContext(),
// "in->provider.contains(gps)", Toast.LENGTH_SHORT).show();
final Intent poke = new Intent();
poke.setClassName("com.android.settings",
"com.android.settings.widget.SettingsAppWidgetProvider");
poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
poke.setData(Uri.parse("3"));
ctx.sendBroadcast(poke);
// CloseTab.this.sendBroadcast(poke);
}
}
..........
These are the classes I am using for my geofence:
SimpleGeofence Class
public class SimpleGeofence {
private final String id;
private double latitude;
private double longitude;
private final float radius;
private long expirationDuration;
private int transitionType;
private int loiteringDelay = 60000;
public SimpleGeofence(String geofenceId, double latitude, double longitude,
float radius, long expiration, int transition) {
this.id = geofenceId;
this.latitude = latitude;
this.longitude = longitude;
this.radius = radius;
this.expirationDuration = expiration;
this.transitionType = transition;
}
public String getId() {
return id;
}
public void setLatitude(Double mLat) {
this.latitude = mLat;
}
public double getLatitude() {
return latitude;
}
public void setLongitude(Double mLong) {
this.longitude = mLong;
}
public double getLongitude() {
return longitude;
}
public float getRadius() {
return radius;
}
public void setExpirationDuration(long mExpirationDuration) {
this.expirationDuration = mExpirationDuration;
}
public long getExpirationDuration() {
return expirationDuration;
}
public int getTransitionType() {
return transitionType;
}
public Geofence toGeofence() {
Geofence g = new Geofence.Builder().setRequestId(getId())
.setTransitionTypes(transitionType)
.setCircularRegion(getLatitude(), getLongitude(), getRadius())
.setExpirationDuration(expirationDuration)
.setLoiteringDelay(loiteringDelay).build();
return g;
}
} // end SimpleGefence Class
SimpleGeofenceStore Class
public class SimpleGeofenceStore {
private static final long GEOFENCE_EXPIRATION_IN_HOURS = 12;
private static final long RADIUS = 100;
public static final long GEOFENCE_EXPIRATION_IN_MILLISECONDS = GEOFENCE_EXPIRATION_IN_HOURS
* DateUtils.HOUR_IN_MILLIS;
protected HashMap<String, SimpleGeofence> geofences = new HashMap<String, SimpleGeofence>();
private static SimpleGeofenceStore instance = new SimpleGeofenceStore();
private double latitude;
private double longitude;
public static SimpleGeofenceStore getInstance() {
// mContext = context;
return instance;
}
public void setLatLong(Double mLat, Double mLong) {
this.latitude = mLat;
this.longitude = mLong;
}
public Double getLatitude() {
return latitude;
}
public Double getLongitude() {
return longitude;
}
private SimpleGeofenceStore() {
geofences.put("My House", new SimpleGeofence("My House", getLatitude(),
getLongitude(), RADIUS, GEOFENCE_EXPIRATION_IN_MILLISECONDS,
Geofence.GEOFENCE_TRANSITION_ENTER
| Geofence.GEOFENCE_TRANSITION_DWELL
| Geofence.GEOFENCE_TRANSITION_EXIT));
}
public HashMap<String, SimpleGeofence> getSimpleGeofences() {
return this.geofences;
}
} // end SimpleGeofenceStore Class
To disable the location services and processes on a button click from a different Activity, I followed these steps. First I defined the location variables in GeolocationServices.java as public and static. This allows you access to them in the other Activities. Next, I put a boolean variable "tabClosed" around everything that could potentially reconnect the GoogleApiClient after it had been disconnected. I'm not entirely sure that I needed this.
GeolocationServices.java
public class GeolocationService extends Service implements ConnectionCallbacks,
OnConnectionFailedListener, LocationListener, ResultCallback<Status> {
// TinyDB saved value handles: (boolean)"mapReady"
LocationListener listener;
private static final long GEOFENCE_EXPIRATION_IN_HOURS = 12;
private static final long RADIUS = 100;
public static final long GEOFENCE_EXPIRATION_IN_MILLISECONDS = GEOFENCE_EXPIRATION_IN_HOURS
* DateUtils.HOUR_IN_MILLIS;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 5;
// protected GoogleApiClient mGoogleApiClient;
public static GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
// private PendingIntent mPendingIntent;
public static PendingIntent mPendingIntent;
List<Geofence> mGeofenceList;
SimpleGeofence simpleGeo;
Location mLocation, newLocation;
public static LocationManager mlocManager;
public static LocationListener mlocListener;
public static ConnectionCallbacks connCallbacks;
public static OnConnectionFailedListener connFailedListener;
public static ResultCallback<Status> mGeoCallback;
// ON START
// ***********
#Override
public void onStart(Intent intent, int startId) {
TinyDB tinydb = new TinyDB(getApplicationContext());
boolean tabClosed = tinydb.getBoolean("tabClosed");
if (!tabClosed) {
buildGoogleApiClient();
mGoogleApiClient.connect();
}
}
// ON DESTROY
// *************
#Override
public void onDestroy() {
// super.onDestroy();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
mlocManager.removeUpdates(mPendingIntent);
mlocManager.removeProximityAlert(mPendingIntent);
mPendingIntent.cancel();
}
super.onDestroy();
}
// REGISTER GEOFENCES
// *********************
protected void registerGeofences(Location location) {
if (Alarm.geofencesAlreadyRegistered)
return;
Log.d(Alarm.TAG, "Registering Geofences");
String geoId = "geoId";
simpleGeo = new SimpleGeofence(geoId, location.getLatitude(),
location.getLongitude(), RADIUS,
GEOFENCE_EXPIRATION_IN_MILLISECONDS,
Geofence.GEOFENCE_TRANSITION_ENTER
| Geofence.GEOFENCE_TRANSITION_DWELL
| Geofence.GEOFENCE_TRANSITION_EXIT);
// //
HashMap<String, SimpleGeofence> geofences = SimpleGeofenceStore
.getInstance().getSimpleGeofences();
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
for (Map.Entry<String, SimpleGeofence> item : geofences.entrySet()) {
SimpleGeofence sg = item.getValue();
sg.setLatitude(simpleGeo.getLatitude());
sg.setLongitude(simpleGeo.getLongitude());
builder.addGeofence(sg.toGeofence());
SimpleGeofenceStore store = SimpleGeofenceStore.getInstance();
store.setLatLong(simpleGeo.getLatitude(), simpleGeo.getLongitude());
// Log.d(Alarm.TAG, sg.getLatitude() + " " + sg.getLongitude());
}
TinyDB tinydb = new TinyDB(getApplicationContext());
tinydb.putBoolean("mapReady", false);
GeofencingRequest geofencingRequest = builder.build();
mPendingIntent = requestPendingIntent();
mGeoCallback = this;
LocationServices.GeofencingApi.addGeofences(mGoogleApiClient,
geofencingRequest, mPendingIntent).setResultCallback(
mGeoCallback);
Alarm.geofencesAlreadyRegistered = true;
} // end registerGeofences()
// REQUEST PENDING INTENT
// *************************
private PendingIntent requestPendingIntent() {
PendingIntent tempPendingIntent = null;
if (null != mPendingIntent)
return mPendingIntent;
TinyDB tinydb = new TinyDB(getApplicationContext());
boolean tabClosed = tinydb.getBoolean("tabClosed");
if (!tabClosed) {
Intent intent = new Intent(this, GeofenceReceiver.class);
tempPendingIntent = PendingIntent.getService(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
return tempPendingIntent;
} // end requestPendingIntent()
// BROADCAST LOCATION FOUND
// ***************************
public void broadcastLocationFound(Location location) {
Intent intent = new Intent(
"com.diligencedojo.tabsitter.geolocation.service");
intent.putExtra("latitude", location.getLatitude());
intent.putExtra("longitude", location.getLongitude());
intent.putExtra("done", 1);
TinyDB tinydb = new TinyDB(getApplicationContext());
boolean tabClosed = tinydb.getBoolean("tabClosed");
if (!tabClosed)
sendBroadcast(intent);
} // end broadcastLocationFound(Location location)
// START LOCATION UPDATES
// *************************
protected void startLocationUpdates() {
TinyDB tinydb = new TinyDB(getApplicationContext());
boolean tabClosed = tinydb.getBoolean("tabClosed");
if (!tabClosed) { //
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
} // end startLocationUpdates()
// STOP LOCATION UPDATES
// ************************
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
} // end stopLocationUpdates()
// ON CONNECTED
// ***************
#Override
public void onConnected(Bundle connectionHint) {
Log.i(Alarm.TAG, "Connected to GoogleApiClient");
startLocationUpdates();
} // end onConnected(Bundle connectionHint)
// ON LOCATION CHANGED
// **********************
#Override
public void onLocationChanged(Location location) {
Log.d(Alarm.TAG, "new location : " + location.getLatitude() + ", "
+ location.getLongitude() + ". " + location.getAccuracy());
TinyDB tinydb = new TinyDB(getApplicationContext());
boolean tabClosed = tinydb.getBoolean("tabClosed");
if (!tabClosed)
broadcastLocationFound(location);
if (!Alarm.geofencesAlreadyRegistered)
registerGeofences(location);
} // end onLocationChanged(Location location)
// ON CONNECTION SUSPENDED
// **************************
#Override
public void onConnectionSuspended(int cause) {
Log.i(Alarm.TAG, "Connection suspended");
TinyDB tinydb = new TinyDB(getApplicationContext());
boolean tabClosed = tinydb.getBoolean("tabClosed");
if (!tabClosed)
mGoogleApiClient.connect();
} // end onConnectionSuspended(int cause)
// ON CONNECTION FAILED
// ***********************
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(Alarm.TAG,
"Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
} // end onConnectionFailed(ConnectionResult result)
// BUILD GOOGLE API CLIENT
// **************************
protected synchronized void buildGoogleApiClient() {
Log.i(Alarm.TAG, "Building GoogleApiClient");
TinyDB tinydb = new TinyDB(getApplicationContext());
boolean tabClosed = tinydb.getBoolean("tabClosed");
if (!tabClosed) {
mlocListener = this;
connCallbacks = this;
connFailedListener = this;
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(connCallbacks)
.addOnConnectionFailedListener(connFailedListener)
.addApi(LocationServices.API).build();
createLocationRequest();
}
} // end buildGoogleApiClient()
// CREATE LOCATION REQUEST
// **************************
protected void createLocationRequest() {
TinyDB tinydb = new TinyDB(getApplicationContext());
boolean tabClosed = tinydb.getBoolean("tabClosed");
if (!tabClosed) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest
.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
} // end createLocationRequest()
// ON BIND
// **********
#Override
public IBinder onBind(Intent intent) {
return null;
}
// ON RESULT
// ************
public void onResult(Status status) {
TinyDB tinydb = new TinyDB(getApplicationContext());
boolean tabClosed = tinydb.getBoolean("tabClosed");
if (!tabClosed) {
if (status.isSuccess()) {
Toast.makeText(getApplicationContext(),
getString(R.string.geofences_added), Toast.LENGTH_SHORT)
.show();
tinydb.putBoolean("mapReady", true);
} else {
Alarm.geofencesAlreadyRegistered = false;
String errorMessage = getErrorString(this,
status.getStatusCode());
Toast.makeText(getApplicationContext(), errorMessage,
Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(getApplicationContext(),
"Tab closed, do not add geofence.", Toast.LENGTH_SHORT)
.show();
}
} // end onResult(Status status)
// GET ERROR STRING
// *******************
public static String getErrorString(Context context, int errorCode) {
Resources mResources = context.getResources();
switch (errorCode) {
case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE:
return mResources.getString(R.string.geofence_not_available);
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
return mResources.getString(R.string.geofence_too_many_geofences);
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
return mResources
.getString(R.string.geofence_too_many_pending_intents);
default:
return mResources.getString(R.string.unknown_geofence_error);
} // end switch (errorCode)
} // end getErrorString(Context context, int errorCode)
} // end GeolocationService Class
Now in CloseTab.java, I retrieved the variables I had declared public static in GeolocationService.java. It is important to use the same pending intent as a parameter when disabling the location services. First I removed the geofence, then the location updates, and then I disconnected the google api client all together. Finally, I used stopService(intent) to remove any lingering services (such as those started within my MapFragment.java).
public class CloseTab extends Activity {
Button numDrinksBtn, estBillBtn, avgCostBtn, tipAmtBtn, totBillBtn,
dismissBtn;
TextView tipExpl;
int currDrinkTotal = 0;
double currTabTotal, currTipTotal, tipAmt = 0.0;
boolean isSobriety, isSaver, isCount = false;
GoogleApiClient mGoogleApiClient;
PendingIntent mPendingIntent;
ResultCallback<Status> mGeoCallback;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.close_tab_layout);
numDrinksBtn = (Button) findViewById(R.id.num_drinks_amout);
estBillBtn = (Button) findViewById(R.id.est_bill_amout);
avgCostBtn = (Button) findViewById(R.id.avg_cost_amout);
tipExpl = (TextView) findViewById(R.id.tip_expl_text);
tipAmtBtn = (Button) findViewById(R.id.total_tip_amount);
totBillBtn = (Button) findViewById(R.id.total_bill_amout);
dismissBtn = (Button) findViewById(R.id.dismiss_button);
getSavedValues(); // populate view with saved values
// DISMISS BUTTON
dismissBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mGoogleApiClient = GeolocationService.mGoogleApiClient;
if (mGoogleApiClient.isConnected()) {
// Log.d("DBG", "mGoogleApiClient.isConnected()");
mPendingIntent = GeolocationService.mPendingIntent;
mGeoCallback = GeolocationService.mGeoCallback;
try { // Log.d("DBG", "try hit in CloseTab");
// use the same pending intent set in GeolocationService
// to identify the right things to disable
// Remove geofence
LocationServices.GeofencingApi.removeGeofences(
mGoogleApiClient, mPendingIntent)
.setResultCallback(mGeoCallback);
// Remove location updates
LocationServices.FusedLocationApi
.removeLocationUpdates(mGoogleApiClient,
mPendingIntent);
// Disconnect google client
mGoogleApiClient.disconnect();
// Remove any lingering services
Intent intent = new Intent(getApplicationContext(),
GeolocationService.class);
stopService(intent);
} catch (SecurityException securityException) {
// Catch exception generated if the app does not use
// ACCESS_FINE_LOCATION permission.
Log.d("DBG", "catch hit in CloseTab");
}
}
// clear all saved values
TinyDB tinydb = new TinyDB(getApplicationContext());
tinydb.clear();
// tab has been closed. this is used as a condition to determine
// if gps should be allowed to reconnect on it's own
tinydb.putBoolean("tabClosed", true);
Intent toLobby = new Intent(v.getContext(), Lobby.class);
startActivity(toLobby);
}
});
}// end onCreate
Hopefully this will help someone else.