package edu.illinois.geoalarm; import java.util.Calendar; import android.app.PendingIntent; import android.app.Service; import android.app.AlarmManager; import android.content.Context; import android.content.Intent; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.util.Log; /** * This Service is launched when a trip is planned. It monitors the current time/location, and then * it signals the RouteMap service to sound the alarm. * @author GeoAlarm * */ public class AlarmService extends Service { /* Constants */ private final long minTime = 3000; // milliseconds private final long minDistance = 10; // meters private final IBinder serviceBinder = new AlarmServiceBinder(); /* Instance Variables */ private LocationManager locationManager; private AlarmManager alarmManager; private LocationListener locationListener; private Location startingLocation; private Location destinationLocation; private Location currentLocation; private boolean gpsEnabled; private boolean networkEnabled; private int startingLatitude; private int startingLongitude; private int destinationLatitude; private int destinationLongitude; private String selectedNotificationTime ; private int hourSet; private int minuteSet; private static Service mInstance; @Override public int onStartCommand(Intent intent, int flags, int startId) { startingLatitude = intent.getIntExtra("edu.illinois.geoalarm.startingStationLatitude", 0); startingLongitude = intent.getIntExtra("edu.illinois.geoalarm.startingStationLongitude", 0); destinationLatitude = intent.getIntExtra("edu.illinois.geoalarm.destinationStationLatitude", 0); destinationLongitude = intent.getIntExtra("edu.illinois.geoalarm.destinationStationLongitude", 0); selectedNotificationTime = intent.getStringExtra("edu.illinois.geoalarm.selectedNotificationTime") ; hourSet = intent.getIntExtra("edu.illinois.geoalarm.selectedNotificationHour", 0); minuteSet = intent.getIntExtra("edu.illinois.geoalarm.selectedNotificationMinute", 0); startingLocation = new Location(LocationManager.GPS_PROVIDER); startingLocation.setLatitude(((double)startingLatitude) / 1E6); startingLocation.setLongitude(((double)startingLongitude) / 1E6); destinationLocation = new Location(LocationManager.GPS_PROVIDER); destinationLocation.setLatitude(((double)destinationLatitude) / 1E6); destinationLocation.setLongitude(((double)destinationLongitude) / 1E6); Log.d("AlarmService", "Service Started"); if(!selectedNotificationTime.equals("At Time")) { setLocationListener(); checkForProviders(); registerListeners(); } else { setAlarmListener(); } return START_STICKY; } @Override public void onCreate() { super.onCreate(); Log.d("AlarmService", "Alarm Service Started"); mInstance = this; } /** * This function sets up a gps/network location event listener. When location is updated, it checks to see * if we have reached the destination */ private void setLocationListener() { locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); locationListener = new LocationListener(){ public void onLocationChanged(Location location) { currentLocation = location; checkIfAtDestination(); } public void onProviderDisabled(String provider) { } public void onProviderEnabled(String provider) { } public void onStatusChanged(String provider, int status, Bundle extras) { } }; locationManager.removeUpdates(locationListener); } /** * This method sets a system alarm that launches the RouteMap intent when we have arrived */ private void setAlarmListener() { alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(this.getApplicationContext(), RouteMap.class); intent.putExtra("edu.illinois.geoalarm.timedAlarmSignal", true); intent.putExtra("edu.illinois.geoalarm.isPlannedTrip", false); PendingIntent pendingIntent = PendingIntent.getActivity(getBaseContext(), 111, intent, PendingIntent.FLAG_CANCEL_CURRENT); Calendar c = Calendar.getInstance(); c.set(Calendar.HOUR_OF_DAY, hourSet); c.set(Calendar.MINUTE, minuteSet); alarmManager.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis() - 30000, pendingIntent); stopSelf(); } /** * This method checks to see if the current location is 10 meters or less from the destination * location */ public void checkIfAtDestination() { float distanceTo = currentLocation.distanceTo(destinationLocation); if(selectedNotificationTime.equals(TripPlanner.AT_STOP_CHOICE) && distanceTo < 50.0) { Intent wakeUpRouteMap = new Intent(getBaseContext(), RouteMap.class); wakeUpRouteMap.putExtra("edu.illinois.geoalarm.timedAlarmSignal", true); wakeUpRouteMap.putExtra("edu.illinois.geoalarm.isPlannedTrip", false); wakeUpRouteMap.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(wakeUpRouteMap); stopSelf(); } else if(selectedNotificationTime.equals(TripPlanner.STATION_BEFORE_STOP_CHOICE) && distanceTo < 150.0) { Intent wakeUpRouteMap = new Intent(getBaseContext(), RouteMap.class); wakeUpRouteMap.putExtra("edu.illinois.geoalarm.timedAlarmSignal", true); wakeUpRouteMap.putExtra("edu.illinois.geoalarm.isPlannedTrip", false); wakeUpRouteMap.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(wakeUpRouteMap); stopSelf(); } } /** * This method returns the static instance of this service * @return */ public static Service getInstance() { return mInstance; } /** * This method checks to see what location providers are currently enabled */ protected void checkForProviders() { gpsEnabled = locationManager.getProviders(true).contains(LocationManager.GPS_PROVIDER); networkEnabled = locationManager.getProviders(true).contains(LocationManager.NETWORK_PROVIDER); } /** * This method registers */ protected void registerListeners() { if(gpsEnabled==true) { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, minTime, minDistance, locationListener); } if(networkEnabled==true) { locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, minTime, minDistance, locationListener); } } /** * This method is called when the service is bound to an Activity. * In this case, we return the serviceBinder to the Activity so * that it can interact with the service. */ @Override public IBinder onBind(Intent intent) { return serviceBinder; } @Override public void onDestroy() { super.onDestroy(); if(locationManager != null && locationListener != null) { locationManager.removeUpdates(locationListener); } } /** * This inner class extends the Binder class, and allows us to return a Service * binder to an Activity. * @author deflume1 * */ public class AlarmServiceBinder extends Binder { AlarmService getService() { return AlarmService.this; } } }