UnifiedNlp/src/org/microg/nlp/location/BackendHelper.java
2014-03-05 21:31:46 +01:00

133 lines
3.4 KiB
Java

package org.microg.nlp.location;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.location.Location;
import android.os.*;
import android.util.Log;
import com.android.location.provider.LocationProviderBase;
import org.microg.nlp.api.LocationBackend;
import org.microg.nlp.api.LocationCallback;
public class BackendHelper {
private static final String TAG = BackendHelper.class.getName();
private final Context context;
private final LocationProvider provider;
private final Intent serviceIntent;
private final Connection connection = new Connection();
private final Callback callback = new Callback();
private LocationBackend backend;
private boolean updateWaiting;
private Location lastLocation;
private boolean bound;
public BackendHelper(Context context, LocationProvider provider, Intent serviceIntent) {
this.context = context;
this.provider = provider;
this.serviceIntent = serviceIntent;
}
public boolean bind() {
if (!bound) {
try {
context.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE);
} catch (Exception e) {
Log.w(TAG, e);
return false;
}
}
return true;
}
public void unbind() {
if (bound) {
try {
backend.close();
context.unbindService(connection);
} catch (Exception e) {
Log.w(TAG, e);
}
}
}
public Location getLastLocation() {
return lastLocation;
}
public Location update() {
if (backend == null) {
Log.d(TAG, "Not (yet) bound.");
updateWaiting = true;
} else {
updateWaiting = false;
try {
setLastLocation(backend.update());
provider.reportLocation(lastLocation);
} catch (RemoteException e) {
Log.w(TAG, e);
unbind();
}
}
return lastLocation;
}
private Location setLastLocation(Location location) {
if (location == null) {
return lastLocation;
}
if (location.getExtras() == null) {
location.setExtras(new Bundle());
}
location.getExtras().putString("SERVICE_BACKEND_PROVIDER", location.getProvider());
location.getExtras().putString("SERVICE_BACKEND_PACKAGE", serviceIntent.getPackage());
location.setProvider("network");
if (!location.hasAccuracy()) {
location.setAccuracy(50000);
}
if (location.getTime() <= 0) {
location.setTime(System.currentTimeMillis());
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
if (location.getElapsedRealtimeNanos() <= 0) {
location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
}
}
location.getExtras().putParcelable(LocationProviderBase.EXTRA_NO_GPS_LOCATION, new Location(location));
lastLocation = location;
Log.v(TAG, "location=" + lastLocation);
return lastLocation;
}
private class Connection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
bound = true;
backend = LocationBackend.Stub.asInterface(service);
try {
backend.open(callback);
if (updateWaiting) {
update();
}
} catch (RemoteException e) {
Log.w(TAG, e);
unbind();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
backend = null;
bound = false;
}
}
private class Callback extends LocationCallback.Stub {
@Override
public void report(Location location) throws RemoteException {
provider.reportLocation(setLastLocation(location));
}
}
}