Adding and removing Proximity Alert in Google Map Android API V2 using LocationManager

April 14, 2013
By

Proximity alert is an alert which is triggered by Android LocationManager when the device enters a region specified by its center coordinate (latitude, longitude) and radius.



In this article, we will develop an Android application which demonstrates how to add and remove a proximity alert in Google Map Android API V2. The center of the region is specified by clicking (tap) a location in the Google Map. The radius of the region is hard-coded as 20 meters.

On clicking a location in the Google Map, proximity alert is added and on long clicking on the Google Map, the proximity alert is removed.



An extension to this application is available in the article titled “Adding and removing multiple proximity alerts in Google Maps Android API V2“, where, as the title of the article indicates, multiple proximity alerts can be defined in Google Maps Android API V2.

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 “ProximityMapV2″

New Android application project namely "ProximityMapV2"

Figure 1 : New Android application project namely "ProximityMapV2"


2. Configure the project

Configure the application project

Figure 2 : Configure the application project


3. Design application launcher icon

Design application launcher icon

Figure 3 : Design application launcher icon


4. Create a blank activity

Create a blank activity

Figure 4 : Create a blank activity


5. Enter MainActivity details

Enter MainActivity details

Figure 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. Add Google Play Services Library to this project

Link Google Play Services Library to this project

Figure 6 : 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/proximitymapv2/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/proximitymapv2/ProximityActivity.java


