133 lines
3.4 KiB
Java
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));
|
|
}
|
|
}
|
|
}
|