Prepare for maven publishing, adopt api changes

This commit is contained in:
Marvin W 2016-11-06 16:13:15 +01:00
parent 3a219305d8
commit 2e3a13eaa5
No known key found for this signature in database
GPG Key ID: 072E9235DB996F2A
27 changed files with 1746 additions and 50 deletions

View File

@ -9,38 +9,10 @@ WIP
This is still work in progress, and most applications will not build.
However feel free to try it out and create issues for missing method calls (please include an application to test it).
Example: DashClock
------------------
[DashClock](https://code.google.com/p/dashclock/) is an open source clock widget with enhanced features.
However it uses play services as location backend and thus requires proprietary libraries to compile it.
Developer Notes
---------------
However, it is possible to build DashClock using GmsLib, supporting all it's location features, with or without play services installed.
To do this, download and build GmsLib plus its submodules and install it to the local gradle repository:
Replace all compile includes to com.google.android.gms with org.microg master-SNAPSHOT includes
$ git clone https://github.com/microg/android_external_GmsLib.git GmsLib
$ cd GmsLib
$ git submodule update --init --recursive
$ gradle install
sed -i 's/compile [\'"]com.google.android.gms:\([^:]*\):[^\']*[\'"]/compile \'org.microg:\1:master-SNAPSHOT\'/g' build.gradle
Then update the main/build.gradle to point to non-google gms in local maven:
repositories {
+ maven { url "${System.env.HOME}/.m2/repository" } // This can be mavenLocal() since Gradle 2.0
mavenCentral()
flatDir {
dirs '../local_aars'
}
}
dependencies {
compile 'com.android.support:support-v13:22.0.0'
- compile 'com.google.android.gms:play-services:4.0.30'
+ compile 'org.microg.gms:play-services:1.0-SNAPSHOT'
//compile 'com.mobeta.android.dslv:drag-sort-listview:0.6.1-SNAPSHOT-AAR'
compile 'com.mobeta.android.dslv:drag-sort-listview:0.6.1-SNAPSHOT-AAR@aar'
compile project(':api')
}
Afterwards you can compile dashclock the usual way:
$ gradle :main:assembleDebug

View File

@ -19,7 +19,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
classpath 'com.android.tools.build:gradle:2.2.2'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'
}
}

2
extern/GmsApi vendored

@ -1 +1 @@
Subproject commit acec513b19aaba856722fc22c9adf3f5e0ea3ac7
Subproject commit 9ff42ae73a02ea971dc557f657b612113dfa6e24

View File

@ -0,0 +1,34 @@
#
# Copyright 2013-2016 microG Project Team
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
POM_NAME=Play Services Library Base
POM_DESCRIPTION=Base classes used by all Play Services Library modules
POM_PACKAGING=aar
POM_URL=https://github.com/microg/android_external_GmsLib
POM_SCM_URL=https://github.com/microg/android_external_GmsLib
POM_SCM_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
POM_SCM_DEV_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
POM_LICENCE_NAME=The Apache Software License, Version 2.0
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=mar-v-in
POM_DEVELOPER_NAME=Marvin W

View File

@ -0,0 +1,23 @@
/*
* Copyright 2013-2015 microG Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.gms.common.api;
import org.microg.safeparcel.AutoSafeParcelable;
public class AccountInfo extends AutoSafeParcelable {
public static final Creator<AccountInfo> CREATOR = new AutoCreator<AccountInfo>(AccountInfo.class);
}

View File

@ -0,0 +1,84 @@
/*
* Copyright 2013-2015 microG Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.gms.common.api;
import org.microg.gms.common.PublicApi;
import org.microg.gms.common.api.ApiBuilder;
/**
* 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
* parts of Google Play Services.
* <p/>
* Google APIs are partitioned into sections which allow your application to configure only the
* services it requires. Each Google API provides an API object which can be passed to
* {@link GoogleApiClient.Builder#addApi(Api)} in order to configure and enable that functionality
* in your {@link GoogleApiClient} instance.
* <p/>
* See {@link GoogleApiClient.Builder} for usage examples.
*/
@PublicApi
public final class Api<O extends Api.ApiOptions> {
private final ApiBuilder<O> builder;
@PublicApi(exclude = true)
public Api(ApiBuilder<O> builder) {
this.builder = builder;
}
@PublicApi(exclude = true)
public ApiBuilder<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.
*/
@PublicApi
public interface ApiOptions {
/**
* Base interface for {@link ApiOptions} in {@link Api}s that have options.
*/
@PublicApi
interface HasOptions extends ApiOptions {
}
/**
* Base interface for {@link ApiOptions} that are not required, don't exist.
*/
@PublicApi
interface NotRequiredOptions extends ApiOptions {
}
/**
* {@link ApiOptions} implementation for {@link Api}s that do not take any options.
*/
@PublicApi
final class NoOptions implements NotRequiredOptions {
}
/**
* Base interface for {@link ApiOptions} that are optional.
*/
@PublicApi
interface Optional extends HasOptions, NotRequiredOptions {
}
}
}

View File

