/**
* The MIT License (MIT)
*
* Copyright (c) 2013 Gautam Tandon (mail@gautamtandon.me)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package gt.geolocation;
import gt.geolocation.w3c.Position;
import gt.geolocation.w3c.PositionCallback;
import gt.geolocation.w3c.PositionError;
/**
* <p>The <code>GeolocationAcquirer</code> class actually calculates the position using an implementation.
* It implements the <code>Runnable</code> interface so that the process of calculating the position could
* be run asynchronously in a separate thread.</p>
*
* <p>All implementing classes of this class must implement the <code>acquireLocation</code> method in which
* they must do all the necessary work to retrieve application's location.</p>
*/
public abstract class GeolocationAcquirer implements Runnable {
/*
* A flag that can be used to perform necessary actions required to calculate a position with
* high level of accuracy.
*/
private boolean enableHighAccuracy;
/*
* The callback to be used to provide the calculated position or an error.
*/
private PositionCallback callback;
/*
* The cached position calculated in the last call.
*/
private Position cachedPosition = null;
/**
* Must be implemented by the sub-class to actually calculate the position.
*
* @param enableHighAccuracy if set to true, the sub-class should make every effort to calculate
* the position with high level of accuracy.
* @return the current position of the application.
* @throws InterruptedException if the process is interrupted while it's still working.
*/
protected abstract Position acquireLocation(boolean enableHighAccuracy) throws InterruptedException;
/**
* Sets the "enable high accuracy" flag.
*
* @param enableHighAccuracy the "enable high accuracy" flag.
*/
public final void setEnableHighAccuracy(boolean enableHighAccuracy) {
this.enableHighAccuracy = enableHighAccuracy;
}
/**
* Sets the position callback.
*
* @param callback the PositionCallback callback.
*/
public final void setPositionCallback(PositionCallback callback) {
this.callback = callback;
}
/**
* Returns the last cached position.
*
* @return the last cached <code>Position</code>. If no cached position is available, returns null.
*/
public final Position getCachedPosition() {
return cachedPosition;
}
/**
* The <code>run()</code> method.
*/
public final void run() {
try {
Position pos = acquireLocation(enableHighAccuracy);
cachedPosition = pos;
if (pos != null) {
callback.onSuccess(pos);
} else {
callback.onFailure(new PositionError(PositionError.POSITION_UNAVAILABLE));
}
} catch (InterruptedException ie) {
cachedPosition = null;
callback.onFailure(new PositionError(PositionError.TIMEOUT));
}
}
}