10.5 Android Map Based activities

Hello Readers!! Hope you are doing well. Android platform supports Google Maps. Although we have used Google maps in our previous tutorial sections but weare going to learn the basics of maps. Trust me; you will love doing this maps tutorial. Let us not waste time and start maps.

10.1 Introduction

Android platform comes bundled with Google Maps. We can not only use maps but we can embed maps in our applications which we have already done in the previous sections. Now we are to the basics. Most common usage of Google Maps is as shown in the following listing:

  • We can change views of Google maps
  • We can obtain latitude and longitude of locations in Google Maps
  • We can translate address into latitude and longitude values.
  • We can translate street address from latitude and longitude of a particular location.
  • We can add markers to Google Maps

We need to have Google APIs added on in our project. This add-on includes standard Android library along with Maps library which are packaged within maps.jar file. We need to apply for a free Google Maps API key before wecan integrate Google Maps into our Android application. When we apply for the key, we must also agree to Google’s terms of use. To obtain key we need to follow certain steps. We need to have a google account for sure before doing any such thing. Before testing the application on the Android Emulator or an Android device directly connected to our development machine, we have to locate the SDK debug certificate located in the default folder. We can verify the existence of the debug certificate by navigating to Eclipse and selecting Window->Preferences. Then we have to expand the Android item and choose Build. On the right side of the window, we will be able to see the debug certificate’s location. Filename of the debug key store is debug.keystore. This is the certificate which Eclipse uses to sign our application so that it may be run on the Android Emulator or devices. The debug keystore is used to extract its MD5 fingerprint. It in turn uses the Keytool.exe application which is included with our JDK installation. This fingerprint is required to apply for the free Google Maps key. The Keytool.exe application is usually found in the C:\Program​Files\Java\<JDK_version_number>\bin folder.
The key class in the Google Maps Android API is MapView. A map is displayed by the MapViewwith data obtained from the Google Maps service. MapView will capture key presses and touch gestures to pan and zoom the map automatically. It also handles network requests for additional map tiles.

10.2 Maps Key

Following set up is required to use MapView class:

1. Download and install the Google API’s Software Development Kit (SDK).

2. Obtain a valid Maps API key to use the Google Maps service

2. Obtain a valid Maps API key to use the Google Maps service

Use the keytool command to generate an MD5 certificate fingerprint for the key alias_name:

keytool -list -alias alias_name -keystoremy.keystore

 

                                          Figure Extracting the MD5 fingerprint

The overall process of adding a map to an Android application is as follows:

  1. Download and configure the Google Play services SDK. The Google Maps Android API is distributed as part of this SDK.
  2. Obtain an API key. To do this, you will need to register a project in the Google APIs Console, and get a signing certificate for your app.
  3. Specify settings in the Application Manifest.
  4. Add a map to a new or existing Android project.
  5. Publish your application

Obtaining a key for your application requires several steps

  1. Retrieve information about your application's certificate.
  2. Register a project in the Google APIs Console and add the Maps API as a service for the project.
  3. Once you have a project set up, you can request one or more keys.
  4. Finally, you can add your key to your application and begin development

 

                                                                    Figure Obtaining API Key

As soon as key is generated, it can be used for the application.

 

                                                           Figure Generated API key

10.3 Example

Create a project and name it as you like. I am naming it as MapOverlay app. Open the activity_main.xml file and populate the class as shown in the following listing:

<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
    android:orientation="vertical"
>
<com.google.android.maps.MapView
android:id="@+id/mapView"
android:clickable="true"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:enabled="true"
android:apiKey="<your key>"
>
</com.google.android.maps.MapView>
</LinearLayout>

                                                                                Figure activity_main.xml

Open the main activity file and populate the class as shown in the following listing:

packagecom.android.tution.MapOver;
importjava.io.IOException;
importjava.util.List;
importjava.util.Locale;
importcom.google.android.maps.GeoPoint;
importcom.google.android.maps.MapActivity;
importcom.google.android.maps.MapController;
importcom.google.android.maps.MapView;
importcom.google.android.maps.MyLocationOverlay;
importcom.google.android.maps.Overlay;
importcom.google.android.maps.OverlayItem;
importandroid.app.AlertDialog;
importandroid.content.DialogInterface;
importandroid.graphics.drawable.Drawable;
importandroid.location.Address;
importandroid.location.Geocoder;
importandroid.os.Bundle;
importandroid.view.MotionEvent;
importandroid.widget.Toast;
publicclassMainActivityextendsMapActivity {
    longstart;
    longstop;
MapViewmap;
MyLocationOverlaycompass;
MapControllercontroller;
Double lat,lon;
GeoPointtouch;
intx,y;
List<Overlay>overlays; 
Drawabled;
@Override
publicvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
map=(MapView)findViewById(R.id.mapView);
map.setBuiltInZoomControls(true);
map.setSatellite(true);
        Touchy t=newTouchy();
overlays=map.getOverlays();
overlays.add(t);
compass=newMyLocationOverlay(MainActivity.this, map);
overlays.add(compass);
controller=map.getController();
lat=30.7363236*1E6;
lon=76.7350951*1E6;
GeoPoint point=newGeoPoint(lat.intValue(),lon.intValue());
controller.animateTo(point);
controller.setZoom(7);
d=getResources().getDrawable(R.drawable.ic_launcher);
    }
    @Override
    protectedvoidonPause() {
        // TODO Auto-generated method stub
    compass.disableCompass();
        super.onPause();
    }

                                                                    Figure first half of activity class