@ -0,0 +1,494 @@
/*
* Copyright 2013-2015 microG Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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.auth.AuthConstants;
import org.microg.gms.common.PublicApi;
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;
/**
* The main entry point for Google Play services integration.
* <p/>
* GoogleApiClient is used with a variety of static methods. Some of these methods require that
* GoogleApiClient be connected, some will queue up calls before GoogleApiClient is connected;
* check the specific API documentation to determine whether you need to be connected.
* <p/>
* Before any operation is executed, the GoogleApiClient must be connected using the
* {@link #connect()} method. The client is not considered connected until the
* {@link ConnectionCallbacks#onConnected(Bundle)} callback has been called.
* <p/>
* When your app is done using this client, call {@link #disconnect()}, even if the async result
* from {@link #connect()} has not yet been delivered.
* <p/>
* You should instantiate a client object in your Activity's {@link Activity#onCreate(Bundle)}
* method and then call {@link #connect()} in {@link Activity#onStart()} and {@link #disconnect()}
* in {@link Activity#onStop()}, regardless of the state.
*/
@PublicApi
public interface GoogleApiClient {
/**
* Connects the client to Google Play services. Blocks until the connection either succeeds or
* fails. This is not allowed on the UI thread.
*
* @return the result of the connection
*/
ConnectionResult blockingConnect();
/**
* Connects the client to Google Play services. Blocks until the connection is set or failed or
* has timed out. This is not allowed on the UI thread.
*
* @param timeout the maximum time to wait
* @param unit the time unit of the {@code timeout} argument
* @return the result of the connection
*/
ConnectionResult blockingConnect(long timeout, TimeUnit unit);
/**
* Clears the account selected by the user and reconnects the client asking the user to pick an
* account again if {@link Builder#useDefaultAccount()} was set.
*
* @return the pending result is fired once the default account has been cleared, but before
* the client is reconnected - for that {@link ConnectionCallbacks} can be used.
*/
PendingResult<Status> clearDefaultAccountAndReconnect();
/**
* Connects the client to Google Play services. This method returns immediately, and connects
* to the service in the background. If the connection is successful,
* {@link ConnectionCallbacks#onConnected(Bundle)} is called and enqueued items are executed.
* On a failure, {@link OnConnectionFailedListener#onConnectionFailed(ConnectionResult)} is
* called.
*/
void connect();
/**
* Closes the connection to Google Play services. No calls can be made using this client after
* calling this method. Any method calls that haven't executed yet will be canceled. That is
* {@link ResultCallback#onResult(Result)} won't be called, if connection to the service hasn't
* been established yet all calls already made will be canceled.
*
* @see #connect()
*/
void disconnect();
/**
* Checks if the client is currently connected to the service, so that requests to other
* methods will succeed. Applications should guard client actions caused by the user with a
* call to this method.
*
* @return {@code true} if the client is connected to the service.
*/
boolean isConnected();
/**
* Checks if the client is attempting to connect to the service.
*
* @return {@code true} if the client is attempting to connect to the service.
*/
boolean isConnecting();
/**
* Returns {@code true} if the specified listener is currently registered to receive connection
* events.
*
* @param listener The listener to check for.
* @return {@code true} if the specified listener is currently registered to receive connection
* events.
* @see #registerConnectionCallbacks(ConnectionCallbacks)
* @see #unregisterConnectionCallbacks(ConnectionCallbacks)
*/
boolean isConnectionCallbacksRegistered(ConnectionCallbacks listener);
/**
* Returns {@code true} if the specified listener is currently registered to receive connection
* failed events.
*
* @param listener The listener to check for.
* @return {@code true} if the specified listener is currently registered to receive connection
* failed events.
* @see #registerConnectionFailedListener(OnConnectionFailedListener)
* @see #unregisterConnectionFailedListener(OnConnectionFailedListener)
*/
public boolean isConnectionFailedListenerRegistered(OnConnectionFailedListener listener);
/**
* Closes the current connection to Google Play services and creates a new connection.
* <p/>
* This method closes the current connection then returns immediately and reconnects to the
* service in the background.
* <p/>
* After calling this method, your application will receive
* {@link ConnectionCallbacks#onConnected(Bundle)} if the connection is successful, or
* {@link OnConnectionFailedListener#onConnectionFailed(ConnectionResult)} if the connection
* failed.
*
* @see #connect()
* @see #disconnect()
*/
void reconnect();
/**
* Registers a listener to receive connection events from this {@link GoogleApiClient}. If the
* service is already connected, the listener's {@link ConnectionCallbacks#onConnected(Bundle)}
* method will be called immediately. Applications should balance calls to this method with
* calls to {@link #unregisterConnectionCallbacks(ConnectionCallbacks)} to avoid leaking
* resources.
* <p/>
* If the specified listener is already registered to receive connection events, this method
* will not add a duplicate entry for the same listener, but will still call the listener's
* {@link ConnectionCallbacks#onConnected(Bundle)} method if currently connected.
* <p/>
* Note that the order of messages received here may not be stable, so clients should not rely
* on the order that multiple listeners receive events in.
*
* @param listener the listener where the results of the asynchronous {@link #connect()} call
* are delivered.
*/
void registerConnectionCallbacks(ConnectionCallbacks listener);
/**
* Registers a listener to receive connection failed events from this {@link GoogleApiClient}.
* Unlike {@link #registerConnectionCallbacks(ConnectionCallbacks)}, if the service is not
* already connected, the listener's
* {@link OnConnectionFailedListener#onConnectionFailed(ConnectionResult)} method will not be
* called immediately. Applications should balance calls to this method with calls to
* {@link #unregisterConnectionFailedListener(OnConnectionFailedListener)} to avoid leaking
* resources.
* <p/>
* If the specified listener is already registered to receive connection failed events, this
* method will not add a duplicate entry for the same listener.
* <p/>
* Note that the order of messages received here may not be stable, so clients should not rely
* on the order that multiple listeners receive events in.
*
* @param listener the listener where the results of the asynchronous {@link #connect()} call
* are delivered.
*/
public void registerConnectionFailedListener(OnConnectionFailedListener listener);
/**
* Disconnects the client and stops automatic lifecycle management. Use this before creating a
* new client (which might be necessary when switching accounts, changing the set of used APIs
* etc.).
* <p/>
* This method must be called from the main thread.
*
* @param lifecycleActivity the activity managing the client's lifecycle.
* @throws IllegalStateException if called from outside of the main thread.
* @see Builder#enableAutoManage(FragmentActivity, int, OnConnectionFailedListener)
*/
void stopAutoManager(FragmentActivity lifecycleActivity) throws IllegalStateException;
/**
* Removes a connection listener from this {@link GoogleApiClient}. Note that removing a
* listener does not generate any callbacks.
* <p/>
* If the specified listener is not currently registered to receive connection events, this
* method will have no effect.
*
* @param listener the listener to unregister.
*/
void unregisterConnectionCallbacks(ConnectionCallbacks listener);
/**
* Removes a connection failed listener from the {@link GoogleApiClient}. Note that removing a
* listener does not generate any callbacks.
* <p/>
* If the specified listener is not currently registered to receive connection failed events,
* this method will have no effect.
*
* @param listener the listener to unregister.
*/
void unregisterConnectionFailedListener(OnConnectionFailedListener listener);
/**
* Builder to configure a {@link GoogleApiClient}.
*/
@PublicApi
class Builder {
private final Context context;
private final Map<Api, Api.ApiOptions> apis = new HashMap<Api, Api.ApiOptions>();
private final Set<ConnectionCallbacks> connectionCallbacks = new HashSet<ConnectionCallbacks>();
private final Set<OnConnectionFailedListener> connectionFailedListeners = new HashSet<OnConnectionFailedListener>();
private final Set<String> scopes = new HashSet<String>();
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();
}
/**
* Builder to help construct the {@link GoogleApiClient} object.
*
* @param context The context to use for the connection.
* @param connectedListener The listener where the results of the asynchronous
* {@link #connect()} call are delivered.
* @param connectionFailedListener The listener which will be notified if the connection
* attempt fails.
*/
public Builder(Context context, ConnectionCallbacks connectedListener,
OnConnectionFailedListener connectionFailedListener) {
this(context);
addConnectionCallbacks(connectedListener);
addOnConnectionFailedListener(connectionFailedListener);
}
/**
* Specify which Apis are requested by your app. See {@link Api} for more information.
*
* @param api The Api requested by your app.
* @param options Any additional parameters required for the specific AP
* @see Api
*/
public <O extends Api.ApiOptions.HasOptions> Builder addApi(Api<O> api, O options) {
apis.put(api, options);
return this;
}
/**
* Specify which Apis are requested by your app. See {@link Api} for more information.
*
* @param api The Api requested by your app.
* @see Api
*/
public Builder addApi(Api<? extends Api.ApiOptions.NotRequiredOptions> api) {
apis.put(api, null);
return this;
}
/**
* Registers a listener to receive connection events from this {@link GoogleApiClient}.
* Applications should balance calls to this method with calls to
* {@link #unregisterConnectionCallbacks(ConnectionCallbacks)} to avoid
* leaking resources.
* <p/>
* If the specified listener is already registered to receive connection events, this
* method will not add a duplicate entry for the same listener.
* <p/>
* Note that the order of messages received here may not be stable, so clients should not
* rely on the order that multiple listeners receive events in.
*
* @param listener the listener where the results of the asynchronous {@link #connect()}
* call are delivered.
*/
public Builder addConnectionCallbacks(ConnectionCallbacks listener) {
connectionCallbacks.add(listener);
return this;
}
/**
* Adds a listener to register to receive connection failed events from this
* {@link GoogleApiClient}. Applications should balance calls to this method with calls to
* {@link #unregisterConnectionFailedListener(OnConnectionFailedListener)} to avoid
* leaking resources.
* <p/>
* If the specified listener is already registered to receive connection failed events,
* this method will not add a duplicate entry for the same listener.
* <p/>
* Note that the order of messages received here may not be stable, so clients should not
* rely on the order that multiple listeners receive events in.
*
* @param listener the listener where the results of the asynchronous {@link #connect()}
* call are delivered.
*/
public Builder addOnConnectionFailedListener(OnConnectionFailedListener listener) {
connectionFailedListeners.add(listener);
return this;
}
/**
* Specify the OAuth 2.0 scopes requested by your app. See
* {@link com.google.android.gms.common.Scopes} for more information.
*
* @param scope The OAuth 2.0 scopes requested by your app.
* @see com.google.android.gms.common.Scopes
*/
public Builder addScope(Scope scope) {
scopes.add(scope.getScopeUri());
return this;
}
/**
* Builds a new {@link GoogleApiClient} object for communicating with the Google APIs.
*
* @return The {@link GoogleApiClient} object.
*/
public GoogleApiClient build() {
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 {
this.fragmentActivity = fragmentActivity;
this.clientId = cliendId;
this.unresolvedConnectionFailedListener = unresolvedConnectionFailedListener;
return this;
}
/**
* Specify an account name on the device that should be used. If this is never called, the
* client will use the current default account for Google Play services for this
* application.
*
* @param accountName The account name on the device that should be used by
* {@link GoogleApiClient}.
*/
public Builder setAccountName(String accountName) {
this.accountName = accountName;
return this;
}
/**
* Specifies the part of the screen at which games service popups (for example,
* "welcome back" or "achievement unlocked" popups) will be displayed using gravity.
*
* @param gravityForPopups The gravity which controls the placement of games service popups.
*/
public Builder setGravityForPopups(int gravityForPopups) {
this.gravityForPopups = gravityForPopups;
return this;
}
/**
* Sets a {@link Handler} to indicate which thread to use when invoking callbacks. Will not
* be used directly to handle callbacks. If this is not called then the application's main
* thread will be used.
*/
public Builder setHandler(Handler handler) {
this.looper = handler.getLooper();
return this;
}
/**
* Sets the {@link View} to use as a content view for popups.
*
* @param viewForPopups The view to use as a content view for popups. View cannot be null.
*/
public Builder setViewForPopups(View viewForPopups) {
this.viewForPopups = viewForPopups;
return this;
}
/**
* Specify that the default account should be used when connecting to services.
*/
public Builder useDefaultAccount() {
this.accountName = AuthConstants.DEFAULT_ACCOUNT;
return this;
}
}
/**
* Provides callbacks that are called when the client is connected or disconnected from the
* service. Most applications implement {@link #onConnected(Bundle)} to start making requests.
*/
@PublicApi
interface ConnectionCallbacks {
/**
* A suspension cause informing that the service has been killed.
*/
int CAUSE_SERVICE_DISCONNECTED = 1;
/**
* A suspension cause informing you that a peer device connection was lost.
*/
int CAUSE_NETWORK_LOST = 2;
/**
* After calling {@link #connect()}, this method will be invoked asynchronously when the
* connect request has successfully completed. After this callback, the application can
* make requests on other methods provided by the client and expect that no user
* intervention is required to call methods that use account and scopes provided to the
* client constructor.
* <p/>
* Note that the contents of the {@code connectionHint} Bundle are defined by the specific
* services. Please see the documentation of the specific implementation of
* {@link GoogleApiClient} you are using for more information.
*
* @param connectionHint Bundle of data provided to clients by Google Play services. May
* be null if no content is provided by the service.
*/
void onConnected(Bundle connectionHint);
/**
* Called when the client is temporarily in a disconnected state. This can happen if there
* is a problem with the remote service (e.g. a crash or resource problem causes it to be
* killed by the system). When called, all requests have been canceled and no outstanding
* listeners will be executed. GoogleApiClient will automatically attempt to restore the
* connection. Applications should disable UI components that require the service, and wait
* for a call to {@link #onConnected(Bundle)} to re-enable them.
*
* @param cause The reason for the disconnection. Defined by constants {@code CAUSE_*}.
*/
void onConnectionSuspended(int cause);
}
/**
* Provides callbacks for scenarios that result in a failed attempt to connect the client to
* the service. See {@link ConnectionResult} for a list of error codes and suggestions for
* resolution.
*/
@PublicApi
interface OnConnectionFailedListener {
/**
* Called when there was an error connecting the client to the service.
*
* @param result A {@link ConnectionResult} that can be used for resolving the error, and
* deciding what sort of error occurred. To resolve the error, the resolution
* must be started from an activity with a non-negative {@code requestCode}
* passed to {@link ConnectionResult#startResolutionForResult(Activity, int)}.
* Applications should implement {@link Activity#onActivityResult} in their
* Activity to call {@link #connect()} again if the user has resolved the
* issue (resultCode is {@link Activity#RESULT_OK}).
*/
void onConnectionFailed(ConnectionResult result);
}
}

