Storing Google Maps Android API V2 marker locations in MySQL

October 14, 2013
By

In this article, we will develop an Android application that stores user touched locations of Google Maps in a remote MySQL server. Since this application is developed using SupportMapFragment, it can support Android API version 8 and above.

In order to send latitude and longitude from the application to the web server, we are using HTTPUrlConnection api in “POST” request method.

Screenshot of this application is available towards the end of this article.

This application is developed in Eclipse ( 4.2.0 ) with Android SDK ( 22.2.1 ) and ADT plugin ( 22.2.1 ) and is tested in Android API Level 2.3.6 and 4.1.2.


1. Create new Android application with the given below details

Application Name : LocationMarkerMySQL

Project Name : LocationMarkerMySQL

Package Name : in.wptrafficanalyzer.locationmarkermysql

Minimum Required SDK : API 8: Android 2.2 ( Froyo )

Target SDK : API 18: Android 4.3

Compile With: API 18: Android 4.3

Theme : Holo Light with Dark Action Bar


2. Download and configure Google Play Services Library in Eclipse

Please follow the given below link to setup Google Play Service library in Eclipse.

http://developer.android.com/google/play-services/setup.html


3. Referencing the Google Play Services library in this project

Please follow the given below link to reference the Google Play Service library into this project

http://developer.android.com/tools/projects/projects-eclipse.html#ReferencingLibraryProject


4. Get the API key for Google Maps Android API V2

We need to get an API key from Google to use Google Maps in Android application.

Please follow the given below link to get the API key for Google Maps Android API v2.

https://developers.google.com/maps/documentation/android/start


5. Add Android Support Library ( V4 )  to this project

By default, Android support library (android-support-v4.jar ) is added to this project by Eclipse IDE to the directory libs. If it is not added, we can do it manually by doing the following steps :

  • Open Project Explorer by Clicking “Window -> Show View -> Project Explorer”
  • Right click this project
  • Then from popup menu, Click “Android Tools -> Add Support Library “

6. Update the file res/layout/activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    ools:context=".MainActivity" >

    <fragment
        android:id="@+id/map"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        class="com.google.android.gms.maps.SupportMapFragment" />

</RelativeLayout>


7. Create a parser class namely MarkerJSONParser in the file src/in/wptrafficanalyzer/locationmarkermysql/MarkerJSONParser.java