Second half of class is as shown in the following listing:

@Override
    protectedvoidonResume() {
        // TODO Auto-generated method stub        
        compass.enableCompass();
        super.onResume();
    }
    @Override
    protectedbooleanisRouteDisplayed() {
        // TODO Auto-generated method stub
        returnfalse;
    }
publicclass Touchy extends Overlay{
publicbooleanonTouchEvent(MotionEvente,MapView m){    
    if(e.getAction()==MotionEvent.ACTION_DOWN)
     {
        start=e.getEventTime();
        x=(int)e.getX();
        y=(int)e.getY();
        touch=map.getProjection().fromPixels(x, y);
     }
    if(e.getAction()==MotionEvent.ACTION_UP)
     {
        stop=e.getEventTime();
     }    
    if((stop - start) > 1500)
     {    
        AlertDialog alert=newAlertDialog.Builder(MainActivity.this).create();
        alert.setTitle("Pick an option");
        alert.setMessage("just pick one of these");        
        alert.setButton("place a pinpoint", newDialogInterface.OnClickListener() {            
            @Override
            publicvoidonClick(DialogInterface dialog, int which) {
                // TODO Auto-generated method stub        
            OverlayItemoverlayItem=newOverlayItem(touch, "what's up", "simple string");    
            CustomPinpoint custom=newCustomPinpoint(d,MainActivity.this);
            custom.insertPinpoint(overlayItem);
            overlays.add(custom);        
            }
        });

                                                                             Figure Second half of class

After a long press or click we would be alerted with options to toggle view or get address etc. Third half of code is as shown in the following listing:

alert.setButton2("get an address", newDialogInterface.OnClickListener() {            
            @Override
            publicvoidonClick(DialogInterface dialog, int which) {
                // TODO Auto-generated method stub                
                Geocoder geocode=newGeocoder(getBaseContext(),Locale.getDefault());
                try{            
                    List<Address> address=geocode.getFromLocation(touch.getLatitudeE6()/1E6, touch.getLongitudeE6()/1E6, 1);
                    if(address.size()>0){
                        String display="";
                        for(inti=0;i<address.get(0).getMaxAddressLineIndex();i++){
                            display += address.get(0).getAddressLine(i)+ "\n";            
                        }
                    Toast t=Toast.makeText(getBaseContext(), display, Toast.LENGTH_LONG);
                    t.show();
                    }                    
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }finally{                    
                }
            }        
        });    
alert.setButton3("Toggle View", newDialogInterface.OnClickListener() {    
    @Override
    publicvoidonClick(DialogInterface dialog, int which) {
        // TODO Auto-generated method stub        
        if(map.isSatellite())
        {
            map.setSatellite(false);
            map.setStreetView(true);
        }else{
            map.setStreetView(false);
            map.setSatellite(true);
        }
    }
});
    alert.show();
returntrue;
     }    
    returnfalse;
 }
}
}

                                                                                     Figure third half of class

In this project we shall have a custom pin point on map. Create another inner class and name it CustomPinpoint. Populate this class as shown in the following listing:

packagecom.android.tution.MapOver;
importjava.util.ArrayList;
importandroid.content.Context;
importandroid.graphics.drawable.Drawable;
importcom.google.android.maps.ItemizedOverlay;
importcom.google.android.maps.OverlayItem;
publicclassCustomPinpointextendsItemizedOverlay<OverlayItem>{
    privateArrayList<OverlayItem>pinpoints=newArrayList<OverlayItem>();
    public Context c;    
    publicCustomPinpoint(DrawabledefaultMarker) {
        super(boundCenter(defaultMarker));
        // TODO Auto-generated constructor stub
    }
    publicCustomPinpoint(Drawablem,Context context) {
        // TODO Auto-generated constructor stub
        this(m);
        c=context;    
    }    
    @Override
    protectedOverlayItemcreateItem(inti) {
        // TODO Auto-generated method stub
        returnpinpoints.get(i);
    }
    @Override
    publicint size() {
        // TODO Auto-generated method stub
        returnpinpoints.size();
    }
publicvoidinsertPinpoint(OverlayItem item)
{
pinpoints.add(item);
this.populate();
}
}

                                                                       Figure CustomPinpoint class

Okay guys we done with coding part. Now let us do our last task of manifest file. Open the manifest file and populate it as shown in the following listing:

<?xmlversion="1.0"encoding="utf-8"?>
<manifestxmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.tution.MapOver"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17"/>
<uses-permissionandroid:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permissionandroid:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<uses-libraryandroid:name="com.google.android.maps"
></uses-library>
<activity
android:name="com.android.tution.MapOver.MainActivity"
android:label="@string/app_name">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>

                                                                            Figure manifest file

Create a suitable emulator and run your application. It should look similar to the following application’s snapshot:

          

                                                                         Figure Output of app

Congratulations buddiesJ!!! We are done with maps. Hope you enjoyed this section. Till then keep practicing. Happy App Developing!!!