blob: baef2175598301df711db6c32ec93980b45c03f0 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.wearable.geofencing;
import static com.example.android.wearable.geofencing.Constants.ANDROID_BUILDING_ID;
import static com.example.android.wearable.geofencing.Constants.ANDROID_BUILDING_LATITUDE;
import static com.example.android.wearable.geofencing.Constants.ANDROID_BUILDING_LONGITUDE;
import static com.example.android.wearable.geofencing.Constants.ANDROID_BUILDING_RADIUS_METERS;
import static com.example.android.wearable.geofencing.Constants.CONNECTION_FAILURE_RESOLUTION_REQUEST;
import static com.example.android.wearable.geofencing.Constants.GEOFENCE_EXPIRATION_TIME;
import static com.example.android.wearable.geofencing.Constants.TAG;
import static com.example.android.wearable.geofencing.Constants.YERBA_BUENA_ID;
import static com.example.android.wearable.geofencing.Constants.YERBA_BUENA_LATITUDE;
import static com.example.android.wearable.geofencing.Constants.YERBA_BUENA_LONGITUDE;
import static com.example.android.wearable.geofencing.Constants.YERBA_BUENA_RADIUS_METERS;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationClient.OnAddGeofencesResultListener;
import com.google.android.gms.location.LocationStatusCodes;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity implements ConnectionCallbacks,
OnConnectionFailedListener, OnAddGeofencesResultListener {
// Internal List of Geofence objects. In a real app, these might be provided by an API based on
// locations within the user's proximity.
List<Geofence> mGeofenceList;
// These will store hard-coded geofences in this sample app.
private SimpleGeofence mAndroidBuildingGeofence;
private SimpleGeofence mYerbaBuenaGeofence;
// Persistent storage for geofences.
private SimpleGeofenceStore mGeofenceStorage;
private LocationClient mLocationClient;
// Stores the PendingIntent used to request geofence monitoring.
private PendingIntent mGeofenceRequestIntent;
// Defines the allowable request types (in this example, we only add geofences).
private enum REQUEST_TYPE {ADD}
private REQUEST_TYPE mRequestType;
// Flag that indicates if a request is underway.
private boolean mInProgress;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Rather than displayng this activity, simply display a toast indicating that the geofence
// service is being created. This should happen in less than a second.
Toast.makeText(this, getString(R.string.start_geofence_service), Toast.LENGTH_SHORT).show();
// Instantiate a new geofence storage area.
mGeofenceStorage = new SimpleGeofenceStore(this);
// Instantiate the current List of geofences.
mGeofenceList = new ArrayList<Geofence>();
// Start with the request flag set to false.
mInProgress = false;
createGeofences();
addGeofences();
finish();
}
/**
* In this sample, the geofences are predetermined and are hard-coded here. A real app might
* dynamically create geofences based on the user's location.
*/
public void createGeofences() {
// Create internal "flattened" objects containing the geofence data.
mAndroidBuildingGeofence = new SimpleGeofence(
ANDROID_BUILDING_ID, // geofenceId.
ANDROID_BUILDING_LATITUDE,
ANDROID_BUILDING_LONGITUDE,
ANDROID_BUILDING_RADIUS_METERS,
GEOFENCE_EXPIRATION_TIME,
Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT
);
mYerbaBuenaGeofence = new SimpleGeofence(
YERBA_BUENA_ID, // geofenceId.
YERBA_BUENA_LATITUDE,
YERBA_BUENA_LONGITUDE,
YERBA_BUENA_RADIUS_METERS,
GEOFENCE_EXPIRATION_TIME,
Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT
);
// Store these flat versions in SharedPreferences and add them to the geofence list.
mGeofenceStorage.setGeofence(ANDROID_BUILDING_ID, mAndroidBuildingGeofence);
mGeofenceStorage.setGeofence(YERBA_BUENA_ID, mYerbaBuenaGeofence);
mGeofenceList.add(mAndroidBuildingGeofence.toGeofence());
mGeofenceList.add(mYerbaBuenaGeofence.toGeofence());
}
/**
* Start a request for geofence monitoring by calling LocationClient.connect().
*/
public void addGeofences() {
// Start a request to add geofences.
mRequestType = REQUEST_TYPE.ADD;
// Test for Google Play services after setting the request type.
if (!isGooglePlayServicesAvailable()) {
Log.e(TAG, "Unable to add geofences - Google Play services unavailable.");
return;
}
// Create a new location client object. Since this activity class implements
// ConnectionCallbacks and OnConnectionFailedListener, it can be used as the listener for
// both parameters.
mLocationClient = new LocationClient(this, this, this);
// If a request is not already underway.
if (!mInProgress) {
// Indicate that a request is underway.
mInProgress = true;
// Request a connection from the client to Location Services.
mLocationClient.connect();
// A request is already underway, so disconnect the client and retry the request.
} else {
mLocationClient.disconnect();
mLocationClient.connect();
}
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
mInProgress = false;
// If the error has a resolution, start a Google Play services activity to resolve it.
if (connectionResult.hasResolution()) {
try {
connectionResult.startResolutionForResult(this,
CONNECTION_FAILURE_RESOLUTION_REQUEST);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Exception while resolving connection error.", e);
}
} else {
int errorCode = connectionResult.getErrorCode();
Log.e(TAG, "Connection to Google Play services failed with error code " + errorCode);
}
}
/**
* Called by Location Services if the location client disconnects.
*/
@Override
public void onDisconnected() {
// Turn off the request flag.
mInProgress = false;
// Destroy the current location client.
mLocationClient = null;
}
/**
* Once the connection is available, send a request to add the Geofences.
*/
@Override
public void onConnected(Bundle connectionHint) {
// Use mRequestType to determine what action to take. Only ADD is used in this sample.
if (REQUEST_TYPE.ADD == mRequestType) {
// Get the PendingIntent for the geofence monitoring request.
mGeofenceRequestIntent = getGeofenceTransitionPendingIntent();
// Send a request to add the current geofences.
mLocationClient.addGeofences(mGeofenceList, mGeofenceRequestIntent, this);
}
}
/**
* Called when request to add geofences is complete, with a result status code.
*/
@Override
public void onAddGeofencesResult(int statusCode, String[] geofenceRequestIds) {
// Log if adding the geofences was successful.
if (LocationStatusCodes.SUCCESS == statusCode) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Added geofences successfully.");
}
} else {
Log.e(TAG, "Failed to add geofences. Status code: " + statusCode);
}
// Turn off the in progress flag and disconnect the client.
mInProgress = false;
mLocationClient.disconnect();
}
/**
* Checks if Google Play services is available.
* @return true if it is.
*/
private boolean isGooglePlayServicesAvailable() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == resultCode) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Google Play services is available.");
}
return true;
} else {
Log.e(TAG, "Google Play services is unavailable.");
return false;
}
}
/**
* Create a PendingIntent that triggers GeofenceTransitionIntentService when a geofence
* transition occurs.
*/
private PendingIntent getGeofenceTransitionPendingIntent() {
Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
}