In this article, we will develop an Android application which demonstrates how to add multiple proximity alerts in Google Maps Android API V2.
We will make use the Android API class “LocationManager” to add and remove the proximity alerts and SharedPreferences to persist the markers on the Google Maps while restarting the application.
In order to define a proximity area, simply tap a location on the Google Maps. Then the area circumventing with a radius of 20 meters will be the proximity area for the tapped location. Once the Android device enters the proximity region, a notification alert will be generated along with system’s default notification ring tone and vibration.
This article is an extension to the article titled “Adding and removing Proximity Alert in Google Map Android API V2 using LocationManager” where we have discussed how to add single proximity alert to Google Maps.
This application is developed in Eclipse (4.2.1) with ADT plugin (21.1.0) and Android SDK (21.1.0) and tested in a real Android device (Android 2.3.6 - GingerBread).
1. Create a new Android application project namely “MultipleProximityMapV2″
2. Configure the project
3. Design application launcher icon
4. Create a blank activity
5. Enter MainActivity details
6. Download and configure Google Play Services Library in Eclipse
Google Map for Android is now integrated with Google Play Services. So we need to set up Google Play Service Library for developing Google Map application in Android.
Please follow the given below link to setup Google Play Service library in Eclipse.
http://developer.android.com/google/play-services/setup.html
7. Link Google Play Services Library to this project
8. 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
9. Add Android Support library 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 “
10. Update the layout 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" tools:context=".MainActivity" > <fragment android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>
11. Create a layout file res/layout/notification.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/tv_notification" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout>
12. Create the class “NotificationView” in the file src/in/wptrafficanalyzer/multipleproximitymapv2/NotificationView.java
package in.wptrafficanalyzer.proximitymapv2; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class NotificationView extends Activity { public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.notification); TextView tv = (TextView) findViewById(R.id.tv_notification); Bundle data = getIntent().getExtras(); tv.setText(data.getString("content")); } }
13. Create the class “ProximityActivity” in the file src/in/wptrafficanalyzer/multipleproximitymapv2/ProximityActivity.java
package in.wptrafficanalyzer.multipleproximitymapv2; import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.location.LocationManager; import android.media.RingtoneManager; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.NotificationCompat; import android.widget.Toast; public class ProximityActivity extends Activity { String notificationTitle; String notificationContent; String tickerMessage; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); boolean proximity_entering = getIntent().getBooleanExtra(LocationManager.KEY_PROXIMITY_ENTERING, true); double lat = getIntent().getDoubleExtra("lat", 0); double lng = getIntent().getDoubleExtra("lng", 0); String strLocation = Double.toString(lat)+","+Double.toString(lng); if(proximity_entering){ Toast.makeText(getBaseContext(),"Entering the region" ,Toast.LENGTH_LONG).show(); notificationTitle = "Proximity - Entry"; notificationContent = "Entered the region:" + strLocation; tickerMessage = "Entered the region:" + strLocation; }else{ Toast.makeText(getBaseContext(),"Exiting the region" ,Toast.LENGTH_LONG).show(); notificationTitle = "Proximity - Exit"; notificationContent = "Exited the region:" + strLocation; tickerMessage = "Exited the region:" + strLocation; } Intent notificationIntent = new Intent(getApplicationContext(),NotificationView.class); /** Adding content to the notificationIntent, which will be displayed on * viewing the notification */ notificationIntent.putExtra("content", notificationContent ); /** This is needed to make this intent different from its previous intents */ notificationIntent.setData(Uri.parse("tel:/"+ (int)System.currentTimeMillis())); /** Creating different tasks for each notification. See the flag Intent.FLAG_ACTIVITY_NEW_TASK */ PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK); /** Getting the System service NotificationManager */ NotificationManager nManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE); /** Configuring notification builder to create a notification */ NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getApplicationContext()) .setWhen(System.currentTimeMillis()) .setContentText(notificationContent) .setContentTitle(notificationTitle) .setSmallIcon(R.drawable.ic_launcher) .setAutoCancel(true) .setTicker(tickerMessage) .setContentIntent(pendingIntent) .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)); /** Creating a notification from the notification builder */ Notification notification = notificationBuilder.build(); /** Sending the notification to system. * The first argument ensures that each notification is having a unique id * If two notifications share same notification id, then the last notification replaces the first notification * */ nManager.notify((int)System.currentTimeMillis(), notification); /** Finishes the execution of this activity */ finish(); } }
14. Update the class “MainActivity” in the file src/in/wptrafficanalyzer/multipleproximitymapv2/MainActivity.java
package in.wptrafficanalyzer.multipleproximitymapv2; import android.app.Dialog; import android.app.PendingIntent; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Color; import android.location.LocationManager; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.view.Menu; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.GoogleMap.OnMapClickListener; import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.CircleOptions; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MarkerOptions; public class MainActivity extends FragmentActivity { GoogleMap googleMap; LocationManager locationManager; PendingIntent pendingIntent; SharedPreferences sharedPreferences; int locationCount = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Getting Google Play availability status int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getBaseContext()); // Showing status if(status!=ConnectionResult.SUCCESS){ // Google Play Services are not available int requestCode = 10; Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status, this, requestCode); dialog.show(); }else { // Google Play Services are available // Getting reference to the SupportMapFragment of activity_main.xml SupportMapFragment fm = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); // Getting GoogleMap object from the fragment googleMap = fm.getMap(); // Enabling MyLocation Layer of Google Map googleMap.setMyLocationEnabled(true); // Getting LocationManager object from System Service LOCATION_SERVICE locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); // Opening the sharedPreferences object sharedPreferences = getSharedPreferences("location", 0); // Getting number of locations already stored locationCount = sharedPreferences.getInt("locationCount", 0); // Getting stored zoom level if exists else return 0 String zoom = sharedPreferences.getString("zoom", "0"); // If locations are already saved if(locationCount!=0){ String lat = ""; String lng = ""; // Iterating through all the locations stored for(int i=0;i<locationCount;i++){ // Getting the latitude of the i-th location lat = sharedPreferences.getString("lat"+i,"0"); // Getting the longitude of the i-th location lng = sharedPreferences.getString("lng"+i,"0"); // Drawing marker on the map drawMarker(new LatLng(Double.parseDouble(lat), Double.parseDouble(lng))); // Drawing circle on the map drawCircle(new LatLng(Double.parseDouble(lat), Double.parseDouble(lng))); } // Moving CameraPosition to last clicked position googleMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(Double.parseDouble(lat), Double.parseDouble(lng)))); // Setting the zoom level in the map on last position is clicked googleMap.animateCamera(CameraUpdateFactory.zoomTo(Float.parseFloat(zoom))); } googleMap.setOnMapClickListener(new OnMapClickListener() { @Override public void onMapClick(LatLng point) { // Incrementing location count locationCount++; // Drawing marker on the map drawMarker(point); // Drawing circle on the map drawCircle(point); // This intent will call the activity ProximityActivity Intent proximityIntent = new Intent("in.wptrafficanalyzer.activity.proximity"); // Passing latitude to the PendingActivity proximityIntent.putExtra("lat",point.latitude); // Passing longitude to the PendingActivity proximityIntent.putExtra("lng", point.longitude); // Creating a pending intent which will be invoked by LocationManager when the specified region is // entered or exited pendingIntent = PendingIntent.getActivity(getBaseContext(), 0, proximityIntent,Intent.FLAG_ACTIVITY_NEW_TASK); // Setting proximity alert // The pending intent will be invoked when the device enters or exits the region 20 meters // away from the marked point // The -1 indicates that, the monitor will not be expired locationManager.addProximityAlert(point.latitude, point.longitude, 20, -1, pendingIntent); /** Opening the editor object to write data to sharedPreferences */ SharedPreferences.Editor editor = sharedPreferences.edit(); // Storing the latitude for the i-th location editor.putString("lat"+ Integer.toString((locationCount-1)), Double.toString(point.latitude)); // Storing the longitude for the i-th location editor.putString("lng"+ Integer.toString((locationCount-1)), Double.toString(point.longitude)); // Storing the count of locations or marker count editor.putInt("locationCount", locationCount); /** Storing the zoom level to the shared preferences */ editor.putString("zoom", Float.toString(googleMap.getCameraPosition().zoom)); /** Saving the values stored in the shared preferences */ editor.commit(); Toast.makeText(getBaseContext(), "Proximity Alert is added", Toast.LENGTH_SHORT).show(); } }); googleMap.setOnMapLongClickListener(new OnMapLongClickListener() { @Override public void onMapLongClick(LatLng point) { Intent proximityIntent = new Intent("in.wptrafficanalyzer.activity.proximity"); pendingIntent = PendingIntent.getActivity(getBaseContext(), 0, proximityIntent,Intent.FLAG_ACTIVITY_NEW_TASK); // Removing the proximity alert locationManager.removeProximityAlert(pendingIntent); // Removing the marker and circle from the Google Map googleMap.clear(); // Opening the editor object to delete data from sharedPreferences SharedPreferences.Editor editor = sharedPreferences.edit(); // Clearing the editor editor.clear(); // Committing the changes editor.commit(); Toast.makeText(getBaseContext(), "Proximity Alert is removed", Toast.LENGTH_LONG).show(); } }); } } private void drawCircle(LatLng point){ // Instantiating CircleOptions to draw a circle around the marker CircleOptions circleOptions = new CircleOptions(); // Specifying the center of the circle circleOptions.center(point); // Radius of the circle circleOptions.radius(20); // Border color of the circle circleOptions.strokeColor(Color.BLACK); // Fill color of the circle circleOptions.fillColor(0x30ff0000); // Border width of the circle circleOptions.strokeWidth(2); // Adding the circle to the GoogleMap googleMap.addCircle(circleOptions); } private void drawMarker(LatLng point){ // Creating an instance of MarkerOptions MarkerOptions markerOptions = new MarkerOptions(); // Setting latitude and longitude for the marker markerOptions.position(point); // Adding InfoWindow title markerOptions.title("Location Coordinates"); // Adding InfoWindow contents markerOptions.snippet(Double.toString(point.latitude) + "," + Double.toString(point.longitude)); // Adding marker on the Google Map googleMap.addMarker(markerOptions); } @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; } }
15. 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.multipleproximitymapv2" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <permission android:name="in.wptrafficanalyzer.multipleproximitymapv2.permission.MAPS_RECEIVE" android:protectionLevel="signature"/> <uses-permission android:name="in.wptrafficanalyzer.multipleproximitymapv2.permission.MAPS_RECEIVE"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <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.multipleproximitymapv2.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> <activity android:name=".ProximityActivity" android:label="@string/app_name" > <intent-filter > <action android:name="in.wptrafficanalyzer.activity.proximity"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> <activity android:name=".NotificationView" android:label="@string/app_name" > <intent-filter > <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="YOUR_ANDROID_API_KEY"/> </application> </manifest>
Note : Replace “YOUR_ANDROID_API_KEY” at line 61 with the api key obtained in step 8.
16. Screenshots of the application
17. Download the source code


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
Hi, thanks a lot for your tutorials they are very helpful.
I was wondering if you can make a tutorial related to indoor map feature for Google Maps Android API V2
Thank you
Yeah… Thanks a lot, George!
Hi there!
do you have or know any tutorial about indoor map??
Hi,
This post is very useful,but i have a query .if i am creating multiple alerts and i want remove a particular alert from the alerts..how can i do it??
Do i have to use diff unique id in pending intent?
Hi
Thank you very much for the tutorial it’s very useful i’m having a problem when running the example they telling me that the projet has stopped unexpectedly i follow all the step.
thank’s for you answer
Hey mate …there is one problem with your code ….when i add multiple proximity alerts only the last one works
Nice tutorial. But when working in 2g/3g network alarm fires only after a long delay(almost 5-10 mins). Works great in wifi.
A very good example, but not working. Just the last point touched work. How to fix that? Can you help us? 2 weeks stuck!
Hello Mathew, really good tutorial. One problem though, i followed your tutorial, but it only add one proximity alert, and when i try adding the second one, it overrides the first one. where could i be wrong ? Thanks
Hey George Mathew,
A very good example. I juz wanna ask u something. how u added that markers which changes on move and another marker on stationary. Advance thanks
thanks for this nice tutorial ..
Can you tell me how to store and retrive lat and long value in sqlite instead of shared preference in this example..thanks in advance
You saved my life! Tks so much friend!
hi, This code is working fine below android api level 17. But not working
above 17. Please give me the solution for this.
This code works fine but I need to add another metadata tag for Google Play Service version and value.
Hi Sir,
Really nice tutorial,But i have one doubt,when i close my application,i am getting proximity alert notification,how to remove this one while close the application.(my mail id jeeva2k10@gmail.com)
Kindly do the need full.
Thanks
when i add multiple proximity alerts only the last one works
Pls help me… Expecting reply from u..
The last added proximity only works… please why? and solution?
Please let me know how to avoid only last added alert work
Sir, how could we run a voice message or a record when we entered the region?
Sir, it’s app can’t run on android OS 6.0 ( Marsmellow ) or some code must have to changes? Because i already add marker and my location in the red circle but got nothing notification or like else.