Back to project page getback_gps.
The source code is released under:
GNU General Public License
If you think the Android project getback_gps listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/** * Main Activity/*from w ww . j a v a 2 s .c o m*/ * * Copyright (C) 2012-2015 Dieter Adriaenssens * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * @package com.github.ruleant.getback_gps * @author Dieter Adriaenssens <ruleant@users.sourceforge.net> */ package com.github.ruleant.getback_gps; import android.app.Activity; import android.app.AlertDialog; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.ServiceConnection; import android.content.res.Resources; import android.os.Bundle; import android.os.IBinder; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import com.github.ruleant.getback_gps.LocationService.LocationBinder; import com.github.ruleant.getback_gps.lib.CardinalDirection; import com.github.ruleant.getback_gps.lib.FormatUtils; import com.github.ruleant.getback_gps.lib.Navigator; import com.github.ruleant.getback_gps.lib.Tools; import de.keyboardsurfer.android.widget.crouton.Configuration; import de.keyboardsurfer.android.widget.crouton.Crouton; import de.keyboardsurfer.android.widget.crouton.Style; /** * Abstract Ariadne Activity class, contains the common methods * to connect to LocationService. Other activities that need LocationService * can extend this class. * * @author Dieter Adriaenssens <ruleant@users.sourceforge.net> */ abstract class AbstractGetBackGpsActivity extends Activity { /** * Interface to LocationService instance. */ private LocationService mService; /** * Connection state with LocationService. */ private boolean mBound = false; /** * Realtime timestamp in nanoseconds when activity was updated. */ private long mUpdatedTimestamp = 0; /** * Activity update rate in nanoseconds (500ms). */ private static final int ACTIVITY_UPDATE_RATE = 500000000; /** * Inaccurate location crouton. */ private Crouton crInaccurateLocation; /** * 'No destination set' crouton. */ private Crouton crNoDestination; /** * Inaccurate direction crouton. */ private Crouton crInaccurateDirection; /** * 'Destination reached' crouton. */ private Crouton crDestinationReached; @Override public boolean onCreateOptionsMenu(final Menu menu) { // Inflate the menu; // this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.common, menu); return true; } @Override protected final void onStart() { super.onStart(); // Bind to LocationService Intent intent = new Intent(this, LocationService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @Override protected final void onStop() { super.onStop(); // Unbind from the service if (mBound) { unbindService(mConnection); mBound = false; } } @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); // create Crouton configuration Configuration croutonConfig = new Configuration.Builder() .setDuration(Configuration.DURATION_INFINITE) .build(); // create inaccurate location crouton crInaccurateLocation = Crouton.makeText(this, R.string.inaccurate_location, Style.ALERT); crInaccurateLocation.setConfiguration(croutonConfig); // create inaccurate direction crouton crInaccurateDirection = Crouton.makeText(this, R.string.inaccurate_direction, Style.INFO); crInaccurateDirection.setConfiguration(croutonConfig); // create 'no destination set' crouton crNoDestination = Crouton.makeText(this, R.string.notice_no_dest, Style.INFO); crNoDestination.setConfiguration(croutonConfig); // create 'destination reached' crouton crDestinationReached = Crouton.makeText(this, R.string.notice_destination_reached, Style.CONFIRM); crDestinationReached.setConfiguration(croutonConfig); } @Override protected final void onDestroy() { super.onDestroy(); // Cancel active croutons Crouton.cancelAllCroutons(); } /** * Called when the user clicks the Store Location menu item. * It displays a dialog, where the user confirm or cancel storing * the current location. */ final void storeLocation() { if (mBound && mService.getLocation() == null) { Toast.makeText( this, R.string.store_location_disabled, Toast.LENGTH_LONG ).show(); return; } // Use the Builder class for convenient dialog construction, // based on the example on // https://developer.android.com/guide/topics/ui/dialogs.html AlertDialog.Builder builder = new AlertDialog.Builder(this); // Get the layout inflater LayoutInflater inflater = this.getLayoutInflater(); // Inflate the layout for the dialog // Pass null as the parent view because its going in the dialog layout final View dialogView = inflater.inflate(R.layout.dialog_location_name, null); // Get the EditText object containing the location name final EditText etLocationName = (EditText) dialogView.findViewById(R.id.location_name); // Set the layout for the dialog builder.setView(dialogView) .setTitle(R.string.store_location) .setPositiveButton(R.string.store_location, new DialogInterface.OnClickListener() { public void onClick(final DialogInterface dialog, final int id) { if (etLocationName != null) { String locationName = etLocationName.getText().toString(); // store current location // and refresh display if (mBound) { mService.storeCurrentLocation( locationName); } refreshDisplay(); } } }) .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(final DialogInterface dialog, final int id) { // User cancelled the dialog } }); // Create the AlertDialog object and display it builder.create().show(); } /** * Called when the user clicks the Rename Destination menu item. * It displays a dialog, where the user can enter a new name * for the current destination. */ final void renameDestination() { if (mBound && mService.getDestination() == null) { Toast.makeText( this, R.string.rename_destination_disabled, Toast.LENGTH_LONG ).show(); return; } // Use the Builder class for convenient dialog construction, // based on the example on // https://developer.android.com/guide/topics/ui/dialogs.html AlertDialog.Builder builder = new AlertDialog.Builder(this); // Get the layout inflater LayoutInflater inflater = this.getLayoutInflater(); // Inflate the layout for the dialog // Pass null as the parent view because it's going // into the dialog layout final View dialogView = inflater.inflate(R.layout.dialog_location_name, null); // Get the TextView object containing the location question final TextView tvLocationMessage = (TextView) dialogView.findViewById(R.id.location_message); if (tvLocationMessage != null) { // set message for renaming destination tvLocationMessage.setText(R.string.dialog_rename_destination); } // Get the EditText object containing the location name final EditText etLocationName = (EditText) dialogView.findViewById(R.id.location_name); if (etLocationName != null) { // set current destination name as default etLocationName.setText(mService.getDestination().getName()); } // Set the layout for the dialog builder.setView(dialogView) .setTitle(R.string.rename_destination) .setPositiveButton(R.string.rename_destination, new DialogInterface.OnClickListener() { public void onClick(final DialogInterface dialog, final int id) { if (etLocationName != null) { String locationName = etLocationName.getText().toString(); // store current location // and refresh display if (mBound) { mService.renameDestination( locationName); } refreshDisplay(); } } }) .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(final DialogInterface dialog, final int id) { // User cancelled the dialog } }); // Create the AlertDialog object and display it builder.create().show(); } /** * Called when the user clicks the refresh menu item. * * @param item MenuItem object that was clicked */ final void refresh(final MenuItem item) { if (mBound) { mService.updateLocationProvider(); mService.updateLocation(); } refreshDisplay(); } /** * Called when the user clicks the About menu item. * * @param item MenuItem object that was clicked */ final void displayAbout(final MenuItem item) { Intent intent = new Intent(this, AboutActivity.class); startActivity(intent); } /** * Called when the user clicks the Settings menu item. * * @param item MenuItem object that was clicked */ final void displaySettings(final MenuItem item) { Intent intent = new Intent(this, SettingsActivity.class); startActivity(intent); } @Override public boolean onOptionsItemSelected(final MenuItem item) { // One of the group items (using the onClick attribute) was clicked // The item parameter passed here indicates which item it is // All other menu item clicks are handled by onOptionsItemSelected() int itemId = item.getItemId(); if (itemId == R.id.menu_settings) { displaySettings(item); return true; } else if (itemId == R.id.menu_about) { displayAbout(item); return true; } else if (itemId == R.id.menu_storelocation) { storeLocation(); return true; } else if (itemId == R.id.menu_renamedestination) { renameDestination(); return true; } else if (itemId == R.id.menu_refresh) { refresh(item); return true; } else { return super.onOptionsItemSelected(item); } } @Override public boolean onPrepareOptionsMenu(final Menu menu) { MenuItem miStoreLocation = menu.findItem(R.id.menu_storelocation); MenuItem miRenameDest = menu.findItem(R.id.menu_renamedestination); if (isBound()) { // enable store location button if a location is set miStoreLocation.setEnabled(mService.getLocation() != null); // enable store location button if a location is set miRenameDest.setEnabled(mService.getDestination() != null); } return super.onPrepareOptionsMenu(menu); } /** * Refresh display : refresh the values of Location Provider, Location, ... * * @return true if refresh was successful */ protected boolean refreshDisplay() { // only refresh items if activity is bound to service if (!isBound() || Tools.isTimestampNanoRecent( mUpdatedTimestamp, ACTIVITY_UPDATE_RATE)) { return false; } mUpdatedTimestamp = Tools.getTimestampNano(); refreshCrouton(); return true; } /** * Update which crouton should be displayed. */ final void refreshCrouton() { // only refresh items if activity is bound to service // connection state is checked in getNavigator Navigator navigator = getNavigator(); if (navigator == null) { return; } // if location is inaccurate, display warning if (!navigator.isLocationAccurate()) { crInaccurateLocation.show(); } else { crInaccurateLocation.cancel(); // if no destination is set, display message if (navigator.getDestination() == null) { crNoDestination.show(); } else { crNoDestination.cancel(); // destination was reached if (navigator.isDestinationReached()) { crDestinationReached.show(); } else { crDestinationReached.cancel(); // if bearing is inaccurate, display warning if (!navigator.isBearingAccurate()) { crInaccurateDirection.show(); } else { crInaccurateDirection.cancel(); } } } } } /** * Refresh current speed/bearing views. * * @param displayInaccurate display value when it is inaccurate */ final void refreshCurrentViews(final boolean displayInaccurate) { // only refresh items if activity is bound to service // connection state is checked in getNavigator Navigator navigator = getNavigator(); if (navigator == null) { return; } Resources res = getResources(); // Get "Current" TextViews TextView tvCurrentSpeed = (TextView) findViewById(R.id.textView_currSpeed); TextView tvCurrentBearing = (TextView) findViewById(R.id.textView_currBearing); // Define strings String currentSpeedText = res.getString(R.string.inaccurate); String currentBearingText = res.getString(R.string.inaccurate); // Update current speed if (displayInaccurate || navigator.isLocationAccurate()) { currentSpeedText = FormatUtils.formatSpeed( navigator.getCurrentSpeed(), this); } // Update current bearing if (displayInaccurate || navigator.isBearingAccurate()) { CardinalDirection cd = new CardinalDirection( this, FormatUtils.normalizeAngle( navigator.getCurrentBearing())); currentBearingText = cd.format(); } // update views tvCurrentSpeed.setText(currentSpeedText); tvCurrentBearing.setText(currentBearingText); } /** * Returns bound state to Location Service. * * @return boolean Bound State */ final boolean isBound() { return mBound; } /** * Returns Location Service. * * @return LocationService */ final LocationService getService() { if (isBound()) { return mService; } else { return null; } } /** * Returns Navigator. * * @return Navigator */ final Navigator getNavigator() { LocationService service = getService(); if (service == null) { return null; } return service.getNavigator(); } /** * Defines callbacks for service binding, passed to bindService(). */ private final ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected( final ComponentName className, final IBinder service) { // We've bound to LocationService, cast the IBinder // and get LocationService instance LocationBinder binder = (LocationBinder) service; mService = binder.getService(); mBound = true; // We want to monitor the service for as long as we are // connected to it. binder.registerCallback(mCallback); refreshDisplay(); } @Override public void onServiceDisconnected(final ComponentName arg0) { mBound = false; } }; /** * This implementation is used to receive callbacks * from the remote service. */ private final ILocationServiceCallback mCallback = new ILocationServiceCallback.Stub() { /** * Called by the LocationService when a location is updated, * it gets the new location and refreshes the display. */ public void locationUpdated() { refreshDisplay(); } /** * Called by the LocationService when a orientation is updated, * it gets the new location provider and refreshes the display. */ public void orientationUpdated() { refreshDisplay(); } /** * Called by the LocationService when a location provider is updated, * it gets the new location provider and refreshes the display. */ public void providerUpdated() { refreshDisplay(); } }; }