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  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(R.id.map) .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.
        @Override
protected void onStart()
       {
       super.onStart();
       LocationManager locationManager =
               (LocationManager) getSystemService(Context.LOCATION_SERVICE);
       final boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
       if (!gpsEnabled) {
        gpsAlert(); 
       }
   }
   public void gpsAlert(){
    AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle("Enable GPS");
alertDialogBuilder
.setMessage("Yes")
.setCancelable(false)
.setPositiveButton("Yes",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
enableLocationSettings();
dialog.cancel();
}
 })
.setNegativeButton("No",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
dialog.cancel();
}
});
AlertDialog alertDialog = alertDialogBuilder.create(); 
alertDialog.show();
}
   private void enableLocationSettings() {
       Intent settingsIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
       startActivity(settingsIntent);
   }
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);
       mMap.animateCamera(update);
Add a marker to the current latitude and longitude
      Marker source = mMap.addMarker(new MarkerOptions()
                    .position(sc)
                    .title("MyHome")
                    .snippet("Bangalore")
                    .icon(BitmapDescriptorFactory.fromResource(R.drawable.pin)));
Use the destination latitude and longitude and place a marker to the co-ordinates on the map.
     double dlati,dlongi;
     dlati=12.900250;
     dlongi=77.594622;
      LatiLng  dest = new LatLng(dlati,dlongi);
       Marker destination= mMap.addMarker(new MarkerOptions()
                    .position(dest)
                    .title("MapleBear Head Office")
                    .snippet("Jayanager")
                    .icon(BitmapDescriptorFactory.fromResource(R.drawable.pin)));
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;
       @Override
       protected void onPreExecute() {
           // TODO Auto-generated method stub
           super.onPreExecute();
           progressDialog = new ProgressDialog(MainActivity.this);
           progressDialog.setMessage("Fetching route, Please wait...");
           progressDialog.setIndeterminate(true);
           progressDialog.show();
       }
       @Override
       protected Void doInBackground(Void... params) {
           // TODO Auto-generated method stub
           fetchData();
           return null;
       }
       @Override
       protected void onPostExecute(Void result) {
 // Parse the xml response and use the polyline to display the route between source and destination
           super.onPostExecute(result);           
           if(doc!=null){
               NodeList _nodelist = doc.getElementsByTagName("status");
               Node node1 = _nodelist.item(0);
               String _status1  = node1.getChildNodes().item(0).getNodeValue();
               if(_status1.equalsIgnoreCase("OK")){
                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))
                             .width(2).color(Color.BLUE).geodesic(true))   
                 }
                   progressDialog.dismiss();
               }else{
                                   // Unable to find route
                      }
           }else{
                            // 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)));
                poly.add(p);
            }
            return poly;
        }


Fetch the response which is in XML format.
 Document doc = null;
   private void fetchData()
   {
       StringBuilder urlString = new StringBuilder();
       urlString.append("http://maps.google.com/maps/api/directions/xml?origin=");
       urlString.append( Double.toString(flati));
       urlString.append(",");
       urlString.append( Double.toString(flongi));
       urlString.append("&destination=");//to
       urlString.append( Double.toString(dlati));
       urlString.append(",");
       urlString.append( Double.toString(dlongi));
       urlString.append("&sensor=true&mode=walking");    
       Log.d("url","::"+urlString.toString());
       HttpURLConnection urlConnection= null;
       URL url = null;
       try
       {
           url = new URL(urlString.toString());
           urlConnection=(HttpURLConnection)url.openConnection();
           urlConnection.setRequestMethod("GET");
           urlConnection.setDoOutput(true);
           urlConnection.setDoInput(true);
           urlConnection.connect();
           DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
           DocumentBuilder db = dbf.newDocumentBuilder();
           doc = (Document) db.parse(urlConnection.getInputStream());//Util.XMLfromString(response);
       }catch (MalformedURLException e){
           e.printStackTrace();
       }catch (IOException e){
           e.printStackTrace();
       }catch (ParserConfigurationException e){
           e.printStackTrace();
       }
       catch (SAXException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }
   }
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



No comments:

Post a Comment