Wednesday, 24 April 2013

Google Map API V2. (part 2 continued from part 1)

Part 1 displayed map on the screen. In part 2 i will show how to add markers and poly line to map. The map should display marker's on the source and destination co-ordinates along with the route between fro source to destination.

The Map Object

The Google Maps Android API allows you to display a Google map in your Android application. These maps have the same appearance as the maps you see in the Google Maps for Mobile (GMM) app, and the API exposes many of the same features.
Define a private GoogleMap variable.
private GoogleMap mMap;
In your activity check map is null. 
         if (mMap == null) 
              mMap = ((MapFragment) getFragmentManager().findFragmentById( .getMap();
       if (mMap != null) {
           // The Map is verified. It is now safe to manipulate the map. 
Override onStart() of your activity. To get the current location latitude and longitude you need GPS Enabled. So check if it is enabled or not. If not enables prompt the user to enable the same.
protected void onStart()
       LocationManager locationManager =
               (LocationManager) getSystemService(Context.LOCATION_SERVICE);
       final boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
       if (!gpsEnabled) {
   public void gpsAlert(){
    AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle("Enable GPS");
.setPositiveButton("Yes",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
.setNegativeButton("No",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
AlertDialog alertDialog = alertDialogBuilder.create();;
   private void enableLocationSettings() {
       Intent settingsIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
Get the current latitude and longitude of your current location.
       double clati,clongi;
LocationManager locationmanage = (LocationManager) getSystemService(Context.LOCATION_SERVICE);   
 Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
  if (location != null) {
 clati = location.getLatitude();
  clongi = location.getLongitude();

Use the current latitude and longitude and zoom the map to the co-ordinates using the Camera
      LatiLng  source = new LatLng(clati,clongi);
      CameraUpdate update= CameraUpdateFactory.newLatLngZoom(source,9);
Add a marker to the current latitude and longitude
      Marker source = mMap.addMarker(new MarkerOptions()
Use the destination latitude and longitude and place a marker to the co-ordinates on the map.
     double dlati,dlongi;
      LatiLng  dest = new LatLng(dlati,dlongi);
       Marker destination= mMap.addMarker(new MarkerOptions()
                    .title("MapleBear Head Office")
Next we can display the route using between the source and the destination. For that we need all latitude and longitude co-ordinates between source and destination. Using the source and destination latitude and longitude we will make a http get request to the google server to get the list of latitudes and longitudes.
Making network related operation should be done on background thread on Android 3.0 and above. We will use asynctask for this purpose
 Load the Asynctask on the UI Thread
             new connectAsyncTask().execute()
   private class connectAsyncTask extends AsyncTask<Void, Void, Void>{
       private ProgressDialog progressDialog;
       protected void onPreExecute() {
           // TODO Auto-generated method stub
           progressDialog = new ProgressDialog(MainActivity.this);
           progressDialog.setMessage("Fetching route, Please wait...");
       protected Void doInBackground(Void... params) {
           // TODO Auto-generated method stub
           return null;
       protected void onPostExecute(Void result) {
 // Parse the xml response and use the polyline to display the route between source and destination
               NodeList _nodelist = doc.getElementsByTagName("status");
               Node node1 = _nodelist.item(0);
               String _status1  = node1.getChildNodes().item(0).getNodeValue();
                Toast.makeText(MainActivity.this,"OK" , 1000).show();
                   NodeList _nodelist_path = doc.getElementsByTagName("overview_polyline");
                   Node node_path = _nodelist_path.item(0);
                   Element _status_path = (Element)node_path;
                   NodeList _nodelist_destination_path = _status_path.getElementsByTagName("points");
                   Node _nodelist_dest = _nodelist_destination_path.item(0);
                   String _path  = _nodelist_dest.getChildNodes().item(0).getNodeValue();
                   List<LatLng> points = decodePoly(_path);
                   for (int i = 0; i < points.size() - 1; i++) {
                     LatLng src = points.get(i);
                     LatLng dest = points.get(i + 1);
                        // Polyline to display the routes
                     Polyline line = mMap.addPolyline(new PolylineOptions()
                             .add(new LatLng(src.latitude, src.longitude),
                               new LatLng(dest.latitude,dest.longitude))
                                   // Unable to find route
                            // Unable to find route
The below function will return a list of latitude and longitudes between source and destination
   private List<LatLng> decodePoly(String encoded) {    
            List<LatLng> poly = new ArrayList<LatLng>();
            int index = 0, len = encoded.length();
            int lat = 0, lng = 0;
            while (index < len) {
                int b, shift = 0, result = 0;
                do {
                    b = encoded.charAt(index++) - 63;
                    result |= (b & 0x1f) << shift;
                    shift += 5;
                } while (b >= 0x20);
                int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
                lat += dlat;
                shift = 0;
                result = 0;
                do {
                    b = encoded.charAt(index++) - 63;
                    result |= (b & 0x1f) << shift;
                    shift += 5;
                } while (b >= 0x20);
                int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
                lng += dlng;
                LatLng p = new LatLng((((double) lat / 1E5)), (((double) lng / 1E5)));
            return poly;

Fetch the response which is in XML format.
 Document doc = null;
   private void fetchData()
       StringBuilder urlString = new StringBuilder();
       urlString.append( Double.toString(flati));
       urlString.append( Double.toString(flongi));
       urlString.append( Double.toString(dlati));
       urlString.append( Double.toString(dlongi));
       HttpURLConnection urlConnection= null;
       URL url = null;
           url = new URL(urlString.toString());
           DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
           DocumentBuilder db = dbf.newDocumentBuilder();
           doc = (Document) db.parse(urlConnection.getInputStream());//Util.XMLfromString(response);
       }catch (MalformedURLException e){
       }catch (IOException e){
       }catch (ParserConfigurationException e){
       catch (SAXException e) {
           // TODO Auto-generated catch block
When you run the project on your device you can see marker and route between source and destination.
You can also specify few settings on how the map is displayed
            mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE); // Satellite map
            UiSettings uis =mMap.getUiSettings();
    ui.setCompassEnabled(true);    //enable compass

Using Spannable String in Android

SpannableString can be used to style texts in textview. You can style individual words in textview.

                            TextView tv = (TextView) findViewById(; 
                            String myString = "Hello World";

                            SpannableString  ss=  new SpannableString(myString);
                            ss.setSpan(new StyleSpan(Typeface.BOLD), 0, ss.length(), 0);
                            //make the spannable string bold.
                            //first parameter is to style the text
                            //second parameter is 0 indicating the index from which the text should be styled.
                            //third parameter is the legth of the spannable string.                           
            ss.setSpan(new StyleSpan(Typeface.ITALIC), 0, ss.length(), 0);
                            //make the spannable string italic
            ss.setSpan(new ForegroundColorSpan(Color.BLUE), 0, ss.length(), 0);   
                            //change the color of the spannable string     

Make Spannable String Clickable

      ss.setSpan(MyClickableSpan(ss) , 0, ss.length(), 0);

      class MyClickableSpan extends ClickableSpan

                    String clicked;
                    //Constructor to receive the clicked text
                    public MyClickableSpan(String string) {
            clicked =string;
                    // action to be performed on click 
                    public void onClick(View tv) {
                    Toast.makeText(MainActivity.this,clicked ,Toast.LENGTH_SHORT).show();   

                    //update the drawable state of the text  
                    public void updateDrawState(TextPaint ds) {
                    //set text color 
                    //set stroke width   
                    // set to false to remove underline
Google map api v2 on Android.(part 1)

Steps to get map working on Android.

1.  Download the  Google Play services.
         Goto Windows. Goto Android Sdk Manager. Choose Google play services under extras.
         If not installed install the package.

2.  Copy the google-play services_lib library project to your workspace. The library project can be found under the following path.

         <android-sdk-folder>/extras/google/google_play_services/libproject/google-play-services_lib library project .

3. Import the library project to your eclipse

    Click File > Import, select Android > Existing Android Code into Workspace, and browse the     workspace  import the library project. You can check if it is library project. Right click on the library project. Goto properties. Click Android on the left panel. You will see Is Library checked.

4. Create your Android project like normally you would do for other projects.

5. You need to refer the google-play services_lib library project in your android project.

Right click on your android project.  Goto properties. Choose Android on the left panel. Click on Add and browse the library project. Select the same. Click ok and apply.

6. Obtain API key
     A) Locate your debug keystore file. The file name is debug.keystore, and is created the first time you build your project. By default, it is stored in the same directory as your Android Virtual Device (AVD) files:
  • OS X and Linux~/.android/
  • Windows Vista and Windows 7C:\Users\your_user_name\.android\
If you are using Eclipse with ADT, and you're not sure where your debug keystore is located, you can select Windows > Prefs > Android > Build to check the full path, which you can then paste into a file explorer to locate the directory containing the keystore.
    B) If your using linux or mac os, open terminal and use the following 
      keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
Example for linux:
      keytool -list -v -keystore /home/raghu/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android  

       If you are using Windows or Vista use the following in our command prompt
       keytool -list -v -keystore "C:\Users\your_username\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android.

Note: keytool can be found under jdk bin folder. jdk1.7.0_07/bin/keytool
When you execute the above commands you should see the below output
  Alias name: androiddebugkey
 Creation date: Jan 01, 2013
 Entry type: PrivateKeyEntry
 Certificate chain length: 1
 Owner: CN=Android Debug, O=Android, C=US
 Issuer: CN=Android Debug, O=Android, C=US
 Serial number: 4aa9b300
 Valid from: Mon Jan 01 08:04:04 UTC 2013 until: Mon Jan 01 18:04:04 PST 2033
 Certificate fingerprints:
      MD5:  AE:9F:95:D0:A6:86:89:BC:A8:70:BA:34:FF:6A:AC:F9
      SHA1: BB:0D:AC:74:D3:21:E1:43:07:71:9B:62:90:AF:A1:66:6E:44:5D:75
      Signature algorithm name: SHA1withRSA
      Version: 3

The line that begins SHA1 contains the certificate's SHA-1 fingerprint. The fingerprint is the sequence of 20 two-digit hexadecimal numbers.
                           SHA1: BB:0D:AC:74:D3:21:E1:43:07:71:9B:62:90:AF:A1:66:6E:44:5D:75.
7 .Open the browser and open the following url. (Rememeber to login into google account)
   You should see a window as below

   Click on the create project. On the left you can see API Project. You can click the drop down list and rename it to whatever you like. Click on the services. Scroll Down the list and look for Google Maps API V2 and Google Maps Android ApI v2. Enable the same.
Click on API Access on the left panel. Click on create new Android key

Add the fingerprint along with your android project package name.
Note: You package name is seperated by a semicolon. Click On Create.

 You should the above window. Copy the API key for later use.

Adding the API Key to your application

The final step is to add the API key to your application. It goes in your application's manifest, contained in the file AndroidManifest.xml. From there, the Maps API reads the key value and passes it to the Google Maps server, which then confirms that you have access to Google Maps data.
To add the key to your application:
  1. In AndroidManifest.xml, add the following element as a child of the <application> element, by inserting it just before the closing tag</application>:
    substituting your API key for your_api_key. This element sets the key to the value your_api_key and makes the API key visible to any MapFragment in your application.
  2. Add the following elements to your manifest. Replace com.example.mapdemo with the package name of your application
    <uses-permission android:name="com.example.mapdemo.permission.MAPS_RECEIVE"/>

         3. Add the following permissions in the Manifest file
<uses-permission android:name="com.example.mapdemo.permission.MAPS_RECEIVE"/>  
 <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <uses-permission android:name=""/>
     <!-- The following two permissions are not required to use
     Google Maps Android API v2, but are recommended. -->
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="com.example.mapdemo.permission.MAPS_RECEIVE"/> 
In the above permission you need to replace com.example.mapdemo with your project package name.

Because version 2 of the Google Maps Android API requires OpenGL ES version 2, you must add a <uses-feature> element as a child of the <manifest>element in AndroidManifest.xml:

Save the manifest file.
The last few steps
Add the following to your activity_main.xml file
     <RelativeLayout xmlns:android=""
    tools:context=".MainActivity" >
          android:text="My Map" />

package com.example.mapdemo;
import android.os.Bundle;
public class MainActivity extends Activity {

    protected void onCreate(Bundle savedInstanceState) {
Run the project on your device and you should see the Google map on your screen