package com.example.android.geofence;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.LocationClient;
import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.util.Log;
import java.util.List;
/**
* This class receives geofence transition events from Location Services, in the
* form of an Intent containing the transition type and geofence id(s) that triggered
* the event.
*/
public class ReceiveTransitionsIntentService extends IntentService {
/**
* Sets an identifier for this class' background thread
*/
public ReceiveTransitionsIntentService() {
super("ReceiveTransitionsIntentService");
}
/**
* Handles incoming intents
* @param intent The Intent sent by Location Services. This Intent is provided
* to Location Services (inside a PendingIntent) when you call addGeofences()
*/
@Override
protected void onHandleIntent(Intent intent) {
// Create a local broadcast Intent
Intent broadcastIntent = new Intent();
// Give it the category for all intents sent by the Intent Service
broadcastIntent.addCategory(GeofenceUtils.CATEGORY_LOCATION_SERVICES);
// First check for errors
if (LocationClient.hasError(intent)) {
// Get the error code
int errorCode = LocationClient.getErrorCode(intent);
// Get the error message
String errorMessage = LocationServiceErrorMessages.getErrorString(this, errorCode);
// Log the error
Log.e(GeofenceUtils.APPTAG,
getString(R.string.geofence_transition_error_detail, errorMessage)
);
// Set the action and error message for the broadcast intent
broadcastIntent.setAction(GeofenceUtils.ACTION_GEOFENCE_ERROR)
.putExtra(GeofenceUtils.EXTRA_GEOFENCE_STATUS, errorMessage);
// Broadcast the error *locally* to other components in this app
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent);
// If there's no error, get the transition type and create a notification
} else {
// Get the type of transition (entry or exit)
int transition = LocationClient.getGeofenceTransition(intent);
// Test that a valid transition was reported
if (
(transition == Geofence.GEOFENCE_TRANSITION_ENTER)
||
(transition == Geofence.GEOFENCE_TRANSITION_EXIT)
) {
// Post a notification
List<Geofence> geofences = LocationClient.getTriggeringGeofences(intent);
String[] geofenceIds = new String[geofences.size()];
for (int index = 0; index < geofences.size() ; index++) {
geofenceIds[index] = geofences.get(index).getRequestId();
}
String ids = TextUtils.join(GeofenceUtils.GEOFENCE_ID_DELIMITER,geofenceIds);
String transitionType = getTransitionString(transition);
sendNotification(transitionType, ids);
// Log the transition type and a message
Log.d(GeofenceUtils.APPTAG,
getString(
R.string.geofence_transition_notification_title,
transitionType,
ids));
Log.d(GeofenceUtils.APPTAG,
getString(R.string.geofence_transition_notification_text));
// An invalid transition was reported
} else {
// Always log as an error
Log.e(GeofenceUtils.APPTAG,
getString(R.string.geofence_transition_invalid_type, transition));
}
}
}
/**
* Posts a notification in the notification bar when a transition is detected.
* If the user clicks the notification, control goes to the main Activity.
* @param transitionType The type of transition that occurred.
*
*/
private void sendNotification(String transitionType, String ids) {
// Create an explicit content Intent that starts the main Activity
Intent notificationIntent =
new Intent(getApplicationContext(),MainActivity.class);
// Construct a task stack
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the main Activity to the task stack as the parent
stackBuilder.addParentStack(MainActivity.class);
// Push the content Intent onto the stack
stackBuilder.addNextIntent(notificationIntent);
// Get a PendingIntent containing the entire back stack
PendingIntent notificationPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
// Get a notification builder that's compatible with platform versions >= 4
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// Set the notification contents
builder.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(
getString(R.string.geofence_transition_notification_title,
transitionType, ids))
.setContentText(getString(R.string.geofence_transition_notification_text))
.setContentIntent(notificationPendingIntent);
// Get an instance of the Notification manager
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Issue the notification
mNotificationManager.notify(0, builder.build());
}
/**
* Maps geofence transition types to their human-readable equivalents.
* @param transitionType A transition type constant defined in Geofence
* @return A String indicating the type of transition
*/
private String getTransitionString(int transitionType) {
switch (transitionType) {
case Geofence.GEOFENCE_TRANSITION_ENTER:
return getString(R.string.geofence_transition_entered);
case Geofence.GEOFENCE_TRANSITION_EXIT:
return getString(R.string.geofence_transition_exited);
default:
return getString(R.string.geofence_transition_unknown);
}
}
}