View File

@ -0,0 +1,59 @@
/*
* Copyright 2013-2015 microG Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.gms.common.api;
import java.util.concurrent.TimeUnit;
/**
* Represents a pending result from calling an API method in Google Play services. The final result
* object from a PendingResult is of type R, which can be retrieved in one of two ways.
* <p/>
* <ul>
* <li>via blocking calls to {@link #await()}, or {@link #await(long, TimeUnit)}, or</li>
* <li>via a callback by passing in an object implementing interface {@link ResultCallback} to
* {@link #setResultCallback(ResultCallback)}.</li>
* </ul>
* After the result has been retrieved using {@link #await()} or delivered to the result callback,
* it is an error to attempt to retrieve the result again. It is the responsibility of the caller
* or callback receiver to release any resources associated with the returned result. Some result
* types may implement {@link Releasable}, in which case {@link Releasable#release()} should be
* used to free the associated resources.
* <p/>
* TODO: Docs
*/
public interface PendingResult<R extends Result> {
/**
* Blocks until the task is completed. This is not allowed on the UI thread. The returned
* result object can have an additional failure mode of INTERRUPTED.
*/
public R await();
/**
* Blocks until the task is completed or has timed out waiting for the result. This is not
* allowed on the UI thread. The returned result object can have an additional failure mode
* of either INTERRUPTED or TIMEOUT.
*/
public R await(long time, TimeUnit unit);
public void cancel();
public boolean isCanceled();
public void setResultCallback(ResultCallback<R> callback, long time, TimeUnit unit);
public void setResultCallback(ResultCallback<R> callback);
}

