the progress circle will be used to indicate that there is work being done in the background Change-Id: Id2929f5be68fce0d223e18d8dd07babfcdb37a34 Signed-off-by: Ricky Barrette <rickbarrette@gmail.com>
259 lines
7.8 KiB
Java
259 lines
7.8 KiB
Java
/**
|
|
* @author Twenty Codes, LLC
|
|
* @author Ricky Barrette barrette
|
|
* @date Oct 6, 2010
|
|
*/
|
|
package com.TwentyCodes.android.SkyHook;
|
|
|
|
import java.util.Calendar;
|
|
|
|
import android.app.AlarmManager;
|
|
import android.app.PendingIntent;
|
|
import android.app.Service;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.location.Location;
|
|
import android.os.Handler;
|
|
import android.os.IBinder;
|
|
import android.util.Log;
|
|
|
|
import com.TwentyCodes.android.debug.Debug;
|
|
import com.TwentyCodes.android.location.GeoPointLocationListener;
|
|
import com.TwentyCodes.android.location.LocationReceiver;
|
|
import com.google.android.maps.GeoPoint;
|
|
import com.skyhookwireless.wps.RegistrationCallback;
|
|
import com.skyhookwireless.wps.WPSContinuation;
|
|
import com.skyhookwireless.wps.WPSReturnCode;
|
|
|
|
/**
|
|
* This service class will be used broadcast the users location either one time, or periodically.
|
|
* To use as a one shot location service:
|
|
* <blockquote><pre>PendingIntent pendingIntent = PendingIntent.getService(context, 0, SkyHookService.startService(context), 0);
|
|
* or
|
|
* Intent service = new Intent(context, SkyHookService.class);
|
|
* context.startService(service);<pre></bloackquote>
|
|
* To use as a recurring service:
|
|
* <blockquote>SkyHookService.startService(this, (60000 * Integer.parseInt(ringer.getString(UPDATE_INTVERVAL , "5")))).run();</bloackquote>
|
|
* @author ricky barrette
|
|
*/
|
|
public class SkyHookService extends Service implements GeoPointLocationListener, RegistrationCallback{
|
|
|
|
/**
|
|
* Used to tell the service how frequently it needs to run. This is required if you want a multishot service
|
|
*/
|
|
public static final String INTENT_EXTRA_PERIOD_BETWEEN_UPDATES = "period_beween_updates";
|
|
|
|
/**
|
|
* Used to tell the service how accurate of a location you want reported
|
|
*/
|
|
public static final String INTENT_EXTRA_REQUIRED_ACCURACY = "required_accuracy";
|
|
|
|
/**
|
|
* Used to tell the service the update action to broadcast. If this is not supplied, {@link LocationReceiver.INTENT_EXTRA_ACTION_UPDATE } will be used.
|
|
* @see LocationReceiver.INTENT_EXTRA_ACTION_UPDATE
|
|
*/
|
|
public static final String INTENT_EXTRA_ACTION_UPDATE = "action_update";
|
|
|
|
public static final String TAG = "SkyHookService";
|
|
public static final int REQUEST_CODE = 32741942;
|
|
private SkyHook mSkyhook;
|
|
protected long mPeriod = -1;
|
|
private GeoPoint mLocation;
|
|
private int mStartID;
|
|
private int mRequiredAccuracy;
|
|
private Intent mIntent;
|
|
private int mAccuracy;
|
|
|
|
/**
|
|
* broadcasts location to anything listening for updates
|
|
*
|
|
* @author ricky barrette
|
|
*/
|
|
private void braodcastLocation() {
|
|
if (mLocation != null) {
|
|
Intent locationUpdate = new Intent();
|
|
if(mIntent.getAction() != null)
|
|
locationUpdate.setAction(mIntent.getAction());
|
|
else
|
|
locationUpdate.setAction(LocationReceiver.INTENT_EXTRA_ACTION_UPDATE);
|
|
locationUpdate.putExtra(LocationReceiver.INTENT_EXTRA_LOCATION_PARCEL, convertLocation());
|
|
sendBroadcast(locationUpdate);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* converts skyhook's location object into android's location object
|
|
* @return converted location
|
|
* @author ricky barrette
|
|
*/
|
|
public Location convertLocation(){
|
|
Location location = new Location("location");
|
|
location.setLatitude(this.mLocation.getLatitudeE6() /1e6);
|
|
location.setLongitude(this.mLocation.getLongitudeE6() /1e6);
|
|
location.setAccuracy(this.mAccuracy);
|
|
return location;
|
|
}
|
|
|
|
/**
|
|
* (non-Javadoc)
|
|
* @see android.app.Service#onBind(android.content.Intent)
|
|
* @param arg0
|
|
* @return
|
|
* @author Ricky Barrette barrette
|
|
*/
|
|
@Override
|
|
public IBinder onBind(Intent arg0) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void onCreate(){
|
|
super.onCreate();
|
|
this.mSkyhook = new SkyHook(this);
|
|
this.mSkyhook.setLocationListener(this);
|
|
|
|
/*
|
|
* fail safe
|
|
* this will stop the service after the maximum running time, if location has not been reported
|
|
*/
|
|
new Handler().postDelayed(new Runnable(){
|
|
@Override
|
|
public void run(){
|
|
stopSelfResult(mStartID);
|
|
}
|
|
}, Debug.MAX_LOCATION_SERVICE_RUN_TIME);
|
|
}
|
|
|
|
/**
|
|
* aborts location services
|
|
* (non-Javadoc)
|
|
* @see android.app.Service#onDestroy()
|
|
* @author Ricky Barrette
|
|
*/
|
|
@Override
|
|
public void onDestroy(){
|
|
mSkyhook.removeUpdates();
|
|
braodcastLocation();
|
|
//ask android to restart service if mPeriod is set
|
|
if(mPeriod > -1)
|
|
registerWakeUp();
|
|
super.onDestroy();
|
|
}
|
|
|
|
/*
|
|
* I believe that this method is no longer needed as we are not supporting pre 2.1
|
|
*/
|
|
// /**
|
|
// * To keep backwards compatibility we override onStart which is the equivalent of onStartCommand in pre android 2.x
|
|
// * @author ricky barrette
|
|
// */
|
|
// @Override
|
|
// public void onStart(Intent intent, int startId) {
|
|
// Log.i(SkyHook.TAG, "onStart.Service started with start id of: " + startId);
|
|
// parseIntent(intent);
|
|
// this.mSkyhook.getUpdates();
|
|
// }
|
|
|
|
/**
|
|
* This method is called when startService is called. only used in 2.x android.
|
|
* @author ricky barrette
|
|
*/
|
|
@Override
|
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
Log.i(SkyHook.TAG , "onStartCommand.Service started with start id of: " + startId);
|
|
mStartID = startId;
|
|
parseIntent(intent);
|
|
this.mSkyhook.getUpdates();
|
|
return START_STICKY;
|
|
}
|
|
|
|
/**
|
|
* Parses the incoming intent for the service options
|
|
*
|
|
* @author ricky barrette
|
|
*/
|
|
private void parseIntent(Intent intent){
|
|
|
|
this.mIntent = intent;
|
|
|
|
if (intent.hasExtra(INTENT_EXTRA_PERIOD_BETWEEN_UPDATES))
|
|
mPeriod = intent.getLongExtra(INTENT_EXTRA_PERIOD_BETWEEN_UPDATES, 60000L);
|
|
|
|
if (intent.hasExtra(INTENT_EXTRA_REQUIRED_ACCURACY))
|
|
mRequiredAccuracy = intent.getIntExtra(INTENT_EXTRA_REQUIRED_ACCURACY, -1);
|
|
}
|
|
|
|
/**
|
|
* registers our Receiver the starts the service with the alarm manager
|
|
* @author ricky barrette
|
|
*/
|
|
private void registerWakeUp(){
|
|
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
|
am.set(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis() + this.mPeriod, PendingIntent.getService(this, REQUEST_CODE, this.mIntent, 0));
|
|
}
|
|
|
|
/**
|
|
* a convince method for getting an intent to start the service
|
|
* @param context
|
|
* @return a intent that will be used to start the service
|
|
* @author ricky barrette
|
|
*/
|
|
public static Intent getStartServiceIntent(final Context context){
|
|
return new Intent(context, SkyHookService.class);
|
|
}
|
|
|
|
/**
|
|
* a convince method for stopping the service and removing its que from the alarm manager
|
|
* @param context
|
|
* @return a runnable that will stop the service
|
|
* @author ricky barrette
|
|
*/
|
|
public static Runnable stopService(final Context context){
|
|
return new Runnable(){
|
|
@Override
|
|
public void run(){
|
|
context.stopService(new Intent(context, SkyHookService.class));
|
|
((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).cancel(PendingIntent.getService(context, REQUEST_CODE, new Intent(context, SkyHookService.class), 0));
|
|
}
|
|
};
|
|
}
|
|
|
|
@Override
|
|
public void onLocationChanged(GeoPoint point, int accuracy) {
|
|
this.mLocation = point;
|
|
this.mAccuracy = accuracy;
|
|
/*
|
|
* fail safe
|
|
* if the accuracy is greater than the minimum required accuracy
|
|
* then continue
|
|
* else stop to report location
|
|
*/
|
|
if(accuracy < (this.mRequiredAccuracy > -1 ? this.mRequiredAccuracy : Debug.MINIMUM_REQUIRED_ACCURACY) || Debug.REPORT_FIRST_LOCATION)
|
|
this.stopSelf(this.mStartID);
|
|
|
|
}
|
|
|
|
@Override
|
|
public void done() {
|
|
// unused
|
|
|
|
}
|
|
|
|
@Override
|
|
public WPSContinuation handleError(WPSReturnCode arg0) {
|
|
// unused
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void handleSuccess() {
|
|
// unused
|
|
|
|
}
|
|
|
|
@Override
|
|
public void onFirstFix(boolean isFistFix) {
|
|
// unused
|
|
|
|
}
|
|
} |