package in.wptrafficanalyzer.proximitymapv2;

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.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) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        boolean proximity_entering = getIntent().getBooleanExtra(LocationManager.KEY_PROXIMITY_ENTERING, true);

        if(proximity_entering){
            Toast.makeText(getBaseContext(),"Entering the region"  ,Toast.LENGTH_LONG).show();
            notificationTitle="Proximity - Entry";
            notificationContent="Entered the region";
            tickerMessage = "Entered the region";
        }else{
            Toast.makeText(getBaseContext(),"Exiting the region"  ,Toast.LENGTH_LONG).show();
            notificationTitle="Proximity - Exit";
            notificationContent="Exited the region";
            tickerMessage = "Exited the region";
        }

        Intent notificationIntent = new Intent(getApplicationContext(),NotificationView.class);
        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);

        /** 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/proximitymapv2/MainActivity.java


package in.wptrafficanalyzer.proximitymapv2;

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;

    @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 stored latitude if exists else return 0
            String lat = sharedPreferences.getString("lat", "0");

            // Getting stored longitude if exists else return 0
            String lng = sharedPreferences.getString("lng", "0");

            // Getting stored zoom level if exists else return 0
            String zoom = sharedPreferences.getString("zoom", "0");

            // If coordinates are stored earlier
            if(!lat.equals("0")){

                // Drawing circle on the map
                drawCircle(new LatLng(Double.parseDouble(lat), Double.parseDouble(lng)));

                // Drawing marker on the map
                drawMarker(new LatLng(Double.parseDouble(lat), Double.parseDouble(lng)));

                // Moving CameraPosition to previously clicked position
                googleMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(Double.parseDouble(lat), Double.parseDouble(lng))));

                // Setting the zoom level in the map
                googleMap.animateCamera(CameraUpdateFactory.zoomTo(Float.parseFloat(zoom)));

            }

            googleMap.setOnMapClickListener(new OnMapClickListener() {

                @Override
                public void onMapClick(LatLng point) {

                    // Removes the existing marker from the Google Map
                    googleMap.clear();

                    // 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");

                    // 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 of the current location to the shared preferences */
                    editor.putString("lat", Double.toString(point.latitude));

                    /** Storing the longitude of the current location to the shared preferences */
                    editor.putString("lng", Double.toString(point.longitude));

                    /** 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 drawMarker(LatLng point){
        // Creating an instance of MarkerOptions
        MarkerOptions markerOptions = new MarkerOptions();

        // Setting latitude and longitude for the marker
        markerOptions.position(point);

        // Adding marker on the Google Map
        googleMap.addMarker(markerOptions);
    }

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

    }

    @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.proximitymapv2"
    android:versionCode="1"
    android:versionName="1.0" >

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

    <permission
        android:name="in.wptrafficanalyzer.proximitymapv2.permission.MAPS_RECEIVE"
        android:protectionLevel="signature"/>

    <uses-permission android:name="in.wptrafficanalyzer.proximitymapv2.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.proximitymapv2.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 60 with the API Key obtained in Step 8.


16. Screenshot of the application

Proximity Alerts in Notification List

Figure 7 : Proximity Alerts in Notification List

Entering into the Proximity regionq

Figure 8 : Entering into the Proximity region

Proximity Alert is removed

Figure 9 : Proximity Alert is removed


17. Download the source code


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

22 Responses to Adding and removing Proximity Alert in Google Map Android API V2 using LocationManager

  1. Sultan Ishmuradov on April 21, 2013 at 6:06 pm

    first i need to thank you for your great work ..but how we can add multiple markers and save it in shared preference can you plz help me

      • Sultan Ishmuradov on April 29, 2013 at 10:38 pm

        Thanks George for your quick feedback.As i see you are prof in this work.Cuz i cant find better tutorials about Google Map V2 than yours.Actually i want to do something like this after long click on screen user saves his message with proximity alert then if user enters that area app must show his own message to him which he saved in shared preferences.And it must be enable to add multiple alerts on map.This is my project which i get from university and its too important for me if u can help me with this ill be appreciate.or can we talk from gmail or other social sites so i can explain more.

  2. Mot on April 29, 2013 at 12:31 pm

    how to change mylocation is blue arrow

  3. akshay koul on May 24, 2013 at 12:13 am

    hello i was trying to use this code but i am getting an unusual error
    i.e.
    the eclipse ide can not find the following import
    import com.google.android.gms.maps.model.CircleOptions

    but it can recognize the import
    import com.google.android.gms.maps.model.LatLng etc.

  4. Christopher J on August 25, 2013 at 3:45 pm

    When I download the work file import in my ADT and tested in my device it worked perfectly. But, when i copy pasted everything (same package name) the app crashes.. why it happens to me?? :( :(

  5. Luian on October 4, 2013 at 3:22 am

    Good day.
    I am a Brazilian student and I have some questions to make my final paper in college. Need to register some points (to display with local marks) in a local database (you posted a similar example), then I would like the user could define a radius 1 mile (for example), then the application queries the database and displays the map only marks that are within 1 mile radius.

    How to do it?

    PS: I do not speak English, I used google translator

  6. Deep on March 4, 2014 at 10:54 am

    Thanks a lot .. your code solves my problem ..
    but i have query on Radius. i don’t know is there any restriction on Radius for addProximityAlert ?.. like minimum or maximum.

  7. Amir on September 18, 2014 at 2:34 pm

    when i add locations in proximity it didn’t work.. plz tel me proximity still working when i close my app or when i enter region it show notification or when device near the region.

  8. mehtab ahmad on November 12, 2014 at 1:45 am

    i want to get an approximity alert when some other user enter or exit the region that i have specified. but i don’t know how to do this.will it be better to use mock location or i need to do some thing else???? i have the locations of other peoples on server.. plz help me i will be very greatful to you.

  9. jefer on November 22, 2014 at 4:32 am

    Gracias, Desde Colombia.. muy agradecido Gracias..
    muchos de sus tutoriales lo he seguido.. me parece muy bien lo que hace.. gracias

  10. RUPSI AGRAWAL on December 16, 2014 at 5:05 pm

    I want to create a app like this :first register the location and save the lat long in shared preference then check location when device enter in this location if device in geofence area then given button disable otherwise enable and give the attendance.

  11. Mohammed on March 11, 2015 at 4:27 am

    Finally… :’( brother you saved me!!! Long Live God bless you!! Thanx forever…

  12. kokila on June 10, 2015 at 5:57 pm

    hi ur code worked perfectly to me.But intent was not able to fire when the proximity is entering or exiting.please kindly help me

  13. Lohithananda on July 10, 2015 at 12:33 pm

    I want to create a same app but using polygons,please help me…
    Regards

  14. Heman on July 16, 2015 at 5:13 pm

    Process: in.wptrafficanalyzer.proximitymapv2, PID: 12865
    java.lang.RuntimeException: Unable to start activity ComponentInfo{in.wptrafficanalyzer.proximitymapv2/in.wptrafficanalyzer.proximitymapv2.MainActivity}: android.view.InflateException: Binary XML file line #7: Error inflating class fragment

    i am getting this error while running it on a android device please help

  15. Heman on July 16, 2015 at 5:30 pm

    how can we add sound and vibration in it

  16. Sathish on August 27, 2015 at 12:59 am

    its works excellent,,, but only thing is last added proximity only working. How to avoid overriding the existing alerts!!!!!!!!!! Pls help… Expecting reply from you….

  17. Omagano on March 6, 2016 at 12:53 am

    I cant run the code what’s up.I’m using the latest version please help

  18. Mayur Thorat on April 27, 2016 at 5:03 pm

    hi ur code worked perfectly to me.But intent was not able to fire when the proximity is entering or exiting.please kindly help me

  19. prashant on May 9, 2016 at 2:12 pm

    If this codes causes application crashes, simply replace activity_main.xml with:

  20. jesuraj on July 13, 2016 at 1:08 pm

    I have an doubt. when i add one more proximity alert it will over ride first point .how to solve this issue.I am using android studio .So In pending intent ,Intent.FLAG_NEW_TASK shows error itis now depricated.any other value linke PENDINGINTENT_FLAG_UPDATE_CURRENT or something needed.solve this issue

Leave a Reply

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

Be friend at g+

Subscribe for Lastest Updates

FBFPowered by ®Google Feedburner