package in.wptrafficanalyzer.locationmarkermysql;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class MarkerJSONParser {

    /** Receives a JSONObject and returns a list */
    public List<HashMap<String,String>> parse(JSONObject jObject){

        JSONArray jMarkers = null;
       try {
            /** Retrieves all the elements in the 'markers' array */
            jMarkers = jObject.getJSONArray("markers");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        /** Invoking getMarkers with the array of json object
        * where each json object represent a marker
        */
        return getMarkers(jMarkers);
    }

    private List<HashMap<String, String>> getMarkers(JSONArray jMarkers){
        int markersCount = jMarkers.length();
        List<HashMap<String, String>> markersList = new ArrayList<HashMap<String,String>>();
        HashMap<String, String> marker = null;

        /** Taking each marker, parses and adds to list object */
        for(int i=0; i<markersCount;i++){
            try {
                /** Call getMarker with marker JSON object to parse the marker */
                marker = getMarker((JSONObject)jMarkers.get(i));
                markersList.add(marker);
            }catch (JSONException e){
                e.printStackTrace();
            }
        }
        return markersList;
    }

    /** Parsing the Marker JSON object */
    private HashMap<String, String> getMarker(JSONObject jMarker){

        HashMap<String, String> marker = new HashMap<String, String>();
        String lat = "-NA-";
        String lng ="-NA-";

        try {
            // Extracting latitude, if available
            if(!jMarker.isNull("lat")){
                lat = jMarker.getString("lat");
            }

            // Extracting longitude, if available
            if(!jMarker.isNull("lng")){
                lng = jMarker.getString("lng");
            }

            marker.put("lat", lat);
            marker.put("lng", lng);

        } catch (JSONException e) {
            e.printStackTrace();
        }
        return marker;
    }
}

8. Update the class “MainActivity” in the file src/in/wptrafficanalyzer/locationmarkermysql/MainActivity.java

package in.wptrafficanalyzer.locationmarkermysql;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;

import org.json.JSONException;
import org.json.JSONObject;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.Menu;

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

public class MainActivity extends FragmentActivity {

    GoogleMap mGoogleMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Getting reference to SupportMapFragment
        SupportMapFragment fragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);

        // Creating GoogleMap from SupportMapFragment
        mGoogleMap = fragment.getMap();

        // Enabling MyLocation button for the Google Map
        mGoogleMap.setMyLocationEnabled(true);

        // Setting OnClickEvent listener for the GoogleMap
        mGoogleMap.setOnMapClickListener(new OnMapClickListener() {
            @Override
            public void onMapClick(LatLng latlng) {
                addMarker(latlng);
                sendToServer(latlng);
            }
        });

        // Starting locations retrieve task
        new RetrieveTask().execute();
    }

    // Adding marker on the GoogleMaps
    private void addMarker(LatLng latlng) {
        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(latlng);
        markerOptions.title(latlng.latitude + "," + latlng.longitude);
        mGoogleMap.addMarker(markerOptions);
    }

    // Invoking background thread to store the touched location in Remove MySQL server
    private void sendToServer(LatLng latlng) {
        new SaveTask().execute(latlng);
    }
    // Background thread to save the location in remove MySQL server
    private class SaveTask extends AsyncTask<LatLng, Void, Void> {
        @Override
        protected Void doInBackground(LatLng... params) {
            String lat = Double.toString(params[0].latitude);
            String lng = Double.toString(params[0].longitude);
            String strUrl = "http://192.168.1.3/location_marker_mysql/save.php";
            URL url = null;
            try {
                url = new URL(strUrl);

                HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection();
                connection.setRequestMethod("POST");
                connection.setDoOutput(true);
                OutputStreamWriter outputStreamWriter = new OutputStreamWriter(
                connection.getOutputStream());

                outputStreamWriter.write("lat=" + lat + "&lng="+lng);
                outputStreamWriter.flush();
                outputStreamWriter.close();

                InputStream iStream = connection.getInputStream();
                BufferedReader reader = new BufferedReader(new
                InputStreamReader(iStream));

                StringBuffer sb = new StringBuffer();

                String line = "";

                while( (line = reader.readLine()) != null){
                    sb.append(line);
                }

                reader.close();
                iStream.close();

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            return null;
        }
    }

    // Background task to retrieve locations from remote mysql server
    private class RetrieveTask extends AsyncTask<Void, Void, String>{

        @Override
        protected String doInBackground(Void... params) {
            String strUrl = "http://192.168.1.3/location_marker_mysql/retrieve.php";
            URL url = null;
            StringBuffer sb = new StringBuffer();
            try {
                url = new URL(strUrl);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.connect();
                InputStream iStream = connection.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(iStream));
                String line = "";
                while( (line = reader.readLine()) != null){
                    sb.append(line);
                }

                reader.close();
                iStream.close();

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return sb.toString();
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            new ParserTask().execute(result);
        }
    }

    // Background thread to parse the JSON data retrieved from MySQL server
    private class ParserTask extends AsyncTask<String, Void, List<HashMap<String, String>>>{
        @Override
        protected List<HashMap<String,String>> doInBackground(String... params) {
            MarkerJSONParser markerParser = new MarkerJSONParser();
            JSONObject json = null;
            try {
                json = new JSONObject(params[0]);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            List<HashMap<String, String>> markersList = markerParser.parse(json);
            return markersList;
        }

        @Override
        protected void onPostExecute(List<HashMap<String, String>> result) {
            for(int i=0; i<result.size();i++){
                HashMap<String, String> marker = result.get(i);
                LatLng latlng = new LatLng(Double.parseDouble(marker.get("lat")), Double.parseDouble(marker.get("lng")));
                addMarker(latlng);
            }
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}


9. Update the file AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="in.wptrafficanalyzer.locationmarkermysql"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <!-- Protect the map component of the application using application signature -->
    <permission
        android:name="in.wptrafficanalyzer.locationmarkermysql.permission.MAPS_RECEIVE"
        android:protectionLevel="signature" />

    <!-- Allows to receive map -->
    <uses-permission android:name="in.wptrafficanalyzer.locationmarkermysql.permission.MAPS_RECEIVE" />

    <!-- Used by the Google Maps Android API V2 to download map tiles from Google Maps servers -->
    <uses-permission android:name="android.permission.INTERNET" />

    <!-- Allows the Google Maps Android API V2 to cache map tile data in the device's external storage area -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <!-- Allows the Google Maps Android API V2 to use WiFi or mobile cell data (or both) to determine the device's location -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

    <!-- Allows the Google Maps Android API V2 to use the Global Positioning System (GPS)
        to determine the device's location to within a very small area -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <!-- Allows to contact Google Serves -->
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />

    <!-- Google Maps Android API V2 requires OpenGL ES version 2 -->
    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="in.wptrafficanalyzer.locationmarkermysql.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- Specifies the Android API Key, which is obtained from Google API Console -->
        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="YOUR_ANDROID_API_KEY" />

    </application>
</manifest>



10. Screenshot of the application

Showing markers from MySQL server

Figure 1 : Showing markers from MySQL server


11. Source code of the php script file used in this demo application to store and retrieve locations from MySQL server


12. Source code of this Android Application


How to hire me?

I am George Mathew, working as software architect and Android app developer at wptrafficanalyzer.in

You can hire me on hourly basis or on project basis for Android applications development.

For hiring me, please mail your requirements to info@wptrafficanalyzer.in.

My other blogs
store4js.blogspot.com


Android Knowledge Quiz

Ready to test your knowledge in Android? Take this quiz :



Tags: , ,

24 Responses to Storing Google Maps Android API V2 marker locations in MySQL

  1. Jitesh on October 23, 2013 at 11:06 pm

    Nice tutorials i like it…..Can you please do some .net webservices calling in android. thanks

  2. alex on November 8, 2013 at 5:53 am

    Hello, How I can repeat AsyncTask to update the marker created manually in the database? thank you.

    • naren on January 12, 2014 at 4:57 pm

      Really this was very helpful and thank you very much.

      I have a question that I want to change the “title” and “snippet” of the marker other than the latitude and longitude.

      any answer replay me on my email.

      • brian on March 20, 2015 at 5:17 am

        please follow the answer me,about how change the tittle.
        thanks you

  3. Xavier on February 1, 2014 at 4:36 pm

    Hello, very nice tuto but I have this error on my log cat :

    02-01 11:59:08.611: E/AndroidRuntime(13615): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myapp/com.example.myapp.HappyMap}: android.view.InflateException: Binary XML file line #11: Error inflating class fragment

    • ephrem on May 30, 2015 at 5:18 am

      AndroidRuntime(13615): java.lang.RuntimeException: Unable to start activity ComponentInfo

  4. okta on February 15, 2014 at 7:31 am

    can you help tutorial google play services import for android API 19 4.4?

  5. maya on March 7, 2014 at 4:54 pm

    hello, first thanks for your tutorial.
    it works on my device, but it only show the map with the blue dot that show my current position.
    i inserted data to database, i run the retrieve.php on browser and it works, it show data. but on my device, it didn’t show any marker at all. i change the URL also, but still didn’t show.
    can you help me? thanks before :)

  6. Muhammaad Nawaz Wali on April 7, 2014 at 9:21 pm

    nice tutorial but i want to get current location and send it to server by pressing button not by adding marker like in this good tutorials u mention please give me any idea to do this…….
    Sir really your tutorail is good for bigginer as well as for advance android programmin learning

    ………………THANKS…………………….

  7. Lee on April 30, 2014 at 7:27 pm

    How to put data(lat & lng) from android to google datastore via PHP

    Plz help me

  8. agungs on May 26, 2014 at 1:01 pm

    can you help me?? this application forse closed :(
    thanks before master :) )

  9. Ashwin on September 24, 2014 at 5:49 pm

    Hi sir,
    How are you & your family?I am ashwin. i already spoke to you regarding USB camera.but i have a small doubt in grid view.
    that is,

    i want to get the position of the item in multiple selection using grid view.
    Actually i use “getselectedItemPostion” method but its not working.

    so i need a sample app for gridview with multipleselection and also while clicking item,just display the item positon of the selected item.

    if it is possible send it to me sir.
    thank you …

  10. han on September 25, 2014 at 7:21 pm

    thats a cool coding…. this important to my study…. tq alot master….
    i try and this running well
    once more… tq alot master

  11. Ray on November 2, 2014 at 11:37 am

    Hi, this is a great tutorial and so helpful, but i would like display the name of the place instead of the lat and lng.. how do i do that help me out.. THANKS

  12. rohit jadhav on December 11, 2014 at 1:23 pm

    can you help me?? this application forse closed :(
    thanks before master :) )

  13. brian on March 20, 2015 at 5:14 am

    how could give the market a different title , I can bring it by post to the database

    • Mardoqueu Sousa on April 22, 2015 at 7:07 pm

      I was trying to do the same thing, you were able to do that?? Please, e-mail-me.

    • Mardoqueu Sousa on April 30, 2015 at 12:39 am

      I am trying to do the same, how could you give me the market a different title? Thanks for your help!

    • Mardoqueu Sousa on June 8, 2015 at 7:25 pm

      Hi! Check out this forum: stackoverflow.com/a/29725056/3304275

  14. Mardoqueu Sousa on April 21, 2015 at 1:04 am

    GREAT TUTORIAL!!! Thank you ever so much for sharing.

    I just wanted to know how to put names instead of latitude and longitude, I mean, if I want to put a new marker, should appears the name like: “Church”.

    Thank in advanced

  15. Kiran on April 21, 2015 at 5:19 pm

    Code is working fine but not storing & retrieving values to/from mySql

  16. izzy on June 6, 2015 at 7:15 pm

    Hi George, could you please help me if i want to show infowindow showing the address and phone number retrieved from mysql database?Your help are really appreciated!

  17. Ana Rotela on January 16, 2016 at 12:37 am

    I was really really helpful, Thank you very much from Paraguay.

  18. uzair on February 28, 2016 at 1:32 pm

    PLEASE CAN ANY ONE TELL ME HOW TO DISPLAY DYNAMIC LATITUDE AND LONGITUDE FROM MYSQL DATABASE TO GOOGLE MAP ON SERVER SIDE ON PHP…

Leave a Reply to Ray Cancel reply

Your email address will not be published. Required fields are marked *

Be friend at g+

Subscribe for Lastest Updates

FBFPowered by ®Google Feedburner