View File

@ -49,6 +49,7 @@ public class GmsConnector<C extends ApiConnection, R extends Result> {
public AbstractPendingResult<R> connect() {
Log.d(TAG, "connect()");
apiClient.incrementUsageCounter();
apiClient.getApiConnection(api);
Looper looper = apiClient.getLooper();
final AbstractPendingResult<R> result = new AbstractPendingResult<R>(looper);
@ -81,6 +82,7 @@ public class GmsConnector<C extends ApiConnection, R extends Result> {
@Override
public void onResultAvailable(R realResult) {
result.deliverResult(realResult);
apiClient.decrementUsageCounter();
}
});
} catch (RemoteException ignored) {

View File

@ -25,7 +25,7 @@ import org.microg.gms.common.ForwardConnectionCallbacks;
import org.microg.gms.common.ForwardConnectionFailedListener;
public class AbstractPlayServicesClient implements GooglePlayServicesClient {
private static final String TAG = "GmsPlatServicesClient";
private static final String TAG = "GmsPlayServicesClient";
protected final GoogleApiClient googleApiClient;
@ -46,7 +46,7 @@ public class AbstractPlayServicesClient implements GooglePlayServicesClient {
@Override
public void disconnect() {
Log.d(TAG, "disconnect()");
googleApiClient.disconnect();
//TODO googleApiClient.disconnect();
}
@Override

View File

@ -0,0 +1,30 @@
/*
* Copyright 2013-2016 microG Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.microg.gms.common.api;
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;
public interface ApiBuilder<O extends Api.ApiOptions> {
ApiConnection build(Context context, Looper looper, O options, AccountInfo accountInfo,
GoogleApiClient.ConnectionCallbacks callbacks,
GoogleApiClient.OnConnectionFailedListener connectionFailedListener);
}

View File

@ -0,0 +1,27 @@
/*
* Copyright 2013-2015 microG Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.microg.gms.common.api;
public interface ApiConnection {
void connect();
void disconnect();
boolean isConnected();
boolean isConnecting();
}

View File

@ -0,0 +1,242 @@
/*
* Copyright 2013-2016 microG Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.microg.gms.common.api;
import android.content.Context;
import android.os.Bundle;
import android.os.Looper;
import android.os.Message;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
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 com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.Status;
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 static final String TAG = "GmsApiClientImpl";
private final Context context;
private final Looper looper;
private final AccountInfo accountInfo;
private final Map<Api, Api.ApiOptions> apis = new HashMap<Api, Api.ApiOptions>();
private final Map<Api, ApiConnection> apiConnections = new HashMap<Api, ApiConnection>();
private final Handler handler;
private final Set<ConnectionCallbacks> connectionCallbacks = new HashSet<ConnectionCallbacks>();
private final Set<OnConnectionFailedListener> connectionFailedListeners = new HashSet<OnConnectionFailedListener>();
private final int clientId;
private final ConnectionCallbacks baseConnectionCallbacks = new ConnectionCallbacks() {
@Override
public void onConnected(Bundle connectionHint) {
Log.d(TAG, "ConnectionCallbacks : onConnected()");
for (ConnectionCallbacks callback : connectionCallbacks) {
callback.onConnected(connectionHint);
}
}
@Override
public void onConnectionSuspended(int cause) {
Log.d(TAG, "ConnectionCallbacks : onConnectionSuspended()");
for (ConnectionCallbacks callback : connectionCallbacks) {
callback.onConnectionSuspended(cause);
}
}
};
private final OnConnectionFailedListener baseConnectionFailedListener = new
OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult result) {
Log.d(TAG, "OnConnectionFailedListener : onConnectionFailed()");
for (OnConnectionFailedListener listener : connectionFailedListeners) {
listener.onConnectionFailed(result);
}
}
};
private int usageCounter = 0;
private boolean shouldDisconnect = false;
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.handler = new Handler(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 synchronized void incrementUsageCounter() {
usageCounter++;
}
public synchronized void decrementUsageCounter() {
usageCounter--;
if (shouldDisconnect) disconnect();
}
public Looper getLooper() {
return looper;
}
public ApiConnection 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 synchronized void connect() {
Log.d(TAG, "connect()");
if (isConnected() || isConnecting()) {
if (shouldDisconnect) {
shouldDisconnect = false;
return;
}
Log.d(TAG, "Already connected/connecting, nothing to do");
return;
}
for (ApiConnection connection : apiConnections.values()) {
if (!connection.isConnected()) {
connection.connect();
}
}
}
@Override
public synchronized void disconnect() {
if (usageCounter > 0) {
shouldDisconnect = true;
} else {
Log.d(TAG, "disconnect()");
for (ApiConnection connection : apiConnections.values()) {
if (connection.isConnected()) {
connection.disconnect();
}
}
}
}
@Override
public synchronized boolean isConnected() {
for (ApiConnection connection : apiConnections.values()) {
if (!connection.isConnected()) return false;
}
return true;
}
@Override
public synchronized boolean isConnecting() {
for (ApiConnection connection : apiConnections.values()) {
if (connection.isConnecting()) return true;
}
return false;
}
@Override
public boolean isConnectionCallbacksRegistered(ConnectionCallbacks listener) {
return connectionCallbacks.contains(listener);
}
@Override
public boolean isConnectionFailedListenerRegistered(
OnConnectionFailedListener listener) {
return connectionFailedListeners.contains(listener);
}
@Override
public synchronized void reconnect() {
Log.d(TAG, "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);
}
private class Handler extends android.os.Handler {
private Handler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
if (msg.what == 0 && msg.obj instanceof Runnable) {
((Runnable) msg.obj).run();
} else {
super.handleMessage(msg);
}
}
public void sendRunnable(Runnable runnable) {
sendMessage(obtainMessage(1, runnable));
}
}
}

View File

@ -0,0 +1,34 @@
#
# Copyright 2013-2016 microG Project Team
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
POM_NAME=Play Services Cast Library
POM_DESCRIPTION=The Play Services Library module to access the Cast API
POM_PACKAGING=aar
POM_URL=https://github.com/microg/android_external_GmsLib
POM_SCM_URL=https://github.com/microg/android_external_GmsLib
POM_SCM_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
POM_SCM_DEV_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
POM_LICENCE_NAME=The Apache Software License, Version 2.0
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=mar-v-in
POM_DEVELOPER_NAME=Marvin W

View File

@ -0,0 +1,34 @@
#
# Copyright 2013-2016 microG Project Team
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
POM_NAME=Play Services GCM Library
POM_DESCRIPTION=The Play Services Library module to access Google Cloud Messaging
POM_PACKAGING=aar
POM_URL=https://github.com/microg/android_external_GmsLib
POM_SCM_URL=https://github.com/microg/android_external_GmsLib
POM_SCM_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
POM_SCM_DEV_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
POM_LICENCE_NAME=The Apache Software License, Version 2.0
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=mar-v-in
POM_DEVELOPER_NAME=Marvin W

View File

@ -0,0 +1,34 @@
#
# Copyright 2013-2016 microG Project Team
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
POM_NAME=Play Services IID Library
POM_DESCRIPTION=The Play Services Library module to access the InstanceID API
POM_PACKAGING=aar
POM_URL=https://github.com/microg/android_external_GmsLib
POM_SCM_URL=https://github.com/microg/android_external_GmsLib
POM_SCM_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
POM_SCM_DEV_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
POM_LICENCE_NAME=The Apache Software License, Version 2.0
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=mar-v-in
POM_DEVELOPER_NAME=Marvin W

View File

@ -0,0 +1,34 @@
#
# Copyright 2013-2016 microG Project Team
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
POM_NAME=Play Services Cast Library
POM_DESCRIPTION=The Play Services Library module to access Google Location Services
POM_PACKAGING=aar
POM_URL=https://github.com/microg/android_external_GmsLib
POM_SCM_URL=https://github.com/microg/android_external_GmsLib
POM_SCM_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
POM_SCM_DEV_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
POM_LICENCE_NAME=The Apache Software License, Version 2.0
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=mar-v-in
POM_DEVELOPER_NAME=Marvin W

View File

@ -0,0 +1,34 @@
#
# Copyright 2013-2016 microG Project Team
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
POM_NAME=Play Services Library Tasks
POM_DESCRIPTION=Classes used by some Play Services Library modules to abstract tasks
POM_PACKAGING=aar
POM_URL=https://github.com/microg/android_external_GmsLib
POM_SCM_URL=https://github.com/microg/android_external_GmsLib
POM_SCM_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
POM_SCM_DEV_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
POM_LICENCE_NAME=The Apache Software License, Version 2.0
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=mar-v-in
POM_DEVELOPER_NAME=Marvin W

View File

@ -0,0 +1,34 @@
#
# Copyright 2013-2016 microG Project Team
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
POM_NAME=Play Services Wearable Library
POM_DESCRIPTION=The Play Services Library module to access the Wearable API
POM_PACKAGING=aar
POM_URL=https://github.com/microg/android_external_GmsLib
POM_SCM_URL=https://github.com/microg/android_external_GmsLib
POM_SCM_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
POM_SCM_DEV_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
POM_LICENCE_NAME=The Apache Software License, Version 2.0
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=mar-v-in
POM_DEVELOPER_NAME=Marvin W

View File

@ -0,0 +1,94 @@
/*
* Copyright 2013-2016 microG Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.gms.wearable;
import android.net.Uri;
import android.os.Parcelable;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.Releasable;
import com.google.android.gms.common.api.Result;
import com.google.android.gms.common.api.Status;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* A channel created through {@link ChannelApi#openChannel(GoogleApiClient, String, String)}.
* <p/>
* The implementation of this interface is parcelable and immutable, and implements reasonable {@link #equals(Object)}
* and {@link #hashCode()} methods, so can be used in collections.
*/
public interface Channel extends Parcelable {
PendingResult<Status> addListener(GoogleApiClient client, ChannelApi.ChannelListener listener);
PendingResult<Status> close(GoogleApiClient client, int errorCode);
PendingResult<Status> close(GoogleApiClient client);
PendingResult<GetInputStreamResult> getInputStream(GoogleApiClient client);
PendingResult<GetOutputStreamResult> getOutputStream(GoogleApiClient client);
String getPath();
PendingResult<Status> receiveFile(GoogleApiClient client, Uri uri, boolean append);
PendingResult<Status> removeListener(GoogleApiClient client, ChannelApi.ChannelListener listener);
PendingResult<Status> sendFile(GoogleApiClient client, Uri uri);
PendingResult<Status> sendFile(GoogleApiClient client, Uri uri, long startOffset, long length);
interface GetInputStreamResult extends Releasable, Result {
/**
* Returns an input stream which can read data from the remote node. The stream should be
* closed when no longer needed. This method will only return {@code null} if this result's
* {@linkplain #getStatus() status} was not {@linkplain Status#isSuccess() success}.
* <p/>
* The returned stream will throw {@link IOException} on read if any connection errors
* occur. This exception might be a {@link ChannelIOException}.
* <p/>
* Since data for this stream comes over the network, reads may block for a long time.
* <p/>
* Multiple calls to this method will return the same instance.
*/
InputStream getInputStream();
}
interface GetOutputStreamResult extends Releasable, Result {
/**
* Returns an output stream which can send data to a remote node. The stream should be
* closed when no longer needed. This method will only return {@code null} if this result's
* {@linkplain #getStatus() status} was not {@linkplain Status#isSuccess() success}.
* <p/>
* The returned stream will throw {@link IOException} on read if any connection errors
* occur. This exception might be a {@link ChannelIOException}.
* <p/>
* Since data for this stream comes over the network, reads may block for a long time.
* <p/>
* Data written to this stream is buffered. If you wish to send the current data without
* waiting for the buffer to fill up, {@linkplain OutputStream#flush() flush} the stream.
* <p/>
* Multiple calls to this method will return the same instance.
*/
OutputStream getOutputStream();
}
}

View File

@ -0,0 +1,185 @@
/*
* Copyright 2013-2016 microG Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.gms.wearable;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.Builder;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.Result;
import com.google.android.gms.common.api.Status;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Client interface for Wearable Channel API. Allows apps on a wearable device to send and receive
* data from other wearable nodes.
* <p/>
* Channels are bidirectional. Each side, both the initiator and the receiver may both read and
* write to the channel by using {@link Channel#getOutputStream(GoogleApiClient)} and {@link Channel#getInputStream(GoogleApiClient)}.
* Once a channel is established, the API for the initiator and receiver are identical.
* <p/>
* Channels are only available when the wearable nodes are connected. When the remote node
* disconnects, all existing channels will be closed. Any listeners (added through {@link #addListener(GoogleApiClient, ChannelListener)}
* and any installed {@link WearableListenerService}) will be notified of the channel closing.
*/
public interface ChannelApi {
/**
* Channel action for use in listener filters.
*
* @see WearableListenerService
*/
String ACTION_CHANNEL_EVENT = "com.google.android.gms.wearable.CHANNEL_EVENT";
/**
* Registers a listener to be notified of channel events. Calls to this method should be
* balanced with calls to {@link #removeListener(GoogleApiClient, ChannelListener)} to avoid
* leaking resources.
* <p/>
* Listener events will be called on the main thread, or the handler specified on {@code client}
* when it was built (using {@link Builder#setHandler(Handler)}).
* <p/>
* Callers wishing to be notified of events in the background should use {@link WearableListenerService}.
*
* @param client a connected client
* @param listener a listener which will be notified of changes to any channel
*/
PendingResult<Status> addListener(GoogleApiClient client, ChannelListener listener);
/**
* Opens a channel to exchange data with a remote node.
* <p/>
* Channel which are no longer needed should be closed using {@link Channel#close(GoogleApiClient)}.
* <p/>
* This call involves a network round trip, so may be long running. {@code client} must remain
* connected during that time, or the request will be cancelled (like any other Play Services
* API calls).
*
* @param client a connected client
* @param nodeId the node ID of a wearable node, as returned from {@link NodeApi#getConnectedNodes(GoogleApiClient)}
* @param path an app-specific identifier for the channel
*/
PendingResult<OpenChannelResult> openChannel(GoogleApiClient client, String nodeId, String path);
/**
* Removes a listener which was previously added through {@link #addListener(GoogleApiClient, ChannelListener)}.
*
* @param client a connected client
* @param listener a listener which was added using {@link #addListener(GoogleApiClient, ChannelListener)}
*/
PendingResult<Status> removeListener(GoogleApiClient client, ChannelListener listener);
/**
* A listener which will be notified on changes to channels.
*/
interface ChannelListener {
/**
* Value passed to {@link #onChannelClosed(Channel, int, int)}, {@link #onInputClosed(Channel, int, int)}
* and {@link #onOutputClosed(Channel, int, int)} when the closing is due to a remote node
* being disconnected.
*/
int CLOSE_REASON_DISCONNECTED = 1;
/**
* Value passed to {@link #onChannelClosed(Channel, int, int)}, {@link #onInputClosed(Channel, int, int)}
* and {@link #onOutputClosed(Channel, int, int)} when the stream is closed due to the
* local node calling {@link Channel#close(GoogleApiClient)} or {@link Channel#close(GoogleApiClient, int)}.
*/
int CLOSE_REASON_LOCAL_CLOSE = 3;
/**
* Value passed to {@link #onInputClosed(Channel, int, int)} or {@link #onOutputClosed(Channel, int, int)}
* (but not {@link #onChannelClosed(Channel, int, int)}), when the stream was closed under
* normal conditions, e.g the whole file was read, or the OutputStream on the remote node
* was closed normally.
*/
int CLOSE_REASON_NORMAL = 0;
/**
* Value passed to {@link #onChannelClosed(Channel, int, int)}, {@link #onInputClosed(Channel, int, int)}
* and {@link #onOutputClosed(Channel, int, int)} when the stream is closed due to the
* remote node calling {@link Channel#close(GoogleApiClient)} or {@link Channel#close(GoogleApiClient, int)}.
*/
int CLOSE_REASON_REMOTE_CLOSE = 2;
/**
* Called when a channel is closed. This can happen through an explicit call to {@link Channel#close(GoogleApiClient)}
* or {@link #close(GoogleApiClient, int)} on either side of the connection, or due to
* disconnecting from the remote node.
*
* @param closeReason the reason for the channel closing. One of {@link #CLOSE_REASON_DISCONNECTED},
* {@link #CLOSE_REASON_REMOTE_CLOSE}, or {@link #CLOSE_REASON_LOCAL_CLOSE}.
* @param appSpecificErrorCode the error code specified on {@link Channel#close(GoogleApiClient, int)},
* or 0 if closeReason is {@link #CLOSE_REASON_DISCONNECTED}.
*/
void onChannelClosed(Channel channel, int closeReason, int appSpecificErrorCode);
/**
* Called when a new channel is opened by a remote node.
*/
void onChannelOpened(Channel channel);
/**
* Called when the input side of a channel is closed.
*
* @param closeReason the reason for the channel closing. One of {@link #CLOSE_REASON_DISCONNECTED},
* {@link #CLOSE_REASON_REMOTE_CLOSE}, {@link #CLOSE_REASON_LOCAL_CLOSE}
* or {@link #CLOSE_REASON_NORMAL}.
* @param appSpecificErrorCode the error code specified on {@link Channel#close(GoogleApiClient, int)},
* or 0 if closeReason is {@link #CLOSE_REASON_DISCONNECTED} or
* {@link #CLOSE_REASON_NORMAL}.
*/
void onInputClosed(Channel channel, @CloseReason int closeReason, int appSpecificErrorCode);
/**
* Called when the output side of a channel is closed.
*
* @param closeReason the reason for the channel closing. One of {@link #CLOSE_REASON_DISCONNECTED},
* {@link #CLOSE_REASON_REMOTE_CLOSE}, {@link #CLOSE_REASON_LOCAL_CLOSE}
* or {@link #CLOSE_REASON_NORMAL}.
* @param appSpecificErrorCode the error code specified on {@link Channel#close(GoogleApiClient, int)},
* or 0 if closeReason is {@link #CLOSE_REASON_DISCONNECTED} or
* {@link #CLOSE_REASON_NORMAL}.
*/
void onOutputClosed(Channel channel, @CloseReason int closeReason, int appSpecificErrorCode);
}
/**
* An annotation for values passed to {@link ChannelListener#onChannelClosed(Channel, int, int)},
* and other methods on the {@link ChannelListener} interface. Annotated method parameters will
* always take one of the following values:
* <ul>
* <li>{@link ChannelListener#CLOSE_REASON_DISCONNECTED}</li>
* <li>{@link ChannelListener#CLOSE_REASON_NORMAL}</li>
* <li>{@link ChannelListener#CLOSE_REASON_LOCAL_CLOSE}</li>
* <li>{@link ChannelListener#CLOSE_REASON_REMOTE_CLOSE}</li>
* </ul>
*/
@Retention(RetentionPolicy.SOURCE)
@interface CloseReason {
}
/**
* Result of {@link #openChannel(GoogleApiClient, String, String)}.
*/
interface OpenChannelResult extends Result {
/**
* Returns the newly created channel, or {@code null}, if the connection couldn't be opened.
*/
Channel getChannel();
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright 2013-2015 microG Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.gms.wearable;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.Result;
import com.google.android.gms.common.api.Status;
import org.microg.gms.common.PublicApi;
@PublicApi
public interface MessageApi {
/**
* A value returned by {@link SendMessageResult#getRequestId()} when
* {@link #sendMessage(GoogleApiClient, String, String, byte[])} fails.
*/
int UNKNOWN_REQUEST_ID = -1;
/**
* Registers a listener to be notified of received messages. Calls to this method should
* balanced with {@link #removeListener(GoogleApiClient, MessageListener)} to avoid leaking
* resources.
* <p/>
* Callers wishing to be notified of events in the background should use {@link WearableListenerService}.
*/
PendingResult<Status> addListener(GoogleApiClient client, MessageListener listener);
/**
* Removes a message listener which was previously added through
* {@link #addListener(GoogleApiClient, MessageListener)}.
*/
PendingResult<Status> removeListener(GoogleApiClient client, MessageListener listener);
/**
* Sends {@code byte[]} data to the specified node.
*
* @param nodeId identifier for a particular node on the Android Wear network. Valid targets
* may be obtained through {@link NodeApi#getConnectedNodes(GoogleApiClient)}
* or from the host in {@link DataItem#getUri()}.
* @param path identifier used to specify a particular endpoint at the receiving node
* @param data small array of information to pass to the target node. Generally not larger
* than 100k
*/
PendingResult<SendMessageResult> sendMessage(GoogleApiClient client, String nodeId,
String path, byte[] data);
/**
* Used with {@link MessageApi#addListener(GoogleApiClient, MessageListener)} to receive
* message events.
* <p/>
* Callers wishing to be notified of events in the background should use
* {@link WearableListenerService}.
*/
interface MessageListener {
/**
* Notification that a message has been received.
*/
void onMessageReceived(MessageEvent messageEvent);
}
/**
* Contains the request id assigned to the message. On failure, the id will be
* {@link MessageApi#UNKNOWN_REQUEST_ID} and the status will be unsuccessful.
*/
interface SendMessageResult extends Result {
/**
* @return an ID used to identify the sent message. If {@link #getStatus()} is not
* successful, this value will be {@link MessageApi#UNKNOWN_REQUEST_ID}.
*/
int getRequestId();
}
}

View File

@ -36,6 +36,7 @@ import com.google.android.gms.wearable.internal.MessageEventParcelable;
import com.google.android.gms.wearable.internal.NodeParcelable;
import org.microg.gms.common.PublicApi;
import org.microg.gms.wearable.ChannelImpl;
import java.util.ArrayList;
import java.util.Arrays;
@ -241,16 +242,16 @@ public abstract class WearableListenerService extends Service implements Capabil
public void run() {
switch (channelEvent.eventType) {
case 1:
WearableListenerService.this.onChannelOpened(channelEvent.channel);
WearableListenerService.this.onChannelOpened(new ChannelImpl(channelEvent.channel));
break;
case 2:
WearableListenerService.this.onChannelClosed(channelEvent.channel, channelEvent.closeReason, channelEvent.appSpecificErrorCode);
WearableListenerService.this.onChannelClosed(new ChannelImpl(channelEvent.channel), channelEvent.closeReason, channelEvent.appSpecificErrorCode);
break;
case 3:
WearableListenerService.this.onInputClosed(channelEvent.channel, channelEvent.closeReason, channelEvent.appSpecificErrorCode);
WearableListenerService.this.onInputClosed(new ChannelImpl(channelEvent.channel), channelEvent.closeReason, channelEvent.appSpecificErrorCode);
break;
case 4:
WearableListenerService.this.onOutputClosed(channelEvent.channel, channelEvent.closeReason, channelEvent.appSpecificErrorCode);
WearableListenerService.this.onOutputClosed(new ChannelImpl(channelEvent.channel), channelEvent.closeReason, channelEvent.appSpecificErrorCode);
break;
default:
Log.w(TAG, "Unknown ChannelEvent.eventType");

View File

@ -0,0 +1,107 @@
/*
* Copyright 2013-2016 microG Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.microg.gms.wearable;
import android.net.Uri;
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.common.api.Status;
import com.google.android.gms.wearable.Channel;
import com.google.android.gms.wearable.ChannelApi;
import com.google.android.gms.wearable.internal.ChannelParcelable;
public class ChannelImpl extends ChannelParcelable implements Channel {
private static final String TAG = "GmsWearChannelImpl";
public ChannelImpl(String token, String nodeId, String path) {
super(token, nodeId, path);
}
public ChannelImpl(ChannelParcelable wrapped) {
this(wrapped.token, wrapped.nodeId, wrapped.path);
}
@Override
public PendingResult<Status> addListener(GoogleApiClient client, ChannelApi.ChannelListener listener) {
Log.d(TAG, "unimplemented Method: addListener");
return null;
}
@Override
public PendingResult<Status> close(GoogleApiClient client, int errorCode) {
Log.d(TAG, "unimplemented Method: close");
return null;
}
@Override
public PendingResult<Status> close(GoogleApiClient client) {
Log.d(TAG, "unimplemented Method: close");
return null;
}
@Override
public PendingResult<GetInputStreamResult> getInputStream(GoogleApiClient client) {
Log.d(TAG, "unimplemented Method: getInputStream");
return null;
}
@Override
public PendingResult<GetOutputStreamResult> getOutputStream(GoogleApiClient client) {
Log.d(TAG, "unimplemented Method: getOutputStream");
return null;
}
public String getNodeId() {
return nodeId;
}
@Override
public String getPath() {
return path;
}
public String getToken() {
return token;
}
@Override
public PendingResult<Status> receiveFile(GoogleApiClient client, Uri uri, boolean append) {
Log.d(TAG, "unimplemented Method: receiveFile");
return null;
}
@Override
public PendingResult<Status> removeListener(GoogleApiClient client, ChannelApi.ChannelListener listener) {
Log.d(TAG, "unimplemented Method: removeListener");
return null;
}
@Override
public PendingResult<Status> sendFile(GoogleApiClient client, Uri uri) {
Log.d(TAG, "unimplemented Method: sendFile");
return null;
}
@Override
public PendingResult<Status> sendFile(GoogleApiClient client, Uri uri, long startOffset, long length) {
Log.d(TAG, "unimplemented Method: sendFile");
return null;
}
}

View File

@ -17,7 +17,6 @@
package org.microg.gms.wearable;
import android.os.RemoteException;
import android.util.Log;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
@ -27,7 +26,6 @@ import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.internal.SendMessageResponse;
import org.microg.gms.common.GmsConnector;
import org.microg.gms.common.api.ApiConnection;
public class MessageApiImpl implements MessageApi {
@Override
@ -48,10 +46,28 @@ public class MessageApiImpl implements MessageApi {
client.getServiceInterface().sendMessage(new BaseWearableCallbacks() {
@Override
public void onSendMessageResponse(SendMessageResponse response) throws RemoteException {
resultProvider.onResultAvailable(response);
resultProvider.onResultAvailable(new SendMessageResultImpl(response));
}
}, nodeId, path, data);
}
});
}
public static class SendMessageResultImpl implements SendMessageResult {
private SendMessageResponse response;
public SendMessageResultImpl(SendMessageResponse response) {
this.response = response;
}
@Override
public int getRequestId() {
return response.requestId;
}
@Override
public Status getStatus() {
return new Status(response.statusCode);
}
}
}

View File

@ -139,7 +139,7 @@ public class DataBundleUtil {
@Override
void store(DataMap dataMap, String key, String value) {
dataMap.putString(key, value);
if (value != null) dataMap.putString(key, value);
}
@Override
@ -174,7 +174,7 @@ public class DataBundleUtil {
@Override
void store(DataMap dataMap, String key, Double value) {
dataMap.putDouble(key, value);
if (value != null) dataMap.putDouble(key, value);
}
@Override
@ -197,7 +197,7 @@ public class DataBundleUtil {
@Override
void store(DataMap dataMap, String key, Float value) {
dataMap.putFloat(key, value);
if (value != null) dataMap.putFloat(key, value);
}
@Override
@ -220,7 +220,7 @@ public class DataBundleUtil {
@Override
void store(DataMap dataMap, String key, Long value) {
dataMap.putLong(key, value);
if (value != null) dataMap.putLong(key, value);
}
@Override
@ -243,7 +243,7 @@ public class DataBundleUtil {
@Override
void store(DataMap dataMap, String key, Integer value) {
dataMap.putInt(key, value);
if (value != null) dataMap.putInt(key, value);
}
@Override
@ -278,7 +278,7 @@ public class DataBundleUtil {
@Override
void store(DataMap dataMap, String key, Byte value) {
dataMap.putByte(key, value);
if (value != null) dataMap.putByte(key, value);
}
@Override
@ -301,7 +301,7 @@ public class DataBundleUtil {
@Override
void store(DataMap dataMap, String key, Boolean value) {
dataMap.putBoolean(key, value);
if (value != null) dataMap.putBoolean(key, value);
}
@Override

View File

@ -0,0 +1,34 @@
#
# Copyright 2013-2016 microG Project Team
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
POM_NAME=Play Services Library
POM_DESCRIPTION=The whole package of Play Services libraries. Use play-services-* artifacts if you only need certain parts
POM_PACKAGING=aar
POM_URL=https://github.com/microg/android_external_GmsLib
POM_SCM_URL=https://github.com/microg/android_external_GmsLib
POM_SCM_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
POM_SCM_DEV_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
POM_LICENCE_NAME=The Apache Software License, Version 2.0
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=mar-v-in
POM_DEVELOPER_NAME=Marvin W