The following code shows how to Create region monitor service.
Code revised from
Android Recipes:A Problem-Solution Approach
http://www.apress.com/9781430234135
ISBN13: 978-1-4302-3413-5
Register service in manifest xml file
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.androidrecipes.regionmonitor" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.androidrecipes.regionmonitor.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> <service android:name="com.androidrecipes.regionmonitor.RegionMonitorService" /> </application> </manifest>
Main xml file
<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/status" android:layout_width="match_parent" android:layout_height="wrap_content" /> <SeekBar android:id="@+id/radius" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="1000"/> <TextView android:id="@+id/radius_text" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Set Geofence at My Location" android:onClick="onSetGeofenceClick" /> <View android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Start Monitoring" android:onClick="onStartMonitorClick" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Stop Monitoring" android:onClick="onStopMonitorClick" /> </LinearLayout>
Main activity Java code
import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesClient; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.location.Geofence; import com.google.android.gms.location.LocationClient; import com.google.android.gms.location.LocationStatusCodes; /* www .j a v a2 s . c o m*/ import android.app.Activity; import android.app.PendingIntent; import android.content.Intent; import android.location.Location; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; public class MainActivity extends Activity implements OnSeekBarChangeListener, GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, LocationClient.OnAddGeofencesResultListener, LocationClient.OnRemoveGeofencesResultListener { private static final String TAG = "RegionMonitorActivity"; private static final String FENCE_ID = "com.androidrecipes.FENCE"; private LocationClient mLocationClient; private SeekBar mRadiusSlider; private TextView mStatusText, mRadiusText; private Geofence mCurrentFence; private Intent mServiceIntent; private PendingIntent mCallbackIntent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mStatusText = (TextView) findViewById(R.id.status); mRadiusText = (TextView) findViewById(R.id.radius_text); mRadiusSlider = (SeekBar) findViewById(R.id.radius); mRadiusSlider.setOnSeekBarChangeListener(this); updateRadiusDisplay(); switch (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this)) { case ConnectionResult.SUCCESS: //Do nothing, move on break; case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED: Toast.makeText(this, "Geofencing service requires an update, please open Google Play.", Toast.LENGTH_SHORT).show(); finish(); return; default: Toast.makeText(this, "Geofencing service is not available on this device.", Toast.LENGTH_SHORT).show(); finish(); return; } //Create a client for Google Services mLocationClient = new LocationClient(this, this, this); //Create an Intent to trigger our service mServiceIntent = new Intent(this, RegionMonitorService.class); //Create a PendingIntent for Google Services to use with callbacks mCallbackIntent = PendingIntent.getService(this, 0, mServiceIntent, PendingIntent.FLAG_UPDATE_CURRENT); } @Override protected void onResume() { super.onResume(); //Connect to all services if (!mLocationClient.isConnected() && !mLocationClient.isConnecting()) { mLocationClient.connect(); } } @Override protected void onPause() { super.onPause(); //Disconnect when not in the foreground mLocationClient.disconnect(); } public void onSetGeofenceClick(View v) { //Obtain the last location from services and radius // from the UI Location current = mLocationClient.getLastLocation(); int radius = mRadiusSlider.getProgress(); //Create a new Geofence using the Builder Geofence.Builder builder = new Geofence.Builder(); mCurrentFence = builder //Unique to this geofence .setRequestId(FENCE_ID) //Size and location .setCircularRegion( current.getLatitude(), current.getLongitude(), radius) //Events both in and out of the fence .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT) //Keep alive .setExpirationDuration(Geofence.NEVER_EXPIRE) .build(); mStatusText.setText(String.format("Geofence set at %.3f, %.3f", current.getLatitude(), current.getLongitude()) ); } public void onStartMonitorClick(View v) { if (mCurrentFence == null) { Toast.makeText(this, "Geofence Not Yet Set", Toast.LENGTH_SHORT).show(); return; } //Add the fence to start tracking, the PendingIntent will // be triggered with new updates ArrayList<Geofence> geofences = new ArrayList<Geofence>(); geofences.add(mCurrentFence); mLocationClient.addGeofences(geofences, mCallbackIntent, this); } public void onStopMonitorClick(View v) { //Remove to stop tracking mLocationClient.removeGeofences(mCallbackIntent, this); } /** SeekBar Callbacks */ @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { updateRadiusDisplay(); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } private void updateRadiusDisplay() { mRadiusText.setText(mRadiusSlider.getProgress() + " meters"); } /** Google Services Connection Callbacks */ @Override public void onConnected(Bundle connectionHint) { Log.v(TAG, "Google Services Connected"); } @Override public void onDisconnected() { Log.w(TAG, "Google Services Disconnected"); } @Override public void onConnectionFailed(ConnectionResult result) { Log.w(TAG, "Google Services Connection Failure"); } /** LocationClient Callbacks */ /* * Called when the asynchronous geofence add is complete. * When this happens we start our monitoring service. */ @Override public void onAddGeofencesResult(int statusCode, String[] geofenceRequestIds) { if (statusCode == LocationStatusCodes.SUCCESS) { Toast.makeText(this, "Geofence Added Successfully", Toast.LENGTH_SHORT).show(); } Intent startIntent = new Intent(mServiceIntent); startIntent.setAction(RegionMonitorService.ACTION_INIT); startService(mServiceIntent); } /* * Called when the asynchronous geofence remove is complete. * The version called depends on whether you requested the * removal via PendingIntent or request Id. * When this happens we stop our monitoring service. */ @Override public void onRemoveGeofencesByPendingIntentResult( int statusCode, PendingIntent pendingIntent) { if (statusCode == LocationStatusCodes.SUCCESS) { Toast.makeText(this, "Geofence Removed Successfully", Toast.LENGTH_SHORT).show(); } stopService(mServiceIntent); } @Override public void onRemoveGeofencesByRequestIdsResult( int statusCode, String[] geofenceRequestIds) { if (statusCode == LocationStatusCodes.SUCCESS) { Toast.makeText(this, "Geofence Removed Successfully", Toast.LENGTH_SHORT).show(); } stopService(mServiceIntent); } }
Service Java code
package com.java2s.myapplication3.app; //from ww w . j ava 2 s . co m import com.google.android.gms.location.Geofence; import com.google.android.gms.location.LocationClient; import android.app.Notification; import android.app.NotificationManager; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class MyService extends Service { private static final String TAG = "RegionMonitorService"; private static final int NOTE_ID = 100; //Unique action to identify start requests vs. events public static final String ACTION_INIT = "com.androidrecipes.regionmonitor.ACTION_INIT"; private NotificationManager mNoteManager; @Override public void onCreate() { super.onCreate(); mNoteManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); //Post a system notification when the service starts NotificationCompat.Builder builder = new NotificationCompat.Builder(this); builder.setSmallIcon(R.drawable.ic_launcher); builder.setContentTitle("Geofence Service"); builder.setContentText("Waiting for transition..."); builder.setOngoing(true); Notification note = builder.build(); mNoteManager.notify(NOTE_ID, note); } @Override public int onStartCommand(Intent intent, int flags, int startId) { //Nothing to do yet, just starting the service if (ACTION_INIT.equals(intent.getAction())) { //We don't care if this service dies unexpectedly return START_NOT_STICKY; } if (LocationClient.hasError(intent)) { //Log any errors Log.w(TAG, "Error monitoring region: " + LocationClient.getErrorCode(intent)); } else { //Update the ongoing notification from the new event NotificationCompat.Builder builder = new NotificationCompat.Builder(this); builder.setSmallIcon(R.drawable.ic_launcher); builder.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_LIGHTS); builder.setOngoing(true); int transitionType = LocationClient.getGeofenceTransition(intent); //Check whether we entered or exited the region if (transitionType == Geofence.GEOFENCE_TRANSITION_ENTER) { builder.setContentTitle("Geofence Transition"); builder.setContentText("Entered your Geofence"); } else if (transitionType == Geofence.GEOFENCE_TRANSITION_EXIT) { builder.setContentTitle("Geofence Transition"); builder.setContentText("Exited your Geofence"); } Notification note = builder.build(); mNoteManager.notify(NOTE_ID, note); } //We don't care if this service dies unexpectedly return START_NOT_STICKY; } @Override public void onDestroy() { super.onDestroy(); //When the service dies, cancel our ongoing notification mNoteManager.cancel(NOTE_ID); } /* We are not binding to this service */ @Override public IBinder onBind(Intent intent) { return null; } }