/*
* Copyright (C) 2011 Google Inc.
*
* 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.google.example.tv.maps;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import java.io.IOException;
import java.util.List;
/**
* Activity to show the map and all the controls on screen and handles all the
* user events.
*
*/
public class MapViewActivity extends MapActivity {
/**
* Left scrolling speed of map while panning through controls.
*/
private static final int PAN_LEFT_SCROLL_SPEED = -50;
/**
* Right scrolling speed of map while panning through controls.
*/
private static final int PAN_RIGHT_SCROLL_SPEED = 50;
/**
* Downward scrolling speed of map while panning through controls.
*/
private static final int PAN_DOWN_SCROLL_SPEED = 50;
/**
* Upward scrolling speed of map while panning through controls.
*/
private static final int PAN_UP_SCROLL_SPEED = -50;
/**
* Index for fetching the first address from list.
*/
private static final int ZERO_INDEX = 0;
/**
* Initial zoom level.
*/
private static final int MAP_ZOOM_LEVEL = 7;
/**
* Zoom level when maps shows a particular location.
*/
private static final int LOCATION_ZOOM_LEVEL = 14;
/**
* Key for search input stored in preference.
*/
private static final String SEARCH_INPUT_KEY = "search input";
/**
* Key for help dialog.
*/
private static final String HELP_DIALOG_KEY = "show help";
/**
* Constant for preference file name.
*/
private static final String PREF_FILE_NAME = "maps_tv_pref_file";
/**
* A view which display a Map.
*/
private MapView mMapView;
/**
* Control panel layout for all the map controls.
*/
private RelativeLayout mControlPanel;
/**
* Search Bar Layout.
*/
private LinearLayout mSearchbar;
/**
* Map controller to manager panning and zoom.
*/
private MapController mMapController;
/**
* EditText for search location text.
*/
private EditText mSearchEditText;
/**
* Imageview to toggle map, satellite and traffic mode.
*/
private ImageView mMapModeView, mSatelliteModeView, mTrafficModeView;
/**
* Shared preference to store the last search address.
*/
private SharedPreferences mPreferences;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mMapView = (MapView) findViewById(R.id.mapview);
mSearchEditText = (EditText) findViewById(R.id.searchtext);
mMapController = mMapView.getController();
mControlPanel = (RelativeLayout) findViewById(R.id.control_panel);
mMapModeView = (ImageView) findViewById(R.id.map_mode);
mSatelliteModeView = (ImageView) findViewById(R.id.sat_mode);
mTrafficModeView = (ImageView) findViewById(R.id.traffic_mode);
mSearchbar = (LinearLayout) findViewById(R.id.searchbar);
//Pre-load the tiles so that maps can get loaded faster.
mMapView.preLoad();
//Turn on the map mode and set the zoom level.
mMapController.setZoom(MAP_ZOOM_LEVEL);
mMapView.setSatellite(false);
mMapView.setBuiltInZoomControls(true);
mSearchEditText.setFocusable(true);
setSearchEditorActionListner();
}
/**
* Set the listener for the search bar to perform search when user presses
* enter/ok key.
*/
private void setSearchEditorActionListner() {
mSearchEditText.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
//When user puts in the address and press enter on search bar
//then search that location and zoom in.
if (actionId == EditorInfo.IME_NULL) {
goToLocation(mSearchEditText.getText().toString());
}
return true;
}
});
}
@Override
protected void onStart() {
super.onStart();
mPreferences = getSharedPreferences(PREF_FILE_NAME, MODE_PRIVATE);
Boolean shouldShowHelp = mPreferences.getBoolean(HELP_DIALOG_KEY, true);
//Shows the help dialog first time user installs the application.
if (shouldShowHelp) {
showHelpDialog();
// Store that help screen is already shown to user in
// SharedPreferences.
SharedPreferences.Editor editor = mPreferences.edit();
editor.putBoolean(HELP_DIALOG_KEY, false);
editor.commit();
}
//Check if there is previous location stored in preferences and
//pan/zoom to that location on re-launch of that activity.
String lastAddress = mPreferences.getString(SEARCH_INPUT_KEY, "");
if (!TextUtils.isEmpty(lastAddress)) {
mSearchEditText.setText(lastAddress);
goToLocation(lastAddress);
}
}
/**
* Shows the help dialog first time user installs the application.
*
*/
private void showHelpDialog() {
AlertDialog.Builder builder;
builder = new AlertDialog.Builder(this);
builder.setMessage(getResources().getText(R.string.dialog_help_text));
builder.setTitle(getResources().getText(R.string.dialog_title));
builder.setIcon(android.R.drawable.ic_menu_help);
builder.setPositiveButton(getResources().getText(R.string.dialog_button_ok),
new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// Do nothing.
}
});
AlertDialog helpDialog = builder.create();
helpDialog.show();
}
@Override
protected void onStop() {
// Store the current location in preferences for re-launch before
// exiting the application.
String prevAddress = mSearchEditText.getText().toString();
mPreferences = getSharedPreferences(PREF_FILE_NAME, MODE_PRIVATE);
SharedPreferences.Editor editor = mPreferences.edit();
editor.putString(SEARCH_INPUT_KEY, prevAddress);
editor.commit();
super.onStop();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//Inflate the menu items from the menu layout.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_map_controls, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
//Handles the menu item selection.
switch (item.getItemId()) {
case R.id.menu_satellite:
mMapView.setSatellite(true);
mMapView.setTraffic(false);
return true;
case R.id.menu_map:
mMapView.setSatellite(false);
return true;
case R.id.menu_traffic:
if (mMapView.isTraffic()) {
mMapView.setTraffic(false);
} else {
mMapView.setTraffic(true);
mMapView.setSatellite(false);
}
return true;
case R.id.menu_help:
showHelpDialog();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/**
* When satellite mode is clicked by the user.
*
* @param view The satellite view.
*/
public void onSatModeClicked(View view) {
mMapView.setSatellite(true);
mMapView.setTraffic(false);
view.setEnabled(false);
mMapModeView.setEnabled(true);
mTrafficModeView.setEnabled(true);
}
/**
* When map mode is clicked by the user.
*
* @param view The map view.
*/
public void onMapModeClicked(View view) {
mMapView.setSatellite(false);
view.setEnabled(false);
mSatelliteModeView.setEnabled(true);
mTrafficModeView.setEnabled(true);
}
/**
* When traffic mode is clicked by the user.
*
* @param view The traffic view.
*/
public void onTrafficModeClicked(View view) {
if (mMapView.isTraffic()) {
mMapView.setTraffic(false);
mMapModeView.setEnabled(false);
mSatelliteModeView.setEnabled(true);
} else {
// If Traffic mode is selected, show the traffic in Map Mode only.
// If Map is already on satellite mode than automatically change it
// to Map Mode and enable the traffic.
mMapView.setTraffic(true);
mMapView.setSatellite(false);
mMapModeView.setEnabled(false);
mTrafficModeView.setEnabled(false);
mSatelliteModeView.setEnabled(true);
}
}
/**
* On up arrow pan the map upwards.
*
* @param view The up arrow view.
*/
public void onUpArrowClicked(View view) {
mMapController.scrollBy(ZERO_INDEX, PAN_UP_SCROLL_SPEED);
}
/**
* On down arrow pan the map downwards
*
* @param view The down arrow view.
*/
public void onDownArrowClicked(View view) {
mMapController.scrollBy(ZERO_INDEX, PAN_DOWN_SCROLL_SPEED);
}
/**
* On left arrow pan the map to the left.
*
* @param view The left arrow view.
*/
public void onLeftArrowClicked(View view) {
mMapController.scrollBy(PAN_LEFT_SCROLL_SPEED, ZERO_INDEX);
}
/**
* On right arrow pan the map to the right.
*
* @param view The right arrow view.
*/
public void onRightArrowClicked(View view) {
mMapController.scrollBy(PAN_RIGHT_SCROLL_SPEED, ZERO_INDEX);
}
/**
* When clicked display the map in full screen.
*
* @param view The full screen view.
*/
public void onFullScreenClicked(View view) {
//Checks if search bar is visible or not and toggle the search bar
// mode accordingly.
mSearchbar.setVisibility(View.GONE);
mControlPanel.setVisibility(View.GONE);
}
/**
* Event to handle when user press Go button to search a location(geocode).
*
* @param view The search icon view.
*/
public void onGoSearchButtonClicked(View view) {
goToLocation(mSearchEditText.getText().toString());
}
/**
* Search the geo-location and zoom the map to that point.
*
* @param addressEntered The address entered by the user to search.
*/
private void goToLocation(final String addressEntered) {
if (!TextUtils.isEmpty(addressEntered.trim())) {
Geocoder geoCode = new Geocoder(this);
try {
//Get top 5 matched address for this location.
final List<Address> foundAdresses = geoCode.getFromLocationName(addressEntered, 5);
if (foundAdresses.isEmpty()) {
//If no address found, show error through toast.
Toast.makeText(this, getResources().getText(R.string.error_message),
Toast.LENGTH_LONG).show();
} else { // Else display address on map and
// store results as longitude and latitude.
Address address = foundAdresses.get(ZERO_INDEX);
Double latitude = address.getLatitude() * 1E6;
Double longitude = address.getLongitude() * 1E6;
GeoPoint point = new GeoPoint(latitude.intValue(), longitude.intValue());
List<Overlay> mapOverlays = mMapView.getOverlays();
Drawable drawable = this.getResources().getDrawable(R.drawable.marker);
MapsMarkerOverlay itemizedoverlay = new MapsMarkerOverlay(drawable,
getApplicationContext());
OverlayItem overlayitem = new OverlayItem(point, null, null);
itemizedoverlay.addOverlay(overlayitem);
if (mapOverlays.size() > 0) {
mapOverlays.remove(0);
}
mapOverlays.add(itemizedoverlay);
mMapView.preLoad();
//Show the location in the center of the map.
mMapController.setCenter(point);
mMapController.animateTo(point);
mMapController.setZoom(LOCATION_ZOOM_LEVEL);
mMapView.invalidate();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_ZOOM_IN:
mMapView.getController().zoomIn();
break;
case KeyEvent.KEYCODE_ZOOM_OUT:
mMapView.getController().zoomOut();
break;
case KeyEvent.KEYCODE_BACK: {
//Checks if search bar is visible or not and toggle the search bar
//mode accordingly.
if (mSearchbar.getVisibility() != View.VISIBLE) {
mSearchbar.setVisibility(View.VISIBLE);
mControlPanel.setVisibility(View.VISIBLE);
mSearchEditText.requestFocus();
return true;
}
break;
}
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
//Stop panning once user releases the DPad control.
if (keyCode == KeyEvent.KEYCODE_DPAD_UP || keyCode == KeyEvent.KEYCODE_DPAD_DOWN
|| keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
mMapController.stopPanning();
}
return super.onKeyUp(keyCode, event);
}
@Override
protected boolean isRouteDisplayed() {
return false;
}
}