mirror of
https://github.com/TeamVanced/VancedMicroG
synced 2024-11-19 02:29:25 +01:00
WIP: Location API
This commit is contained in:
parent
8b42163800
commit
d2fb7d569b
@ -1,4 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.google.android.gms">
|
||||
<uses-sdk minSdkVersion="5" />
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.gms">
|
||||
|
||||
<uses-sdk android:minSdkVersion="5" />
|
||||
</manifest>
|
||||
|
@ -0,0 +1,40 @@
|
||||
package com.google.android.gms.common;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
@Deprecated
|
||||
public interface GooglePlayServicesClient {
|
||||
void connect();
|
||||
|
||||
void disconnect();
|
||||
|
||||
boolean isConnected();
|
||||
|
||||
boolean isConnecting();
|
||||
|
||||
void registerConnectionCallbacks(ConnectionCallbacks listener);
|
||||
|
||||
boolean isConnectionCallbacksRegistered(ConnectionCallbacks listener);
|
||||
|
||||
void unregisterConnectionCallbacks(ConnectionCallbacks listener);
|
||||
|
||||
void registerConnectionFailedListener(OnConnectionFailedListener listener);
|
||||
|
||||
boolean isConnectionFailedListenerRegistered(OnConnectionFailedListener listener);
|
||||
|
||||
void unregisterConnectionFailedListener(OnConnectionFailedListener listener);
|
||||
|
||||
@Deprecated
|
||||
public interface OnConnectionFailedListener {
|
||||
|
||||
void onConnectionFailed(ConnectionResult result);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public interface ConnectionCallbacks {
|
||||
|
||||
void onConnected(Bundle connectionHint);
|
||||
|
||||
void onDisconnected();
|
||||
}
|
||||
}
|
@ -49,7 +49,8 @@ public class GooglePlayServicesUtil {
|
||||
}
|
||||
|
||||
public static int isGooglePlayServicesAvailable(Context context) {
|
||||
return 0; // TODO
|
||||
// As we can't know right now if the later desired feature is available, we just pretend it to be.
|
||||
return ConnectionResult.SUCCESS;
|
||||
}
|
||||
|
||||
public static boolean isGoogleSignedUid(PackageManager packageManager, int uid) {
|
||||
|
@ -1,5 +1,8 @@
|
||||
package com.google.android.gms.common.api;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
|
||||
/**
|
||||
* Describes a section of the Google Play Services API that should be made available. Instances of
|
||||
* this should be passed into {@link GoogleApiClient.Builder#addApi(Api)} to enable the appropriate
|
||||
@ -14,6 +17,16 @@ package com.google.android.gms.common.api;
|
||||
*/
|
||||
public final class Api<O extends Api.ApiOptions> {
|
||||
|
||||
private final Builder<O> builder;
|
||||
|
||||
public Api(Builder<O> builder) {
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
public Builder<O> getBuilder() {
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base interface for API options. These are used to configure specific parameters for
|
||||
* individual API surfaces. The default implementation has no parameters.
|
||||
@ -34,7 +47,7 @@ public final class Api<O extends Api.ApiOptions> {
|
||||
/**
|
||||
* {@link ApiOptions} implementation for {@link Api}s that do not take any options.
|
||||
*/
|
||||
public class NoOptions implements NotRequiredOptions {
|
||||
public final class NoOptions implements NotRequiredOptions {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -43,4 +56,16 @@ public final class Api<O extends Api.ApiOptions> {
|
||||
public interface Optional extends HasOptions, NotRequiredOptions {
|
||||
}
|
||||
}
|
||||
|
||||
public interface Connection {
|
||||
public void connect();
|
||||
public void disconnect();
|
||||
public boolean isConnected();
|
||||
}
|
||||
|
||||
public interface Builder<O extends ApiOptions> {
|
||||
Connection build(Context context, Looper looper, O options, AccountInfo accountInfo,
|
||||
GoogleApiClient.ConnectionCallbacks callbacks,
|
||||
GoogleApiClient.OnConnectionFailedListener connectionFailedListener);
|
||||
}
|
||||
}
|
||||
|
@ -3,12 +3,19 @@ package com.google.android.gms.common.api;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.view.View;
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import org.microg.gms.Constants;
|
||||
import org.microg.gms.common.api.GoogleApiClientImpl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Handler;
|
||||
|
||||
/**
|
||||
* The main entry point for Google Play services integration.
|
||||
@ -209,13 +216,27 @@ public interface GoogleApiClient {
|
||||
* Builder to configure a {@link GoogleApiClient}.
|
||||
*/
|
||||
public class Builder {
|
||||
private final Context context;
|
||||
private final Map<Api, Api.ApiOptions> apis = new HashMap<>();
|
||||
private final Set<ConnectionCallbacks> connectionCallbacks = new HashSet<>();
|
||||
private final Set<OnConnectionFailedListener> connectionFailedListeners = new HashSet<>();
|
||||
private final Set<String> scopes = new HashSet<>();
|
||||
private String accountName;
|
||||
private int clientId = -1;
|
||||
private FragmentActivity fragmentActivity;
|
||||
private Looper looper;
|
||||
private int gravityForPopups;
|
||||
private OnConnectionFailedListener unresolvedConnectionFailedListener;
|
||||
private View viewForPopups;
|
||||
|
||||
/**
|
||||
* Builder to help construct the {@link GoogleApiClient} object.
|
||||
*
|
||||
* @param context The context to use for the connection.
|
||||
*/
|
||||
public Builder(Context context) {
|
||||
|
||||
this.context = context;
|
||||
this.looper = context.getMainLooper();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -242,7 +263,7 @@ public interface GoogleApiClient {
|
||||
* @see Api
|
||||
*/
|
||||
public <O extends Api.ApiOptions.HasOptions> Builder addApi(Api<O> api, O options) {
|
||||
// TODO
|
||||
apis.put(api, options);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -253,7 +274,7 @@ public interface GoogleApiClient {
|
||||
* @see Api
|
||||
*/
|
||||
public Builder addApi(Api<? extends Api.ApiOptions.NotRequiredOptions> api) {
|
||||
// TODO
|
||||
apis.put(api, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -273,7 +294,7 @@ public interface GoogleApiClient {
|
||||
* call are delivered.
|
||||
*/
|
||||
public Builder addConnectionCallbacks(ConnectionCallbacks listener) {
|
||||
// TODO
|
||||
connectionCallbacks.add(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -293,7 +314,7 @@ public interface GoogleApiClient {
|
||||
* call are delivered.
|
||||
*/
|
||||
public Builder addOnConnectionFailedListener(OnConnectionFailedListener listener) {
|
||||
// TODO
|
||||
connectionFailedListeners.add(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -305,7 +326,7 @@ public interface GoogleApiClient {
|
||||
* @see com.google.android.gms.common.Scopes
|
||||
*/
|
||||
public Builder addScope(Scope scope) {
|
||||
// TODO
|
||||
scopes.add(scope.getScopeUri());
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -315,13 +336,20 @@ public interface GoogleApiClient {
|
||||
* @return The {@link GoogleApiClient} object.
|
||||
*/
|
||||
public GoogleApiClient build() {
|
||||
return null; // TODO
|
||||
return new GoogleApiClientImpl(context, looper, getAccountInfo(), apis,
|
||||
connectionCallbacks, connectionFailedListeners, clientId);
|
||||
}
|
||||
|
||||
private AccountInfo getAccountInfo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Builder enableAutoManage(FragmentActivity fragmentActivity, int cliendId,
|
||||
OnConnectionFailedListener unresolvedConnectionFailedListener)
|
||||
throws NullPointerException, IllegalArgumentException, IllegalStateException {
|
||||
// TODO
|
||||
this.fragmentActivity = fragmentActivity;
|
||||
this.clientId = cliendId;
|
||||
this.unresolvedConnectionFailedListener = unresolvedConnectionFailedListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -334,7 +362,7 @@ public interface GoogleApiClient {
|
||||
* {@link GoogleApiClient}.
|
||||
*/
|
||||
public Builder setAccountName(String accountName) {
|
||||
// TODO
|
||||
this.accountName = accountName;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -345,7 +373,7 @@ public interface GoogleApiClient {
|
||||
* @param gravityForPopups The gravity which controls the placement of games service popups.
|
||||
*/
|
||||
public Builder setGravityForPopups(int gravityForPopups) {
|
||||
// TODO
|
||||
this.gravityForPopups = gravityForPopups;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -355,7 +383,7 @@ public interface GoogleApiClient {
|
||||
* thread will be used.
|
||||
*/
|
||||
public Builder setHandler(Handler handler) {
|
||||
// TODO
|
||||
this.looper = handler.getLooper();
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -365,7 +393,7 @@ public interface GoogleApiClient {
|
||||
* @param viewForPopups The view to use as a content view for popups. View cannot be null.
|
||||
*/
|
||||
public Builder setViewForPopups(View viewForPopups) {
|
||||
// TODO
|
||||
this.viewForPopups = viewForPopups;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -373,7 +401,7 @@ public interface GoogleApiClient {
|
||||
* Specify that the default account should be used when connecting to services.
|
||||
*/
|
||||
public Builder useDefaultAccount() {
|
||||
// TODO
|
||||
this.accountName = Constants.DEFAULT_ACCOUNT;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +0,0 @@
|
||||
package com.google.android.gms.common.api;
|
||||
|
||||
/**
|
||||
* Represents the final result of invoking an API method in Google Play Services.
|
||||
*/
|
||||
public interface Result {
|
||||
public Status getStatus();
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package com.google.android.gms.common.api;
|
||||
|
||||
/**
|
||||
* Represents the results of work.
|
||||
* <p/>
|
||||
* TODO: content (is this IPC API?)
|
||||
*/
|
||||
public final class Status implements Result {
|
||||
@Override
|
||||
public Status getStatus() {
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.google.android.gms.location;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.location.Location;
|
||||
import android.os.Looper;
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
import com.google.android.gms.common.api.PendingResult;
|
||||
import org.microg.gms.Constants;
|
||||
|
||||
public interface FusedLocationProviderApi {
|
||||
String KEY_LOCATION_CHANGED = "com.google.android.location.LOCATION";
|
||||
String KEY_MOCK_LOCATION = Constants.KEY_MOCK_LOCATION;
|
||||
|
||||
public Location getLastLocation(GoogleApiClient client);
|
||||
|
||||
public PendingResult requestLocationUpdates(GoogleApiClient client, LocationRequest request,
|
||||
LocationListener listener);
|
||||
|
||||
public PendingResult requestLocationUpdates(GoogleApiClient client, LocationRequest request,
|
||||
LocationListener listener, Looper looper);
|
||||
|
||||
public PendingResult requestLocationUpdates(GoogleApiClient client, LocationRequest request,
|
||||
PendingIntent callbackIntent);
|
||||
|
||||
public PendingResult removeLocationUpdates(GoogleApiClient client, LocationListener listener);
|
||||
|
||||
public PendingResult removeLocationUpdates(GoogleApiClient client,
|
||||
PendingIntent callbackIntent);
|
||||
|
||||
public PendingResult setMockMode(GoogleApiClient client, boolean isMockMode);
|
||||
|
||||
public PendingResult setMockLocation(GoogleApiClient client, Location mockLocation);
|
||||
}
|
4
src/com/google/android/gms/location/GeofencingApi.java
Normal file
4
src/com/google/android/gms/location/GeofencingApi.java
Normal file
@ -0,0 +1,4 @@
|
||||
package com.google.android.gms.location;
|
||||
|
||||
public interface GeofencingApi {
|
||||
}
|
78
src/com/google/android/gms/location/LocationClient.java
Normal file
78
src/com/google/android/gms/location/LocationClient.java
Normal file
@ -0,0 +1,78 @@
|
||||
package com.google.android.gms.location;
|
||||
|
||||
import android.content.Context;
|
||||
import com.google.android.gms.common.GooglePlayServicesClient;
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
import org.microg.gms.common.ForwardConnectionCallbacks;
|
||||
import org.microg.gms.common.ForwardConnectionFailedListener;
|
||||
|
||||
@Deprecated
|
||||
public class LocationClient implements GooglePlayServicesClient {
|
||||
private GoogleApiClient googleApiClient;
|
||||
|
||||
public LocationClient(Context context, ConnectionCallbacks callbacks) {
|
||||
googleApiClient = new GoogleApiClient.Builder(context)
|
||||
.addApi(LocationServices.API)
|
||||
.addConnectionCallbacks(new ForwardConnectionCallbacks(callbacks))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
googleApiClient.connect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
googleApiClient.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
return googleApiClient.isConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnecting() {
|
||||
return googleApiClient.isConnecting();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerConnectionCallbacks(final ConnectionCallbacks listener) {
|
||||
googleApiClient.registerConnectionCallbacks(new ForwardConnectionCallbacks(listener));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnectionCallbacksRegistered(ConnectionCallbacks listener) {
|
||||
return googleApiClient
|
||||
.isConnectionCallbacksRegistered(new ForwardConnectionCallbacks(listener));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterConnectionCallbacks(
|
||||
ConnectionCallbacks listener) {
|
||||
googleApiClient.unregisterConnectionCallbacks(new ForwardConnectionCallbacks(listener));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerConnectionFailedListener(
|
||||
OnConnectionFailedListener listener) {
|
||||
googleApiClient.registerConnectionFailedListener(
|
||||
new ForwardConnectionFailedListener(listener));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnectionFailedListenerRegistered(
|
||||
OnConnectionFailedListener listener) {
|
||||
return googleApiClient.isConnectionFailedListenerRegistered(
|
||||
new ForwardConnectionFailedListener(listener));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterConnectionFailedListener(
|
||||
OnConnectionFailedListener listener) {
|
||||
googleApiClient.unregisterConnectionFailedListener(
|
||||
new ForwardConnectionFailedListener(listener));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package com.google.android.gms.location;
|
||||
|
||||
public interface LocationListener {
|
||||
}
|
28
src/com/google/android/gms/location/LocationServices.java
Normal file
28
src/com/google/android/gms/location/LocationServices.java
Normal file
@ -0,0 +1,28 @@
|
||||
package com.google.android.gms.location;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
import com.google.android.gms.common.api.AccountInfo;
|
||||
import com.google.android.gms.common.api.Api;
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
import org.microg.gms.location.FusedLocationProviderApiImpl;
|
||||
import org.microg.gms.location.GeofencingApiImpl;
|
||||
import org.microg.gms.location.LocationClientImpl;
|
||||
|
||||
/**
|
||||
* The main entry point for location services integration.
|
||||
*/
|
||||
public class LocationServices {
|
||||
public static final Api<Api.ApiOptions.NoOptions> API = new Api<>(
|
||||
new Api.Builder<Api.ApiOptions.NoOptions>() {
|
||||
@Override
|
||||
public Api.Connection build(Context context, Looper looper,
|
||||
Api.ApiOptions.NoOptions options,
|
||||
AccountInfo accountInfo, GoogleApiClient.ConnectionCallbacks callbacks,
|
||||
GoogleApiClient.OnConnectionFailedListener connectionFailedListener) {
|
||||
return new LocationClientImpl(context);
|
||||
}
|
||||
});
|
||||
public static final FusedLocationProviderApi FusedLocationApi = new FusedLocationProviderApiImpl();
|
||||
public static final GeofencingApi GeofencingApi = new GeofencingApiImpl();
|
||||
}
|
35
src/org/microg/gms/common/ForwardConnectionCallbacks.java
Normal file
35
src/org/microg/gms/common/ForwardConnectionCallbacks.java
Normal file
@ -0,0 +1,35 @@
|
||||
package org.microg.gms.common;
|
||||
|
||||
import android.os.Bundle;
|
||||
import com.google.android.gms.common.GooglePlayServicesClient;
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
import com.google.android.gms.location.LocationClient;
|
||||
|
||||
public final class ForwardConnectionCallbacks implements GoogleApiClient.ConnectionCallbacks {
|
||||
private final GooglePlayServicesClient.ConnectionCallbacks callbacks;
|
||||
|
||||
public ForwardConnectionCallbacks(GooglePlayServicesClient.ConnectionCallbacks callbacks) {
|
||||
this.callbacks = callbacks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof ForwardConnectionCallbacks &&
|
||||
callbacks.equals(((ForwardConnectionCallbacks) o).callbacks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return callbacks.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnected(Bundle connectionHint) {
|
||||
callbacks.onConnected(connectionHint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionSuspended(int cause) {
|
||||
callbacks.onDisconnected();
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package org.microg.gms.common;
|
||||
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GooglePlayServicesClient;
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
|
||||
public final class ForwardConnectionFailedListener
|
||||
implements GoogleApiClient.OnConnectionFailedListener {
|
||||
private final GooglePlayServicesClient.OnConnectionFailedListener listener;
|
||||
|
||||
public ForwardConnectionFailedListener(
|
||||
GooglePlayServicesClient.OnConnectionFailedListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof ForwardConnectionFailedListener &&
|
||||
listener.equals(((ForwardConnectionFailedListener) o).listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return listener.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionFailed(ConnectionResult result) {
|
||||
listener.onConnectionFailed(result);
|
||||
}
|
||||
}
|
105
src/org/microg/gms/common/GmsClient.java
Normal file
105
src/org/microg/gms/common/GmsClient.java
Normal file
@ -0,0 +1,105 @@
|
||||
package org.microg.gms.common;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.IInterface;
|
||||
import android.os.RemoteException;
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GooglePlayServicesUtil;
|
||||
import com.google.android.gms.common.api.Api;
|
||||
import com.google.android.gms.common.internal.IGmsCallbacks;
|
||||
import com.google.android.gms.common.internal.IGmsServiceBroker;
|
||||
|
||||
public abstract class GmsClient<I extends IInterface> implements Api.Connection {
|
||||
private static final String TAG = "GmsClient";
|
||||
|
||||
private final Context context;
|
||||
private ConnectionState state = ConnectionState.CONNECTED;
|
||||
private ServiceConnection serviceConnection;
|
||||
private I serviceInterface;
|
||||
|
||||
public GmsClient(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
protected abstract String getActionString();
|
||||
|
||||
protected abstract void onConnectedToBroker(IGmsServiceBroker broker, GmsCallbacks callbacks)
|
||||
throws RemoteException;
|
||||
|
||||
protected abstract I interfaceFromBinder(IBinder binder);
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
state = ConnectionState.CONNECTING;
|
||||
if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(context) !=
|
||||
ConnectionResult.SUCCESS) {
|
||||
state = ConnectionState.NOT_CONNECTED;
|
||||
} else {
|
||||
if (serviceConnection != null) {
|
||||
MultiConnectionKeeper.getInstance(context)
|
||||
.unbind(getActionString(), serviceConnection);
|
||||
}
|
||||
serviceConnection = new GmsServiceConnection();
|
||||
MultiConnectionKeeper.getInstance(context).bind(getActionString(),
|
||||
serviceConnection);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
serviceInterface = null;
|
||||
if (serviceConnection != null) {
|
||||
MultiConnectionKeeper.getInstance(context).unbind(getActionString(), serviceConnection);
|
||||
serviceConnection = null;
|
||||
}
|
||||
state = ConnectionState.NOT_CONNECTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
return state == ConnectionState.CONNECTED;
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public I getServiceInterface() {
|
||||
return serviceInterface;
|
||||
}
|
||||
|
||||
private enum ConnectionState {
|
||||
NOT_CONNECTED, CONNECTING, CONNECTED, ERROR
|
||||
}
|
||||
|
||||
private class GmsServiceConnection implements ServiceConnection {
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
|
||||
try {
|
||||
onConnectedToBroker(IGmsServiceBroker.Stub.asInterface(iBinder), new GmsCallbacks());
|
||||
} catch (RemoteException e) {
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName componentName) {
|
||||
state = ConnectionState.ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
public class GmsCallbacks extends IGmsCallbacks.Stub {
|
||||
|
||||
@Override
|
||||
public void onPostInitComplete(int statusCode, IBinder binder, Bundle params)
|
||||
throws RemoteException {
|
||||
serviceInterface = interfaceFromBinder(binder);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
136
src/org/microg/gms/common/MultiConnectionKeeper.java
Normal file
136
src/org/microg/gms/common/MultiConnectionKeeper.java
Normal file
@ -0,0 +1,136 @@
|
||||
package org.microg.gms.common;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.microg.gms.Constants.GMS_PACKAGE_NAME;
|
||||
|
||||
public class MultiConnectionKeeper {
|
||||
private static MultiConnectionKeeper INSTANCE;
|
||||
|
||||
private final Context context;
|
||||
private final Map<String, Connection> connections = new HashMap<>();
|
||||
|
||||
public MultiConnectionKeeper(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public static MultiConnectionKeeper getInstance(Context context) {
|
||||
if (INSTANCE == null)
|
||||
INSTANCE = new MultiConnectionKeeper(context);
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public boolean bind(String action, ServiceConnection connection) {
|
||||
Connection con = connections.get(action);
|
||||
if (con != null) {
|
||||
if (!con.forwardsConnection(connection)) {
|
||||
con.addConnectionForward(connection);
|
||||
if (!con.isBound())
|
||||
con.bind();
|
||||
}
|
||||
} else {
|
||||
con = new Connection(action);
|
||||
con.addConnectionForward(connection);
|
||||
con.bind();
|
||||
connections.put(action, con);
|
||||
}
|
||||
return con.isBound();
|
||||
}
|
||||
|
||||
public void unbind(String action, ServiceConnection connection) {
|
||||
Connection con = connections.get(action);
|
||||
if (con != null) {
|
||||
con.removeConnectionForward(connection);
|
||||
if (!con.hasForwards() && con.isBound()) {
|
||||
con.unbind();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Connection {
|
||||
private final String actionString;
|
||||
private final Set<ServiceConnection> connectionForwards = new HashSet<>();
|
||||
private boolean bound = false;
|
||||
private boolean connected = false;
|
||||
private IBinder binder;
|
||||
private ComponentName component;
|
||||
private ServiceConnection serviceConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
|
||||
binder = iBinder;
|
||||
component = componentName;
|
||||
for (ServiceConnection connection : connectionForwards) {
|
||||
connection.onServiceConnected(componentName, iBinder);
|
||||
}
|
||||
connected = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName componentName) {
|
||||
binder = null;
|
||||
component = componentName;
|
||||
for (ServiceConnection connection : connectionForwards) {
|
||||
connection.onServiceDisconnected(componentName);
|
||||
}
|
||||
connected = false;
|
||||
}
|
||||
};
|
||||
|
||||
public Connection(String actionString) {
|
||||
this.actionString = actionString;
|
||||
}
|
||||
|
||||
public void bind() {
|
||||
Intent intent = new Intent(actionString).setPackage(GMS_PACKAGE_NAME);
|
||||
bound = context.bindService(intent, serviceConnection,
|
||||
Context.BIND_ADJUST_WITH_ACTIVITY & Context.BIND_AUTO_CREATE);
|
||||
if (!bound) {
|
||||
context.unbindService(serviceConnection);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBound() {
|
||||
return bound;
|
||||
}
|
||||
|
||||
public IBinder getBinder() {
|
||||
return binder;
|
||||
}
|
||||
|
||||
public void unbind() {
|
||||
context.unbindService(serviceConnection);
|
||||
bound = false;
|
||||
}
|
||||
|
||||
public void addConnectionForward(ServiceConnection connection) {
|
||||
connectionForwards.add(connection);
|
||||
if (connected) {
|
||||
connection.onServiceConnected(component, binder);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeConnectionForward(ServiceConnection connection) {
|
||||
connectionForwards.remove(connection);
|
||||
if (connected) {
|
||||
connection.onServiceDisconnected(component);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean forwardsConnection(ServiceConnection connection) {
|
||||
return connectionForwards.contains(connection);
|
||||
}
|
||||
|
||||
public boolean hasForwards() {
|
||||
return !connectionForwards.isEmpty();
|
||||
}
|
||||
}
|
||||
}
|
95
src/org/microg/gms/common/api/AbstractPendingResult.java
Normal file
95
src/org/microg/gms/common/api/AbstractPendingResult.java
Normal file
@ -0,0 +1,95 @@
|
||||
package org.microg.gms.common.api;
|
||||
|
||||
import android.os.Looper;
|
||||
import com.google.android.gms.common.api.PendingResult;
|
||||
import com.google.android.gms.common.api.Result;
|
||||
import com.google.android.gms.common.api.ResultCallback;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class AbstractPendingResult<R extends Result> implements PendingResult<R> {
|
||||
private final Object lock = new Object();
|
||||
private final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
private final CallbackHandler handler;
|
||||
private boolean canceled;
|
||||
private R result;
|
||||
private ResultCallback<R> resultCallback;
|
||||
|
||||
public AbstractPendingResult(Looper looper) {
|
||||
handler = new CallbackHandler(looper);
|
||||
}
|
||||
|
||||
private R getResult() {
|
||||
synchronized (lock) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public R await() {
|
||||
try {
|
||||
countDownLatch.await();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
return getResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public R await(long time, TimeUnit unit) {
|
||||
try {
|
||||
countDownLatch.await(time, unit);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
return getResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCanceled() {
|
||||
synchronized (lock) {
|
||||
return canceled;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isReady() {
|
||||
return this.countDownLatch.getCount() == 0L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResultCallback(ResultCallback<R> callback, long time, TimeUnit unit) {
|
||||
synchronized (lock) {
|
||||
if (!isCanceled()) {
|
||||
if (isReady()) {
|
||||
handler.sendResultCallback(callback, getResult());
|
||||
} else {
|
||||
handler.sendTimeoutResultCallback(this, unit.toMillis(time));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResultCallback(ResultCallback<R> callback) {
|
||||
synchronized (lock) {
|
||||
if (!isCanceled()) {
|
||||
if (isReady()) {
|
||||
handler.sendResultCallback(callback, getResult());
|
||||
} else {
|
||||
resultCallback = callback;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void deliverResult(R result) {
|
||||
this.result = result;
|
||||
countDownLatch.countDown();
|
||||
|
||||
}
|
||||
|
||||
}
|
42
src/org/microg/gms/common/api/CallbackHandler.java
Normal file
42
src/org/microg/gms/common/api/CallbackHandler.java
Normal file
@ -0,0 +1,42 @@
|
||||
package org.microg.gms.common.api;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import com.google.android.gms.common.api.Result;
|
||||
import com.google.android.gms.common.api.ResultCallback;
|
||||
|
||||
class CallbackHandler<R extends Result> extends Handler {
|
||||
public static final int CALLBACK_ON_COMPLETE = 1;
|
||||
public static final int CALLBACK_ON_TIMEOUT = 2;
|
||||
|
||||
public CallbackHandler(Looper looper) {
|
||||
super(looper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case CALLBACK_ON_COMPLETE:
|
||||
OnCompleteObject<R> o = (OnCompleteObject<R>) msg.obj;
|
||||
o.callback.onResult(o.result);
|
||||
break;
|
||||
case CALLBACK_ON_TIMEOUT:
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void sendResultCallback(ResultCallback<R> callback, R result) {
|
||||
|
||||
}
|
||||
|
||||
public void sendTimeoutResultCallback(AbstractPendingResult pendingResult, long millis) {
|
||||
|
||||
}
|
||||
|
||||
public static class OnCompleteObject<R extends Result> {
|
||||
public ResultCallback<R> callback;
|
||||
public R result;
|
||||
}
|
||||
}
|
155
src/org/microg/gms/common/api/GoogleApiClientImpl.java
Normal file
155
src/org/microg/gms/common/api/GoogleApiClientImpl.java
Normal file
@ -0,0 +1,155 @@
|
||||
package org.microg.gms.common.api;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.api.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class GoogleApiClientImpl implements GoogleApiClient {
|
||||
private final Context context;
|
||||
private final Looper looper;
|
||||
private final AccountInfo accountInfo;
|
||||
private final Map<Api, Api.ApiOptions> apis = new HashMap<>();
|
||||
private final Map<Api, Api.Connection> apiConnections = new HashMap<>();
|
||||
private final Set<ConnectionCallbacks> connectionCallbacks = new HashSet<>();
|
||||
private final Set<OnConnectionFailedListener> connectionFailedListeners = new HashSet<>();
|
||||
private final ConnectionCallbacks baseConnectionCallbacks = new ConnectionCallbacks() {
|
||||
@Override
|
||||
public void onConnected(Bundle connectionHint) {
|
||||
for (ConnectionCallbacks callback : connectionCallbacks) {
|
||||
callback.onConnected(connectionHint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionSuspended(int cause) {
|
||||
for (ConnectionCallbacks callback : connectionCallbacks) {
|
||||
callback.onConnectionSuspended(cause);
|
||||
}
|
||||
}
|
||||
};
|
||||
private final OnConnectionFailedListener baseConnectionFailedListener = new OnConnectionFailedListener() {
|
||||
@Override
|
||||
public void onConnectionFailed(ConnectionResult result) {
|
||||
for (OnConnectionFailedListener listener : connectionFailedListeners) {
|
||||
listener.onConnectionFailed(result);
|
||||
}
|
||||
}
|
||||
};
|
||||
private final int clientId;
|
||||
|
||||
public GoogleApiClientImpl(Context context, Looper looper, AccountInfo accountInfo,
|
||||
Map<Api, Api.ApiOptions> apis,
|
||||
Set<ConnectionCallbacks> connectionCallbacks,
|
||||
Set<OnConnectionFailedListener> connectionFailedListeners, int clientId) {
|
||||
this.context = context;
|
||||
this.looper = looper;
|
||||
this.accountInfo = accountInfo;
|
||||
this.apis.putAll(apis);
|
||||
this.connectionCallbacks.addAll(connectionCallbacks);
|
||||
this.connectionFailedListeners.addAll(connectionFailedListeners);
|
||||
this.clientId = clientId;
|
||||
|
||||
for (Api api : apis.keySet()) {
|
||||
apiConnections.put(api, api.getBuilder().build(context, looper,
|
||||
apis.get(api), accountInfo, baseConnectionCallbacks,
|
||||
baseConnectionFailedListener));
|
||||
}
|
||||
}
|
||||
|
||||
public Api.Connection getApiConnection(Api api) {
|
||||
return apiConnections.get(api);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionResult blockingConnect() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionResult blockingConnect(long timeout, TimeUnit unit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingResult<Status> clearDefaultAccountAndReconnect() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
for (Api.Connection connection : apiConnections.values()) {
|
||||
connection.connect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
for (Api.Connection connection : apiConnections.values()) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
for (Api.Connection connection : apiConnections.values()) {
|
||||
if (!connection.isConnected()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnecting() {
|
||||
return false; // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnectionCallbacksRegistered(ConnectionCallbacks listener) {
|
||||
return connectionCallbacks.contains(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnectionFailedListenerRegistered(
|
||||
OnConnectionFailedListener listener) {
|
||||
return connectionFailedListeners.contains(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reconnect() {
|
||||
disconnect();
|
||||
connect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerConnectionCallbacks(ConnectionCallbacks listener) {
|
||||
connectionCallbacks.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerConnectionFailedListener(OnConnectionFailedListener listener) {
|
||||
connectionFailedListeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopAutoManager(FragmentActivity lifecycleActivity) throws IllegalStateException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterConnectionCallbacks(ConnectionCallbacks listener) {
|
||||
connectionCallbacks.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterConnectionFailedListener(OnConnectionFailedListener listener) {
|
||||
connectionFailedListeners.remove(listener);
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package org.microg.gms.location;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.location.Location;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
import com.google.android.gms.common.api.PendingResult;
|
||||
import com.google.android.gms.location.FusedLocationProviderApi;
|
||||
import com.google.android.gms.location.LocationListener;
|
||||
import com.google.android.gms.location.LocationRequest;
|
||||
|
||||
public class FusedLocationProviderApiImpl implements FusedLocationProviderApi {
|
||||
private static final String TAG = "GmsFusedApiImpl";
|
||||
|
||||
@Override
|
||||
public Location getLastLocation(GoogleApiClient client) {
|
||||
try {
|
||||
return LocationClientImpl.get(client).getLastLocation();
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingResult requestLocationUpdates(GoogleApiClient client, LocationRequest request,
|
||||
LocationListener listener) {
|
||||
//LocationClientImpl.get(client).requestLocationUpdates(request, listener);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingResult requestLocationUpdates(GoogleApiClient client, LocationRequest request,
|
||||
LocationListener listener, Looper looper) {
|
||||
//LocationClientImpl.get(client).requestLocationUpdates(request, listener, looper);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingResult requestLocationUpdates(GoogleApiClient client, LocationRequest request,
|
||||
PendingIntent callbackIntent) {
|
||||
//LocationClientImpl.get(client).requestLocationUpdates(request, callbackIntent);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingResult removeLocationUpdates(GoogleApiClient client, LocationListener listener) {
|
||||
//LocationClientImpl.get(client).removeLocationUpdates(listener);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingResult removeLocationUpdates(GoogleApiClient client,
|
||||
PendingIntent callbackIntent) {
|
||||
//LocationClientImpl.get(client).removeLocationUpdates(callbackIntent);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingResult setMockMode(GoogleApiClient client, boolean isMockMode) {
|
||||
//LocationClientImpl.get(client).setMockMode(isMockMode);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingResult setMockLocation(GoogleApiClient client, Location mockLocation) {
|
||||
//LocationClientImpl.get(client).setMockLocation(mockLocation);
|
||||
return null;
|
||||
}
|
||||
}
|
6
src/org/microg/gms/location/GeofencingApiImpl.java
Normal file
6
src/org/microg/gms/location/GeofencingApiImpl.java
Normal file
@ -0,0 +1,6 @@
|
||||
package org.microg.gms.location;
|
||||
|
||||
import com.google.android.gms.location.GeofencingApi;
|
||||
|
||||
public class GeofencingApiImpl implements GeofencingApi {
|
||||
}
|
35
src/org/microg/gms/location/GoogleLocationManagerClient.java
Normal file
35
src/org/microg/gms/location/GoogleLocationManagerClient.java
Normal file
@ -0,0 +1,35 @@
|
||||
package org.microg.gms.location;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import com.google.android.gms.common.internal.IGmsServiceBroker;
|
||||
import com.google.android.gms.location.internal.IGoogleLocationManagerService;
|
||||
import org.microg.gms.Constants;
|
||||
import org.microg.gms.common.GmsClient;
|
||||
|
||||
public class GoogleLocationManagerClient extends GmsClient<IGoogleLocationManagerService> {
|
||||
public GoogleLocationManagerClient(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getActionString() {
|
||||
return Constants.ACTION_GMS_LOCATION_MANAGER_SERVICE_START;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IGoogleLocationManagerService interfaceFromBinder(IBinder binder) {
|
||||
return IGoogleLocationManagerService.Stub.asInterface(binder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onConnectedToBroker(IGmsServiceBroker broker, GmsCallbacks callbacks)
|
||||
throws RemoteException {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("client_name", "locationServices");
|
||||
broker.getGoogleLocationManagerService(callbacks, Constants.MAX_REFERENCE_VERSION,
|
||||
getContext().getPackageName(), bundle);
|
||||
}
|
||||
}
|
61
src/org/microg/gms/location/LocationClientImpl.java
Normal file
61
src/org/microg/gms/location/LocationClientImpl.java
Normal file
@ -0,0 +1,61 @@
|
||||
package org.microg.gms.location;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
import com.google.android.gms.location.LocationListener;
|
||||
import com.google.android.gms.location.LocationRequest;
|
||||
import com.google.android.gms.location.LocationServices;
|
||||
import org.microg.gms.common.api.GoogleApiClientImpl;
|
||||
|
||||
public class LocationClientImpl extends GoogleLocationManagerClient {
|
||||
public LocationClientImpl(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public static LocationClientImpl get(GoogleApiClient apiClient) {
|
||||
if (apiClient instanceof GoogleApiClientImpl) {
|
||||
return (LocationClientImpl) ((GoogleApiClientImpl) apiClient)
|
||||
.getApiConnection(LocationServices.API);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Location getLastLocation() throws RemoteException {
|
||||
return getServiceInterface().getLastLocation();
|
||||
}
|
||||
|
||||
public void requestLocationUpdates(LocationRequest request, LocationListener listener)
|
||||
throws RemoteException {
|
||||
|
||||
}
|
||||
|
||||
public void requestLocationUpdates(LocationRequest request, PendingIntent pendingIntent)
|
||||
throws RemoteException {
|
||||
|
||||
}
|
||||
|
||||
public void requestLocationUpdates(LocationRequest request, LocationListener listener,
|
||||
Looper looper) throws RemoteException {
|
||||
|
||||
}
|
||||
|
||||
public void removeLocationUpdates(LocationListener listener) throws RemoteException {
|
||||
|
||||
}
|
||||
|
||||
public void removeLocationUpdates(PendingIntent pendingIntent) throws RemoteException {
|
||||
|
||||
}
|
||||
|
||||
public void setMockMode(boolean isMockMode) throws RemoteException {
|
||||
|
||||
}
|
||||
|
||||
public void setMockLocation(Location mockLocation) throws RemoteException {
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user