package edu.vanderbilt.cs282.feisele;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.text.Editable;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
/**
* An activity which prompts the user for latitude and longitude. These values
* are used as part of a location intent. The resulting intent is used to start
* an activity.
*
* <p>
* This behavior can be investigated with the activity manager "am".
*
* @author Fred Eisele <phreed@gmail.com>
*
*/
public class MapDemoActivity extends LifecycleLoggingActivity {
static private final String TAG = "MapDemo";
/**
* Extract the latitude determining if it is valid.
* <p> Recall that the Mercator projection
* does not extend to the poles.
*/
private double LATITUDE_MIN = -90.0;
private double LATITUDE_MERC_MIN = -85.05;
private double LATITUDE_MERC_MAX = 85.05;
private double LATITUDE_MAX = 90.0;
private Double extractLatitude(EditText view) {
final Editable latitudeEditable = view.getText();
final String latitudeString = latitudeEditable.toString();
final double latitude;
try {
latitude = Double.parseDouble(latitudeString);
} catch (NumberFormatException ex) {
final String faultMsg = this.getResources().getString(R.string.latitude_format_error );
view.setError(faultMsg);
return Double.NaN;
}
if (latitude < LATITUDE_MIN) {
final String faultMsg = this.getResources().getString(R.string.latitude_lower_bound_error );
view.setError(faultMsg);
return Double.NaN;
}
if (LATITUDE_MAX < latitude) {
final String faultMsg = this.getResources().getString(R.string.latitude_upper_bound_error );
view.setError(faultMsg);
return Double.NaN;
}
if (latitude < LATITUDE_MERC_MIN) {
final Drawable dr = this.getResources().
getDrawable(R.drawable.indicator_input_warn);
dr.setBounds(0, 0, dr.getIntrinsicWidth(), dr.getIntrinsicHeight());
final String faultMsg = this.getResources().
getString(R.string.latitude_mercator_lower_bound_warn );
view.setError(faultMsg, dr);
Toast.makeText(MapDemoActivity.this,
R.string.latitude_mercator_lower_bound_warn,
Toast.LENGTH_LONG).show();
}
if (LATITUDE_MERC_MAX < latitude) {
final Drawable dr = this.getResources().
getDrawable(R.drawable.indicator_input_warn);
dr.setBounds(0, 0, dr.getIntrinsicWidth(), dr.getIntrinsicHeight());
final String faultMsg = this.getResources().
getString(R.string.latitude_mercator_upper_bound_warn );
view.setError(faultMsg, dr);
Toast.makeText(MapDemoActivity.this,
R.string.latitude_mercator_upper_bound_warn,
Toast.LENGTH_LONG).show();
}
return latitude;
}
/**
* Extract the longitude determining if it is valid.
*/
private double LONGITUDE_MIN = -180.0;
private double LONGITUDE_MAX = 180.0;
private Double extractLongitude(EditText view) {
final Editable longitideEditable = view.getText();
final String longitudeString = longitideEditable.toString();
final double longitude;
try {
longitude = Double.parseDouble(longitudeString);
} catch (NumberFormatException ex) {
final String faultMsg = this.getResources().getString(R.string.longitude_format_error );
view.setError(faultMsg);
return Double.NaN;
}
if (longitude < LONGITUDE_MIN) {
final String faultMsg = this.getResources().getString(R.string.longitude_lower_bound_error );
view.setError(faultMsg);
return Double.NaN;
}
if (LONGITUDE_MAX < longitude) {
final String faultMsg = this.getResources().getString(R.string.longitude_upper_bound_error );
view.setError(faultMsg);
return Double.NaN;
}
return longitude;
}
/**
* There are some choices for the location schema.
* <p>
* <h2>Geo URI</h2>
* <p>
* A Geo URI is "a Uniform Resource Identifier (URI) for geographic
* locations using the 'geo' scheme name. A 'geo' URI identifies a physical
* location in a two- or three-dimensional coordinate reference system in a
* compact, simple, human-readable, and protocol-independent way." -- RFC
* 5870 e.g. geo:36.16,-86.16
* <h2>Google Maps</h2>
* <p>
* This is not a standard but it is in common use. e.g.
* http://maps.google.com/?q=36.16,-86.16
*
*/
static final private String geoUriPrefix = "geo:";
static final private String gmapsUriPrefix = "http://maps.google.com/?q=";
static private Uri getLocationUri(String prefix, double latitude,
double longitude) {
final StringBuilder sb = new StringBuilder(prefix)
.append(latitude).append(",").append(longitude);
return Uri.parse(sb.toString());
}
private EditText latitudeView;
private EditText longitudeView;
/**
* The fields are checked that they are numerical and are within the normal
* bounds for latitude and longitude.
*
* @param savedInstanceState
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_demo);
this.latitudeView = (EditText) findViewById(R.id.edit_latitude);
this.longitudeView = (EditText) findViewById(R.id.edit_longitude);
}
/**
* Performed when the show location button is clicked.
* - extract and validate the latitude and longitude
* - try starting activities with various intents
*
* @param view
* the button view object (unused)
*/
public void showLocation(View view) {
final Double latitude = extractLatitude(this.latitudeView);
final Double longitude = extractLongitude(this.longitudeView);
if (longitude.isNaN() || latitude.isNaN())
return;
final Uri geoUri = getLocationUri(geoUriPrefix, latitude, longitude);
Log.d(TAG, "starting activity with " + geoUri.toString());
try {
final Intent locateIntent = new Intent(
android.content.Intent.ACTION_VIEW, geoUri);
startActivity(locateIntent);
// Activity started successfully
return;
} catch (ActivityNotFoundException ex) {
Log.w(TAG, "no application to handle the intent " + geoUri.toString());
}
final Uri gmapsUri = getLocationUri(gmapsUriPrefix, latitude, longitude);
Log.d(TAG, "starting activity with " + gmapsUri.toString());
try {
final Intent locateIntent = new Intent(
android.content.Intent.ACTION_VIEW, gmapsUri);
startActivity(locateIntent);
// Activity started successfully
return;
} catch (ActivityNotFoundException ex) {
Log.w(TAG, "no application to handle the intent " + gmapsUri.toString());
Toast.makeText(MapDemoActivity.this, R.string.no_app_capable,
Toast.LENGTH_LONG).show();
}
}
}