Java tutorial
/* * Copyright 2011 Matthew Precious * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.mattprecious.locnotifier; import android.annotation.TargetApi; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.media.RingtoneManager; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.preference.PreferenceManager; import android.support.v4.app.NotificationCompat; import android.telephony.SmsManager; import android.util.Log; /** * * @author Matthew Precious * */ public class LocationService extends Service { private SharedPreferences preferences; private NotificationManager notificationManager; private Notification runningNotification; private LocationManager locationManager; private LocationListener locationListener; private Location destination; private float radius; private Location bestLocation; private static boolean isRunning = false; @Override public void onCreate() { super.onCreate(); LocationService.isRunning = true; preferences = PreferenceManager.getDefaultSharedPreferences(this); updateRunningNotification(); int lat = preferences.getInt("dest_lat", 0); int lng = preferences.getInt("dest_lng", 0); destination = new Location(""); destination.setLatitude(lat / 1E6); destination.setLongitude(lng / 1E6); radius = preferences.getFloat("dest_radius", 0); notificationManager = (NotificationManager) getApplicationContext() .getSystemService(Context.NOTIFICATION_SERVICE); locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); locationListener = new LocationListener() { public void onLocationChanged(Location location) { Log.d(getClass().getSimpleName(), "Location changed"); updateLocation(location); } public void onStatusChanged(String provider, int status, Bundle extras) { } public void onProviderEnabled(String provider) { } public void onProviderDisabled(String provider) { } }; locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener); if (preferences.getBoolean("use_gps", false)) { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener); } Log.d(getClass().getSimpleName(), "Watching your location"); // creepy } @Override public void onDestroy() { LocationService.isRunning = false; locationManager.removeUpdates(locationListener); LocationNotifier.sUpdateStartGo(); stopForeground(true); Log.d(getClass().getSimpleName(), "No longer watching"); super.onDestroy(); } @Override public IBinder onBind(Intent arg0) { return null; } public static boolean isRunning() { return LocationService.isRunning; } private void updateLocation(Location location) { if (LocationHelper.isBetterLocation(location, bestLocation)) { bestLocation = location; float distance = location.distanceTo(destination); updateRunningNotification(distance); if (distance <= radius) { approachingDestination(); } } } private void approachingDestination() { Log.d(getClass().getSimpleName(), "Within distance to destination"); locationManager.removeUpdates(locationListener); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(), 0); String notifTitle = getString(R.string.notification_alert_title); String notifText = getString(R.string.notification_alert_text); runningNotification = null; NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this); notificationBuilder.setSmallIcon(R.drawable.notification_alert).setContentTitle(notifTitle) .setContentText(notifText).setContentIntent(contentIntent).setAutoCancel(true); String tone = preferences.getString("tone", null); Uri toneUri = (tone == null) ? RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) : Uri.parse(tone); notificationBuilder.setSound(toneUri); if (preferences.getBoolean("vibrate", false)) { int shortVib = 150; int shortPause = 150; // vibrate 3 short times long[] pattern = { 0, shortVib, shortPause, shortVib, shortPause, shortVib, }; notificationBuilder.setVibrate(pattern); } notificationBuilder.setLights(0xffff0000, 500, 500); Notification notification = notificationBuilder.getNotification(); if (preferences.getBoolean("insistent", false)) { notification.flags |= Notification.FLAG_INSISTENT; } notificationManager.notify(0, notification); // send sms if (preferences.getBoolean("sms_enabled", false)) { String number = preferences.getString("sms_contact", null); String message = preferences.getString("sms_message", null); if (number != null && message != null) { SmsManager smsManager = SmsManager.getDefault(); smsManager.sendTextMessage(number, null, message, null, null); } } stopSelf(); } private void updateRunningNotification() { updateRunningNotification(-1); } @TargetApi(16) private void updateRunningNotification(float distance) { String message; if (distance == -1) { message = getString(R.string.notification_awaiting); } else { boolean imperial = preferences.getBoolean("imperial", false); int distanceStrId = imperial ? R.string.distance_feet : R.string.distance_metres; long displayDistance = imperial ? Math.round(distance * 3.2808399) : Math.round(distance); message = getString(R.string.notification_tracking, getString(distanceStrId, displayDistance)); } String title = getString(R.string.app_name); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, LocationNotifier.class), 0); if (runningNotification == null) { runningNotification = new NotificationCompat.Builder(this).setSmallIcon(R.drawable.notification_running) .setContentTitle(title).setContentText(message).setContentIntent(contentIntent) .setOnlyAlertOnce(true).getNotification(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { if (preferences.getString("notification_priority", "low").equals("low")) { runningNotification.priority = Notification.PRIORITY_MIN; } else { runningNotification.priority = Notification.PRIORITY_HIGH; } } startForeground(R.string.app_name, runningNotification); } else { // TODO: Figure out how to do this without using the deprecated setLatestEventInfo runningNotification.setLatestEventInfo(this, title, message, contentIntent); notificationManager.notify(R.string.app_name, runningNotification); } } }