Java tutorial
/* * Copyright (C) 2013 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 edu.bsu.android.apps.geofence; import android.app.Activity; import android.app.Dialog; import android.app.ListActivity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Color; import android.os.Bundle; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; import android.support.v4.content.LocalBroadcastManager; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.EditText; import android.widget.Toast; import edu.bsu.android.apps.geofence.R; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.location.Geofence; import com.google.android.gms.location.LocationClient; import edu.bsu.android.apps.geofence.content.ContentProviderUtils; import edu.bsu.android.apps.geofence.objects.SimpleGeofence; import edu.bsu.android.apps.geofence.utils.FileUtils; import edu.bsu.android.apps.geofence.utils.GeofenceUtils; import edu.bsu.android.apps.geofence.utils.GeofenceUtils.REMOVE_TYPE; import edu.bsu.android.apps.geofence.utils.GeofenceUtils.REQUEST_TYPE; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * UI handler for the Location Services Geofence sample app. Allow input of latitude, longitude, and radius for two geofences. When registering * geofences, check input and then send the geofences to Location Services. Also allow removing either one of or both of the geofences. The menu * allows you to clear the screen or delete the geofences stored in persistent memory. */ public class Other extends FragmentActivity { /* * Use to set an expiration time for a geofence. After this amount of time Location Services will stop tracking the geofence. Remember to * unregister a geofence when you're finished with it. Otherwise, your app will use up battery. To continue monitoring a geofence indefinitely, * set the expiration time to Geofence#NEVER_EXPIRE. */ private static final long GEOFENCE_EXPIRATION_IN_HOURS = 12; private static final long GEOFENCE_EXPIRATION_IN_MILLISECONDS = GEOFENCE_EXPIRATION_IN_HOURS * DateUtils.HOUR_IN_MILLIS; private ContentProviderUtils mProvider; // Store the current request private REQUEST_TYPE mRequestType; // Store the current type of removal private REMOVE_TYPE mRemoveType; // Persistent storage for geofences //private SimpleGeofenceStore mPrefs; // Store a list of geofences to add List<Geofence> mCurrentGeofences; // Add geofences handler private GeofenceRequester mGeofenceRequester; // Remove geofences handler private GeofenceRemover mGeofenceRemover; // Handle to geofence 1 latitude in the UI private EditText mLatitude1; // Handle to geofence 1 longitude in the UI private EditText mLongitude1; // Handle to geofence 1 radius in the UI private EditText mRadius1; // Handle to geofence 2 latitude in the UI private EditText mLatitude2; // Handle to geofence 2 longitude in the UI private EditText mLongitude2; // Handle to geofence 2 radius in the UI private EditText mRadius2; // Handle to geofence 3 latitude in the UI private EditText mLatitude3; // Handle to geofence 3 longitude in the UI private EditText mLongitude3; // Handle to geofence 3 radius in the UI private EditText mRadius3; // Handle to geofence 4 latitude in the UI private EditText mLatitude4; // Handle to geofence 4 longitude in the UI private EditText mLongitude4; // Handle to geofence 4 radius in the UI private EditText mRadius4; /* * Internal lightweight geofence objects for geofence 1 and 2 */ private SimpleGeofence mUIGeofence1; private SimpleGeofence mUIGeofence2; private SimpleGeofence mUIGeofence3; private SimpleGeofence mUIGeofence4; // decimal formats for latitude, longitude, and radius private DecimalFormat mLatLngFormat; private DecimalFormat mRadiusFormat; /* * An instance of an inner class that receives broadcasts from listeners and from the IntentService that receives geofence transition events */ private GeofenceSampleReceiver mBroadcastReceiver; // An intent filter for the broadcast receiver private IntentFilter mIntentFilter; // Store the list of geofences to remove private List<String> mGeofenceIdsToRemove; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mProvider = ContentProviderUtils.Factory.get(this); // Set the pattern for the latitude and longitude format String latLngPattern = getString(R.string.lat_lng_pattern); // Set the format for latitude and longitude mLatLngFormat = new DecimalFormat(latLngPattern); // Localize the format mLatLngFormat.applyLocalizedPattern(mLatLngFormat.toLocalizedPattern()); // Set the pattern for the radius format String radiusPattern = getString(R.string.radius_pattern); // Set the format for the radius mRadiusFormat = new DecimalFormat(radiusPattern); // Localize the pattern mRadiusFormat.applyLocalizedPattern(mRadiusFormat.toLocalizedPattern()); // Create a new broadcast receiver to receive updates from the listeners and service mBroadcastReceiver = new GeofenceSampleReceiver(); // Create an intent filter for the broadcast receiver mIntentFilter = new IntentFilter(); // Action for broadcast Intents that report successful addition of geofences mIntentFilter.addAction(GeofenceUtils.ACTION_GEOFENCES_ADDED); // Action for broadcast Intents that report successful removal of geofences mIntentFilter.addAction(GeofenceUtils.ACTION_GEOFENCES_REMOVED); // Action for broadcast Intents containing various types of geofencing errors mIntentFilter.addAction(GeofenceUtils.ACTION_GEOFENCE_ERROR); // All Location Services sample apps use this category mIntentFilter.addCategory(GeofenceUtils.CATEGORY_LOCATION_SERVICES); // Instantiate a new geofence storage area //mPrefs = new SimpleGeofenceStore(this); // Instantiate the current List of geofences mCurrentGeofences = new ArrayList<Geofence>(); // Instantiate a Geofence requester mGeofenceRequester = new GeofenceRequester(this); // Instantiate a Geofence remover mGeofenceRemover = new GeofenceRemover(this); // Attach to the main UI setContentView(R.layout.activity_main); // Get handles to the Geofence editor fields in the UI mLatitude1 = (EditText) findViewById(R.id.value_latitude_1); mLongitude1 = (EditText) findViewById(R.id.value_longitude_1); mRadius1 = (EditText) findViewById(R.id.value_radius_1); mLatitude2 = (EditText) findViewById(R.id.value_latitude_2); mLongitude2 = (EditText) findViewById(R.id.value_longitude_2); mRadius2 = (EditText) findViewById(R.id.value_radius_2); mLatitude3 = (EditText) findViewById(R.id.value_latitude_3); mLongitude3 = (EditText) findViewById(R.id.value_longitude_3); mRadius3 = (EditText) findViewById(R.id.value_radius_3); mLatitude4 = (EditText) findViewById(R.id.value_latitude_4); mLongitude4 = (EditText) findViewById(R.id.value_longitude_4); mRadius4 = (EditText) findViewById(R.id.value_radius_4); } /* * Handle results returned to this Activity by other Activities started with startActivityForResult(). In particular, the method * onConnectionFailed() in GeofenceRemover and GeofenceRequester may call startResolutionForResult() to start an Activity that handles Google Play * services problems. The result of this call returns here, to onActivityResult. calls */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { // Choose what to do based on the request code switch (requestCode) { // If the request code matches the code sent in onConnectionFailed case GeofenceUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST: switch (resultCode) { // If Google Play services resolved the problem case Activity.RESULT_OK: // If the request was to add geofences if (GeofenceUtils.REQUEST_TYPE.ADD == mRequestType) { // Toggle the request flag and send a new request mGeofenceRequester.setInProgressFlag(false); // Restart the process of adding the current geofences mGeofenceRequester.addGeofences(mCurrentGeofences); // If the request was to remove geofences } else if (GeofenceUtils.REQUEST_TYPE.REMOVE == mRequestType) { // Toggle the removal flag and send a new removal request mGeofenceRemover.setInProgressFlag(false); // If the removal was by Intent if (GeofenceUtils.REMOVE_TYPE.INTENT == mRemoveType) { // Restart the removal of all geofences for the PendingIntent mGeofenceRemover.removeGeofencesByIntent(mGeofenceRequester.getRequestPendingIntent()); // If the removal was by a List of geofence IDs } else { // Restart the removal of the geofence list mGeofenceRemover.removeGeofencesById(mGeofenceIdsToRemove); } } break; // If any other result was returned by Google Play services default: // Report that Google Play services was unable to resolve the problem. Log.d(GeofenceUtils.APPTAG, getString(R.string.no_resolution)); } // If any other request code was received default: // Report that this Activity received an unknown requestCode Log.d(GeofenceUtils.APPTAG, getString(R.string.unknown_activity_request_code, requestCode)); break; } } /* * Whenever the Activity resumes, reconnect the client to Location Services and reload the last geofences that were set */ @Override protected void onResume() { super.onResume(); // Register the broadcast receiver to receive status updates LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, mIntentFilter); /* * Get existing geofences from the latitude, longitude, and radius values stored in SharedPreferences. If no values exist, null is returned. */ ArrayList<SimpleGeofence> list = mProvider.getList(); if (list.size() > 0) { for (int i = 0; i < list.size(); i++) { if (i == 0) { mUIGeofence1 = list.get(i); } else if (i == 1) { mUIGeofence2 = list.get(i); } else if (i == 2) { mUIGeofence3 = list.get(i); } else if (i == 3) { mUIGeofence4 = list.get(i); } } } //mUIGeofence1 = mPrefs.getGeofence("1"); //mUIGeofence2 = mPrefs.getGeofence("2"); //mUIGeofence3 = mPrefs.getGeofence("3"); //mUIGeofence4 = mPrefs.getGeofence("4"); /* * If the returned geofences have values, use them to set values in the UI, using the previously-defined number formats. */ if (mUIGeofence1 != null) { mLatitude1.setText(mLatLngFormat.format(mUIGeofence1.getLatitude())); mLongitude1.setText(mLatLngFormat.format(mUIGeofence1.getLongitude())); mRadius1.setText(mRadiusFormat.format(mUIGeofence1.getRadius())); } if (mUIGeofence2 != null) { mLatitude2.setText(mLatLngFormat.format(mUIGeofence2.getLatitude())); mLongitude2.setText(mLatLngFormat.format(mUIGeofence2.getLongitude())); mRadius2.setText(mRadiusFormat.format(mUIGeofence2.getRadius())); } if (mUIGeofence3 != null) { mLatitude3.setText(mLatLngFormat.format(mUIGeofence3.getLatitude())); mLongitude3.setText(mLatLngFormat.format(mUIGeofence3.getLongitude())); mRadius3.setText(mRadiusFormat.format(mUIGeofence3.getRadius())); } if (mUIGeofence4 != null) { mLatitude4.setText(mLatLngFormat.format(mUIGeofence4.getLatitude())); mLongitude4.setText(mLatLngFormat.format(mUIGeofence4.getLongitude())); mRadius4.setText(mRadiusFormat.format(mUIGeofence4.getRadius())); } } /* * Inflate the app menu */ @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu, menu); return true; } /* * Respond to menu item selections */ @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle item selection switch (item.getItemId()) { // Request to clear the geofence1 settings in the UI /* case R.id.menu_item_clear_geofence1: mLatitude1.setText(GeofenceUtils.EMPTY_STRING); mLongitude1.setText(GeofenceUtils.EMPTY_STRING); mRadius1.setText(GeofenceUtils.EMPTY_STRING); return true; // Request to clear the geofence2 settings in the UI case R.id.menu_item_clear_geofence2: mLatitude2.setText(GeofenceUtils.EMPTY_STRING); mLongitude2.setText(GeofenceUtils.EMPTY_STRING); mRadius2.setText(GeofenceUtils.EMPTY_STRING); return true; // Request to clear both geofence settings in the UI case R.id.menu_item_clear_geofences: mLatitude1.setText(GeofenceUtils.EMPTY_STRING); mLongitude1.setText(GeofenceUtils.EMPTY_STRING); mRadius1.setText(GeofenceUtils.EMPTY_STRING); mLatitude2.setText(GeofenceUtils.EMPTY_STRING); mLongitude2.setText(GeofenceUtils.EMPTY_STRING); mRadius2.setText(GeofenceUtils.EMPTY_STRING); return true; // Remove all geofences from storage case R.id.menu_item_clear_geofence_history: mProvider.deleteSimpleGeofence(mUIGeofence1); mProvider.deleteSimpleGeofence(mUIGeofence2); mProvider.deleteSimpleGeofence(mUIGeofence3); mProvider.deleteSimpleGeofence(mUIGeofence4); //mPrefs.clearGeofence("1"); //mPrefs.clearGeofence("2"); //mPrefs.clearGeofence("3"); //mPrefs.clearGeofence("4"); return true; // Remove all geofences from storage */ case R.id.map: startActivity(newIntent(this, MapActivity.class)); return true; // Pass through any other request default: return super.onOptionsItemSelected(item); } } /* * Save the current geofence settings in SharedPreferences. */ @Override protected void onPause() { super.onPause(); if (mUIGeofence1 != null) { mProvider.updateSimpleGeofence(mUIGeofence1); //mPrefs.setGeofence("1", mUIGeofence1); } if (mUIGeofence2 != null) { mProvider.updateSimpleGeofence(mUIGeofence2); //mPrefs.setGeofence("2", mUIGeofence2); } if (mUIGeofence3 != null) { mProvider.updateSimpleGeofence(mUIGeofence3); //mPrefs.setGeofence("3", mUIGeofence3); } if (mUIGeofence4 != null) { mProvider.updateSimpleGeofence(mUIGeofence4); //mPrefs.setGeofence("4", mUIGeofence4); } } /** * Verify that Google Play services is available before making a request. * * @return true if Google Play services is available, otherwise false */ private boolean servicesConnected() { // Check that Google Play services is available int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); // If Google Play services is available if (ConnectionResult.SUCCESS == resultCode) { // In debug mode, log the status Log.d(GeofenceUtils.APPTAG, getString(R.string.play_services_available)); // Continue return true; // Google Play services was not available for some reason } else { // Display an error dialog Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode, this, 0); if (dialog != null) { ErrorDialogFragment errorFragment = new ErrorDialogFragment(); errorFragment.setDialog(dialog); errorFragment.show(getSupportFragmentManager(), GeofenceUtils.APPTAG); } return false; } } /** * Called when the user clicks the "Remove geofences" button * * @param view The view that triggered this callback */ public void onUnregisterByPendingIntentClicked(View view) { /* * Remove all geofences set by this app. To do this, get the PendingIntent that was added when the geofences were added and use it as an * argument to removeGeofences(). The removal happens asynchronously; Location Services calls onRemoveGeofencesByPendingIntentResult() * (implemented in the current Activity) when the removal is done */ /* * Record the removal as remove by Intent. If a connection error occurs, the app can automatically restart the removal if Google Play services * can fix the error */ // Record the type of removal mRemoveType = GeofenceUtils.REMOVE_TYPE.INTENT; /* * Check for Google Play services. Do this after setting the request type. If connecting to Google Play services fails, onActivityResult is * eventually called, and it needs to know what type of request was in progress. */ if (!servicesConnected()) { return; } // Try to make a removal request try { /* * Remove the geofences represented by the currently-active PendingIntent. If the PendingIntent was removed for some reason, re-create it; * since it's always created with FLAG_UPDATE_CURRENT, an identical PendingIntent is always created. */ mGeofenceRemover.removeGeofencesByIntent(mGeofenceRequester.getRequestPendingIntent()); } catch (UnsupportedOperationException e) { // Notify user that previous request hasn't finished. Toast.makeText(this, R.string.remove_geofences_already_requested_error, Toast.LENGTH_LONG).show(); } } /** * Called when the user clicks the "Remove geofence 1" button * * @param view The view that triggered this callback */ public void onUnregisterGeofence1Clicked(View view) { /* * Remove the geofence by creating a List of geofences to remove and sending it to Location Services. The List contains the id of geofence 1 * ("1"). The removal happens asynchronously; Location Services calls onRemoveGeofencesByPendingIntentResult() (implemented in the current * Activity) when the removal is done. */ // Create a List of 1 Geofence with the ID "1" and store it in the global list mGeofenceIdsToRemove = Collections.singletonList("1"); /* * Record the removal as remove by list. If a connection error occurs, the app can automatically restart the removal if Google Play services * can fix the error */ mRemoveType = GeofenceUtils.REMOVE_TYPE.LIST; /* * Check for Google Play services. Do this after setting the request type. If connecting to Google Play services fails, onActivityResult is * eventually called, and it needs to know what type of request was in progress. */ if (!servicesConnected()) { return; } // Try to remove the geofence try { mGeofenceRemover.removeGeofencesById(mGeofenceIdsToRemove); // Catch errors with the provided geofence IDs } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (UnsupportedOperationException e) { // Notify user that previous request hasn't finished. Toast.makeText(this, R.string.remove_geofences_already_requested_error, Toast.LENGTH_LONG).show(); } } /** * Called when the user clicks the "Remove geofence 2" button * * @param view The view that triggered this callback */ public void onUnregisterGeofence2Clicked(View view) { /* * Remove the geofence by creating a List of geofences to remove and sending it to Location Services. The List contains the id of geofence 2, * which is "2". The removal happens asynchronously; Location Services calls onRemoveGeofencesByPendingIntentResult() (implemented in the * current Activity) when the removal is done. */ /* * Record the removal as remove by list. If a connection error occurs, the app can automatically restart the removal if Google Play services * can fix the error */ mRemoveType = GeofenceUtils.REMOVE_TYPE.LIST; // Create a List of 1 Geofence with the ID "2" and store it in the global list mGeofenceIdsToRemove = Collections.singletonList("2"); /* * Check for Google Play services. Do this after setting the request type. If connecting to Google Play services fails, onActivityResult is * eventually called, and it needs to know what type of request was in progress. */ if (!servicesConnected()) { return; } // Try to remove the geofence try { mGeofenceRemover.removeGeofencesById(mGeofenceIdsToRemove); // Catch errors with the provided geofence IDs } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (UnsupportedOperationException e) { // Notify user that previous request hasn't finished. Toast.makeText(this, R.string.remove_geofences_already_requested_error, Toast.LENGTH_LONG).show(); } } /** * Called when the user clicks the "Register geofences" button. Get the geofence parameters for each geofence and add them to a List. Create the * PendingIntent containing an Intent that Location Services sends to this app's broadcast receiver when Location Services detects a geofence * transition. Send the List and the PendingIntent to Location Services. */ public void onRegisterClicked(View view) { /* * Record the request as an ADD. If a connection error occurs, the app can automatically restart the add request if Google Play services can * fix the error */ mRequestType = GeofenceUtils.REQUEST_TYPE.ADD; /* * Check for Google Play services. Do this after setting the request type. If connecting to Google Play services fails, onActivityResult is * eventually called, and it needs to know what type of request was in progress. */ if (!servicesConnected()) { return; } /* * Check that the input fields have values and that the values are with the permitted range */ if (!checkInputFields()) { return; } /* * Create a version of geofence 1 that is "flattened" into individual fields. This allows it to be stored in SharedPreferences. */ mUIGeofence1 = new SimpleGeofence(); mUIGeofence1.setExpirationDuration(GEOFENCE_EXPIRATION_IN_MILLISECONDS); mUIGeofence1.setLatitude(Double.valueOf(mLatitude1.getText().toString())); mUIGeofence1.setLongitude(Double.valueOf(mLongitude1.getText().toString())); mUIGeofence1.setRadius(Float.valueOf(mRadius1.getText().toString())); mUIGeofence1.setTransitionType(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT); // Store this flat version in SharedPreferences mProvider.insertSimpleGeofence(mUIGeofence1); //mPrefs.setGeofence("1", mUIGeofence1); /* * Create a version of geofence 2 that is "flattened" into individual fields. This allows it to be stored in SharedPreferences. */ mUIGeofence2 = new SimpleGeofence(); mUIGeofence2.setExpirationDuration(GEOFENCE_EXPIRATION_IN_MILLISECONDS); mUIGeofence2.setLatitude(Double.valueOf(mLatitude2.getText().toString())); mUIGeofence2.setLongitude(Double.valueOf(mLongitude2.getText().toString())); mUIGeofence2.setRadius(Float.valueOf(mRadius2.getText().toString())); mUIGeofence2.setTransitionType(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT); // Store this flat version in SharedPreferences mProvider.insertSimpleGeofence(mUIGeofence2); //mPrefs.setGeofence("2", mUIGeofence2); /* * Add Geofence objects to a List. toGeofence() creates a Location Services Geofence object from a flat object */ mCurrentGeofences.add(mUIGeofence1.toGeofence()); mCurrentGeofences.add(mUIGeofence2.toGeofence()); if (!TextUtils.isEmpty(mLatitude3.getText().toString())) { /* * Create a version of geofence 3 that is "flattened" into individual fields. This allows it to be stored in SharedPreferences. */ mUIGeofence3 = new SimpleGeofence(); mUIGeofence3.setExpirationDuration(GEOFENCE_EXPIRATION_IN_MILLISECONDS); mUIGeofence3.setLatitude(Double.valueOf(mLatitude3.getText().toString())); mUIGeofence3.setLongitude(Double.valueOf(mLongitude3.getText().toString())); mUIGeofence3.setRadius(Float.valueOf(mRadius3.getText().toString())); mUIGeofence3.setTransitionType(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT); // Store this flat version in SharedPreferences //mPrefs.setGeofence("3", mUIGeofence3); mProvider.insertSimpleGeofence(mUIGeofence3); mCurrentGeofences.add(mUIGeofence3.toGeofence()); } if (!TextUtils.isEmpty(mLatitude4.getText().toString())) { /* * Create a version of geofence 4 that is "flattened" into individual fields. This allows it to be stored in SharedPreferences. */ mUIGeofence4 = new SimpleGeofence(); mUIGeofence4.setExpirationDuration(GEOFENCE_EXPIRATION_IN_MILLISECONDS); mUIGeofence4.setLatitude(Double.valueOf(mLatitude4.getText().toString())); mUIGeofence4.setLongitude(Double.valueOf(mLongitude4.getText().toString())); mUIGeofence4.setRadius(Float.valueOf(mRadius4.getText().toString())); mUIGeofence4.setTransitionType(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT); // Store this flat version in SharedPreferences //mPrefs.setGeofence("4", mUIGeofence4); mProvider.insertSimpleGeofence(mUIGeofence4); mCurrentGeofences.add(mUIGeofence4.toGeofence()); } // Start the request. Fail if there's already a request in progress try { // Try to add geofences mGeofenceRequester.addGeofences(mCurrentGeofences); } catch (UnsupportedOperationException e) { // Notify user that previous request hasn't finished. Toast.makeText(this, R.string.add_geofences_already_requested_error, Toast.LENGTH_LONG).show(); } } /** * Check all the input values and flag those that are incorrect * * @return true if all the widget values are correct; otherwise false */ private boolean checkInputFields() { // Start with the input validity flag set to true boolean inputOK = true; /* * Latitude, longitude, and radius values can't be empty. If they are, highlight the input field in red and put a Toast message in the UI. * Otherwise set the input field highlight to black, ensuring that a field that was formerly wrong is reset. */ if (TextUtils.isEmpty(mLatitude1.getText())) { mLatitude1.setBackgroundColor(Color.RED); Toast.makeText(this, R.string.geofence_input_error_missing, Toast.LENGTH_LONG).show(); // Set the validity to "invalid" (false) inputOK = false; } else { mLatitude1.setBackgroundColor(Color.BLACK); } if (TextUtils.isEmpty(mLongitude1.getText())) { mLongitude1.setBackgroundColor(Color.RED); Toast.makeText(this, R.string.geofence_input_error_missing, Toast.LENGTH_LONG).show(); // Set the validity to "invalid" (false) inputOK = false; } else { mLongitude1.setBackgroundColor(Color.BLACK); } if (TextUtils.isEmpty(mRadius1.getText())) { mRadius1.setBackgroundColor(Color.RED); Toast.makeText(this, R.string.geofence_input_error_missing, Toast.LENGTH_LONG).show(); // Set the validity to "invalid" (false) inputOK = false; } else { mRadius1.setBackgroundColor(Color.BLACK); } if (TextUtils.isEmpty(mLatitude2.getText())) { mLatitude2.setBackgroundColor(Color.RED); Toast.makeText(this, R.string.geofence_input_error_missing, Toast.LENGTH_LONG).show(); // Set the validity to "invalid" (false) inputOK = false; } else { mLatitude2.setBackgroundColor(Color.BLACK); } if (TextUtils.isEmpty(mLongitude2.getText())) { mLongitude2.setBackgroundColor(Color.RED); Toast.makeText(this, R.string.geofence_input_error_missing, Toast.LENGTH_LONG).show(); // Set the validity to "invalid" (false) inputOK = false; } else { mLongitude2.setBackgroundColor(Color.BLACK); } if (TextUtils.isEmpty(mRadius2.getText())) { mRadius2.setBackgroundColor(Color.RED); Toast.makeText(this, R.string.geofence_input_error_missing, Toast.LENGTH_LONG).show(); // Set the validity to "invalid" (false) inputOK = false; } else { mRadius2.setBackgroundColor(Color.BLACK); } /* * If all the input fields have been entered, test to ensure that their values are within the acceptable range. The tests can't be performed * until it's confirmed that there are actual values in the fields. */ if (inputOK) { /* * Get values from the latitude, longitude, and radius fields. */ double lat1 = Double.valueOf(mLatitude1.getText().toString()); double lng1 = Double.valueOf(mLongitude1.getText().toString()); double lat2 = Double.valueOf(mLatitude1.getText().toString()); double lng2 = Double.valueOf(mLongitude1.getText().toString()); float rd1 = Float.valueOf(mRadius1.getText().toString()); float rd2 = Float.valueOf(mRadius2.getText().toString()); /* * Test latitude and longitude for minimum and maximum values. Highlight incorrect values and set a Toast in the UI. */ if (lat1 > GeofenceUtils.MAX_LATITUDE || lat1 < GeofenceUtils.MIN_LATITUDE) { mLatitude1.setBackgroundColor(Color.RED); Toast.makeText(this, R.string.geofence_input_error_latitude_invalid, Toast.LENGTH_LONG).show(); // Set the validity to "invalid" (false) inputOK = false; } else { mLatitude1.setBackgroundColor(Color.BLACK); } if ((lng1 > GeofenceUtils.MAX_LONGITUDE) || (lng1 < GeofenceUtils.MIN_LONGITUDE)) { mLongitude1.setBackgroundColor(Color.RED); Toast.makeText(this, R.string.geofence_input_error_longitude_invalid, Toast.LENGTH_LONG).show(); // Set the validity to "invalid" (false) inputOK = false; } else { mLongitude1.setBackgroundColor(Color.BLACK); } if (lat2 > GeofenceUtils.MAX_LATITUDE || lat2 < GeofenceUtils.MIN_LATITUDE) { mLatitude2.setBackgroundColor(Color.RED); Toast.makeText(this, R.string.geofence_input_error_latitude_invalid, Toast.LENGTH_LONG).show(); // Set the validity to "invalid" (false) inputOK = false; } else { mLatitude2.setBackgroundColor(Color.BLACK); } if ((lng2 > GeofenceUtils.MAX_LONGITUDE) || (lng2 < GeofenceUtils.MIN_LONGITUDE)) { mLongitude2.setBackgroundColor(Color.RED); Toast.makeText(this, R.string.geofence_input_error_longitude_invalid, Toast.LENGTH_LONG).show(); // Set the validity to "invalid" (false) inputOK = false; } else { mLongitude2.setBackgroundColor(Color.BLACK); } if (rd1 < GeofenceUtils.MIN_RADIUS) { mRadius1.setBackgroundColor(Color.RED); Toast.makeText(this, R.string.geofence_input_error_radius_invalid, Toast.LENGTH_LONG).show(); // Set the validity to "invalid" (false) inputOK = false; } else { mRadius1.setBackgroundColor(Color.BLACK); } if (rd2 < GeofenceUtils.MIN_RADIUS) { mRadius2.setBackgroundColor(Color.RED); Toast.makeText(this, R.string.geofence_input_error_radius_invalid, Toast.LENGTH_LONG).show(); // Set the validity to "invalid" (false) inputOK = false; } else { mRadius2.setBackgroundColor(Color.BLACK); } } // If everything passes, the validity flag will still be true, otherwise it will be false. return inputOK; } /** * Define a Broadcast receiver that receives updates from connection listeners and the geofence transition service. */ public class GeofenceSampleReceiver extends BroadcastReceiver { /* * Define the required method for broadcast receivers This method is invoked when a broadcast Intent triggers the receiver */ @Override public void onReceive(Context context, Intent intent) { // Check the action code and determine what to do String action = intent.getAction(); //Toast.makeText(context, "onReceive action: " + action, Toast.LENGTH_LONG).show(); // Intent contains information about errors in adding or removing geofences if (TextUtils.equals(action, GeofenceUtils.ACTION_GEOFENCE_ERROR)) { handleGeofenceError(context, intent); // Intent contains information about successful addition or removal of geofences } else if (TextUtils.equals(action, GeofenceUtils.ACTION_GEOFENCES_ADDED) || TextUtils.equals(action, GeofenceUtils.ACTION_GEOFENCES_REMOVED)) { handleGeofenceStatus(context, intent); // Intent contains information about a geofence transition } else if (TextUtils.equals(action, GeofenceUtils.ACTION_GEOFENCE_TRANSITION)) { handleGeofenceTransition(context, intent); // The Intent contained an invalid action } else { Log.e(GeofenceUtils.APPTAG, getString(R.string.invalid_action_detail, action)); Toast.makeText(context, R.string.invalid_action, Toast.LENGTH_LONG).show(); } } /** * If you want to display a UI message about adding or removing geofences, put it here. * * @param context A Context for this component * @param intent The received broadcast Intent */ private void handleGeofenceStatus(Context context, Intent intent) { Toast.makeText(context, "geofence status", Toast.LENGTH_LONG).show(); } /** * Report geofence transitions to the UI * * @param context A Context for this component * @param intent The Intent containing the transition */ private void handleGeofenceTransition(Context context, Intent intent) { /* * If you want to change the UI when a transition occurs, put the code here. The current design of the app uses a notification to inform * the user that a transition has occurred. */ int transition = LocationClient.getGeofenceTransition(intent); List<Geofence> crossed = LocationClient.getTriggeringGeofences(intent); Toast.makeText(context, "geofence transition: " + transition + "|" + crossed.get(transition), Toast.LENGTH_LONG).show(); FileUtils.writeFile("transition.txt", transition + "|" + crossed.get(transition)); } /** * Report addition or removal errors to the UI, using a Toast * * @param intent A broadcast Intent sent by ReceiveTransitionsIntentService */ private void handleGeofenceError(Context context, Intent intent) { String msg = intent.getStringExtra(GeofenceUtils.EXTRA_GEOFENCE_STATUS); Log.e(GeofenceUtils.APPTAG, msg); Toast.makeText(context, msg, Toast.LENGTH_LONG).show(); } } /** * Define a DialogFragment to display the error dialog generated in showErrorDialog. */ public static class ErrorDialogFragment extends DialogFragment { // Global field to contain the error dialog private Dialog mDialog; /** * Default constructor. Sets the dialog field to null */ public ErrorDialogFragment() { super(); mDialog = null; } /** * Set the dialog to display * * @param dialog An error dialog */ public void setDialog(Dialog dialog) { mDialog = dialog; } /* * This method must return a Dialog to the DialogFragment. */ @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return mDialog; } } /** * Creates an intent with {@link Intent#FLAG_ACTIVITY_CLEAR_TOP} and {@link Intent#FLAG_ACTIVITY_NEW_TASK}. * * @param context the context * @param cls the class */ public static final Intent newIntent(Context context, Class<?> cls) { try { return new Intent(context, cls) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); } catch (Exception ex) { return new Intent(); } } }