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
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

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