/*
* 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;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.LocationServices;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity implements ConnectionCallbacks,
OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {
// 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 LocationServices mLocationService;
// Stores the PendingIntent used to request geofence monitoring.
private PendingIntent mGeofenceRequestIntent;
private GoogleApiClient mApiClient;
// Defines the allowable request types (in this example, we only add geofences).
private enum REQUEST_TYPE {ADD}
private REQUEST_TYPE mRequestType;
@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.
if (!isGooglePlayServicesAvailable()) {
Log.e(TAG, "Google Play services unavailable.");
finish();
return;
}
mApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mApiClient.connect();
// Instantiate a new geofence storage area.
mGeofenceStorage = new SimpleGeofenceStore(this);
// Instantiate the current List of geofences.
mGeofenceList = new ArrayList<Geofence>();
createGeofences();
}
/**
* 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());
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// 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);
}
}
@Override
public void onDisconnected() {
}
/**
* Once the connection is available, send a request to add the Geofences.
*/
@Override
public void onConnected(Bundle connectionHint) {
// Get the PendingIntent for the geofence monitoring request.
// Send a request to add the current geofences.
mGeofenceRequestIntent = getGeofenceTransitionPendingIntent();
LocationServices.GeofencingApi.addGeofences(mApiClient, mGeofenceList,
mGeofenceRequestIntent);
Toast.makeText(this, getString(R.string.start_geofence_service), Toast.LENGTH_SHORT).show();
finish();
}
@Override
public void onConnectionSuspended(int i) {
if (null != mGeofenceRequestIntent) {
LocationServices.GeofencingApi.removeGeofences(mApiClient, mGeofenceRequestIntent);
}
}
/**
* 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);
}
}