From 1374dfa01201561418230b4c5afeacb5a249b4d8 Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Tue, 31 Mar 2015 23:56:13 +0200 Subject: [PATCH] Add numerous wearable APIs --- extern/GmsApi | 2 +- .../android/gms/common/data/DataBuffer.java | 89 +++++ .../microg/gms/common/api/ApiConnection.java | 6 +- .../FusedLocationProviderApiImpl.java | 2 +- .../google/android/gms/wearable/DataApi.java | 145 +++++++ .../android/gms/wearable/DataEvent.java | 50 +++ .../android/gms/wearable/DataEventBuffer.java | 48 +++ .../android/gms/wearable/DataItemBuffer.java | 45 +++ .../google/android/gms/wearable/DataMap.java | 369 ++++++++++++++++++ .../android/gms/wearable/DataMapItem.java | 45 +++ .../android/gms/wearable/MessageApi.java | 68 ++++ .../android/gms/wearable/MessageEvent.java | 42 ++ .../google/android/gms/wearable/NodeApi.java | 78 ++++ .../gms/wearable/PutDataMapRequest.java | 83 ++++ .../gms/wearable/WearableListenerService.java | 58 +++ .../org/microg/gms/wearable/DataApiImpl.java | 53 +++ .../microg/gms/wearable/MessageApiImpl.java | 17 + .../org/microg/gms/wearable/NodeApiImpl.java | 22 ++ 18 files changed, 1217 insertions(+), 5 deletions(-) create mode 100644 play-services-base/src/main/java/com/google/android/gms/common/data/DataBuffer.java create mode 100644 play-services-wearable/src/main/java/com/google/android/gms/wearable/DataEvent.java create mode 100644 play-services-wearable/src/main/java/com/google/android/gms/wearable/DataEventBuffer.java create mode 100644 play-services-wearable/src/main/java/com/google/android/gms/wearable/DataItemBuffer.java create mode 100644 play-services-wearable/src/main/java/com/google/android/gms/wearable/DataMap.java create mode 100644 play-services-wearable/src/main/java/com/google/android/gms/wearable/DataMapItem.java create mode 100644 play-services-wearable/src/main/java/com/google/android/gms/wearable/MessageEvent.java create mode 100644 play-services-wearable/src/main/java/com/google/android/gms/wearable/PutDataMapRequest.java create mode 100644 play-services-wearable/src/main/java/com/google/android/gms/wearable/WearableListenerService.java diff --git a/extern/GmsApi b/extern/GmsApi index c43facae..70419935 160000 --- a/extern/GmsApi +++ b/extern/GmsApi @@ -1 +1 @@ -Subproject commit c43facae3dba6fcf4139c6a36e3a6f364d6db057 +Subproject commit 704199355e1c6f8b14402e01063fbae7b187b35b diff --git a/play-services-base/src/main/java/com/google/android/gms/common/data/DataBuffer.java b/play-services-base/src/main/java/com/google/android/gms/common/data/DataBuffer.java new file mode 100644 index 00000000..0d406cbd --- /dev/null +++ b/play-services-base/src/main/java/com/google/android/gms/common/data/DataBuffer.java @@ -0,0 +1,89 @@ +/* + * Copyright 2013-2015 µg 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.data; + +import com.google.android.gms.common.api.Releasable; + +import org.microg.gms.common.PublicApi; + +import java.util.Iterator; + +/** + * TODO + */ +@PublicApi +public abstract class DataBuffer implements Releasable, Iterable { + + private DataHolder dataHolder; + + @PublicApi(exclude = true) + public DataBuffer(DataHolder dataHolder) { + this.dataHolder = dataHolder; + } + + /** + * @deprecated use {@link #release()} instead + */ + @Deprecated + public final void close() { + release(); + } + + /** + * Get the item at the specified position. Note that the objects returned from subsequent + * invocations of this method for the same position may not be identical objects, but will be + * equal in value. + * + * @param position The position of the item to retrieve. + * @return the item at {@code position} in this buffer. + */ + public abstract T get(int position); + + public int getCount() { + return dataHolder == null ? 0 : dataHolder.getCount(); + } + + /** + * @deprecated {@link #release()} is idempotent, and so is safe to call multiple times + */ + @Deprecated + public boolean isClosed() { + return false; + } + + @Override + public Iterator iterator() { + return null; + } + + /** + * Releases resources used by the buffer. This method is idempotent. + */ + @Override + public void release() { + + } + + /** + * In order to use this one should correctly override setDataRow(int) in his DataBufferRef + * implementation. Be careful: there will be single DataBufferRef while iterating. + * If you are not sure - DO NOT USE this iterator. + */ + public Iterator singleRefIterator() { + return null; + } +} diff --git a/play-services-base/src/main/java/org/microg/gms/common/api/ApiConnection.java b/play-services-base/src/main/java/org/microg/gms/common/api/ApiConnection.java index d5697e4a..77c9af9d 100644 --- a/play-services-base/src/main/java/org/microg/gms/common/api/ApiConnection.java +++ b/play-services-base/src/main/java/org/microg/gms/common/api/ApiConnection.java @@ -17,11 +17,11 @@ package org.microg.gms.common.api; public interface ApiConnection { - public void connect(); + void connect(); - public void disconnect(); + void disconnect(); - public boolean isConnected(); + boolean isConnected(); boolean isConnecting(); } diff --git a/play-services-location/src/main/java/org/microg/gms/location/FusedLocationProviderApiImpl.java b/play-services-location/src/main/java/org/microg/gms/location/FusedLocationProviderApiImpl.java index f89a79af..08e90c5b 100644 --- a/play-services-location/src/main/java/org/microg/gms/location/FusedLocationProviderApiImpl.java +++ b/play-services-location/src/main/java/org/microg/gms/location/FusedLocationProviderApiImpl.java @@ -136,7 +136,7 @@ public class FusedLocationProviderApiImpl implements FusedLocationProviderApi { } private interface Runnable { - public void run(LocationClientImpl client) throws RemoteException; + void run(LocationClientImpl client) throws RemoteException; } } diff --git a/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataApi.java b/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataApi.java index c26bdf22..25ef04bc 100644 --- a/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataApi.java +++ b/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataApi.java @@ -16,5 +16,150 @@ package com.google.android.gms.wearable; +import android.net.Uri; +import android.os.ParcelFileDescriptor; + +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 com.google.android.gms.common.data.Freezable; + +import org.microg.gms.common.PublicApi; + +import java.io.InputStream; + +/** + * Exposes an API for components to read or write data items and assets. + *

+ * A {@link DataItem} is synchronized across all devices in an Android Wear network. It is possible + * to set data items while not connected to any nodes. Those data items will be synchronized when + * the nodes eventually come online. + *

+ * Data items are private to the application that created them, and are only accessible by that + * application on other nodes. They should generally be small in size, relying on assets for the + * transfer of larger, more persistent data objects such as images. + *

+ * Each data item is identified by a URI, accessible with {@link DataItem#getUri()}, that indicates + * the item's creator and path. Fully specified URIs follow the following format: + * {@code wear:///}, where is the node ID of the wearable node that + * created the data item, and is an application-defined path. This means that given a data + * item's URI, calling {@link Uri#getHost()} will return the creator's node ID. + *

+ * In some of the methods below (such as {@link #getDataItems(GoogleApiClient, Uri)}), it is + * possible to omit the node ID from the URI, and only leave a path. In that case, the URI may + * refer to multiple data items, since multiple nodes may create data items with the same path. + * Partially specified data item URIs follow the following format: + * {@ocde wear:/} + * Note the single / after wear:. + */ +@PublicApi public interface DataApi { + /** + * Registers a listener to receive data item changed and deleted events. This call should be + * balanced with a call to {@link #removeListener(GoogleApiClient, DataListener)}, to avoid + * leaking resources. + *

+ * The listener will be notified of changes initiated by this node. + */ + PendingResult addListener(GoogleApiClient client, DataListener listener); + + /** + * Removes all specified data items from the Android Wear network. + *

+ * If uri is fully specified, this method will delete at most one data item. If {@code uri} + * contains no host, multiple data items may be deleted, since different nodes may create data + * items with the same path. See {@link DataApi} for details of the URI format. + */ + PendingResult deleteDataItems(GoogleApiClient client, Uri uri); + + /** + * Retrieves a single {@link DataItem} from the Android Wear network. A fully qualified URI + * must be specified. The URI's host must be the ID of the node that created the item. + *

+ * See {@link DataApi} for details of the URI format. + */ + PendingResult getDataItem(GoogleApiClient client, Uri uri); + + /** + * Retrieves all data items from the Android Wear network. + *

+ * Callers must call {@link DataItemBuffer#release()} on the returned buffer when finished + * processing results. + */ + PendingResult getDataItems(GoogleApiClient client); + + /** + * Retrieves all data items matching the provided URI, from the Android Wear network. + *

+ * The URI must contain a path. If {@code uri} is fully specified, at most one data item will + * be returned. If uri contains no host, multiple data items may be returned, since different + * nodes may create data items with the same path. See {@link DataApi} for details of the URI + * format. + *

+ * Callers must call {@link DataItemBuffer#release()} on the returned buffer when finished + * processing results. + */ + PendingResult getDataItems(GoogleApiClient client, Uri uri); + + /** + * Retrieves a {@link ParcelFileDescriptor} pointing at the bytes of an asset. Only assets + * previously stored in a {@link DataItem} may be retrieved. + */ + PendingResult getFdForAsset(GoogleApiClient client, DataItemAsset asset); + + /** + * Retrieves a {@link ParcelFileDescriptor} pointing at the bytes of an asset. Only assets + * previously stored in a {@link DataItem} may be retrieved. + */ + PendingResult getFdForAsset(GoogleApiClient client, Asset asset); + + /** + * Adds a {@link DataItem} to the Android Wear network. The updated item is synchronized across + * all devices. + */ + PendingResult putDataItem(GoogleApiClient client, PutDataRequest request); + + /** + * Removes a data listener which was previously added through + * {@link #addListener(GoogleApiClient, DataListener)}. + */ + PendingResult removeListener(GoogleApiClient client, DataListener listener); + + interface DataItemResult extends Result { + /** + * @return data item, or {@code null} if the item does not exit. + */ + DataItem getDataItem(); + } + + interface DataListener { + /** + * Notification that a set of data items have been changed or deleted. The data buffer is + * released upon completion of this method. If a caller wishes to use the events outside + * this callback, they should be sure to {@link Freezable#freeze()} the DataEvent objects + * they wish to use. + */ + void onDataChanged(DataEventBuffer dataEvents); + } + + interface DeleteDataItemsResult extends Result { + /** + * @return the number of items deleted by + * {@link DataApi#deleteDataItems(GoogleApiClient, Uri)}. + */ + int getNumDeleted(); + } + + interface GetFdForAssetResult extends Result { + /** + * @return a file descriptor for the requested asset. + */ + ParcelFileDescriptor getFd(); + + /** + * @return an input stream wrapping the file descriptor. When this input stream is closed, the file descriptor is, as well. + */ + InputStream getInputStream(); + } } diff --git a/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataEvent.java b/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataEvent.java new file mode 100644 index 00000000..0d72101e --- /dev/null +++ b/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataEvent.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013-2015 µg 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.data.Freezable; + +import org.microg.gms.common.PublicApi; + +/** + * Data interface for data events. + */ +@PublicApi +public interface DataEvent extends Freezable { + + /** + * Indicates that the enclosing {@link DataEvent} was triggered by a data item being added or + * changed. + */ + int TYPE_CHANGED = 1; + + /** + * Indicates that the enclosing {@link DataEvent} was triggered by a data item being deleted. + */ + int TYPE_DELETED = 2; + + /** + * @return the data item modified in this event. An event of {@link #TYPE_DELETED} will only + * have its {@link DataItem#getUri} populated. + */ + DataItem getDataItem(); + + /** + * @return the type of event this is. One of {@link #TYPE_CHANGED}, {@link #TYPE_DELETED}. + */ + int getType(); +} diff --git a/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataEventBuffer.java b/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataEventBuffer.java new file mode 100644 index 00000000..1d4f6a45 --- /dev/null +++ b/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataEventBuffer.java @@ -0,0 +1,48 @@ +/* + * Copyright 2013-2015 µg 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.Result; +import com.google.android.gms.common.api.Status; +import com.google.android.gms.common.data.DataBuffer; +import com.google.android.gms.common.data.DataHolder; + +import org.microg.gms.common.PublicApi; + +/** + * Data structure holding references to a set of events. + */ +@PublicApi +public class DataEventBuffer extends DataBuffer implements Result { + private Status status; + + @PublicApi(exclude = true) + public DataEventBuffer(DataHolder dataHolder) { + super(dataHolder); + status = new Status(dataHolder.statusCode); + } + + @Override + public DataEvent get(int position) { + return null; + } + + @Override + public Status getStatus() { + return null; + } +} diff --git a/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataItemBuffer.java b/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataItemBuffer.java new file mode 100644 index 00000000..991b79f4 --- /dev/null +++ b/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataItemBuffer.java @@ -0,0 +1,45 @@ +/* + * Copyright 2013-2015 µg 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.Result; +import com.google.android.gms.common.api.Status; +import com.google.android.gms.common.data.DataBuffer; +import com.google.android.gms.common.data.DataHolder; + +import org.microg.gms.common.PublicApi; + +@PublicApi +public class DataItemBuffer extends DataBuffer implements Result { + private Status status; + + @PublicApi(exclude = true) + public DataItemBuffer(DataHolder dataHolder) { + super(dataHolder); + status = new Status(dataHolder.statusCode); + } + + @Override + public DataItem get(int position) { + return null; + } + + @Override + public Status getStatus() { + return null; + } +} diff --git a/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataMap.java b/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataMap.java new file mode 100644 index 00000000..aad96e14 --- /dev/null +++ b/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataMap.java @@ -0,0 +1,369 @@ +/* + * Copyright 2013-2015 µg 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.os.Bundle; + +import org.microg.gms.common.PublicApi; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * A map of data supported by {@link PutDataMapRequest} and {@link DataMapItem}s. DataMap may + * convert to and from Bundles, but will drop any types not explicitly supported by DataMap in the + * conversion process. + */ +@PublicApi +public class DataMap { + public static String TAG = "GmsDataMap"; + + private Map data = new HashMap<>(); + private Map types = new HashMap<>(); + + public DataMap() { + + } + + /** + * @return an ArrayList of DataMaps from an ArrayList of Bundles. Any elements in the Bundles not supported by DataMap will be dropped. + */ + public static ArrayList arrayListFromBundleArrayList(ArrayList bundleArrayList) { + ArrayList res = new ArrayList<>(); + for (Bundle bundle : bundleArrayList) { + res.add(fromBundle(bundle)); + } + return res; + } + + /** + * Removes all elements from the mapping of this DataMap. + */ + public void clear() { + data.clear(); + } + + /** + * @return true if the given key is contained in the mapping of this DataMap. + */ + public boolean containsKey(String key) { + return data.containsKey(key); + } + + /** + * @return true if the given Object is a DataMap equivalent to this one. + */ + @Override + public boolean equals(Object o) { + return o instanceof DataMap && data.equals(((DataMap) o).data); + } + + /** + * @return a DataMap from a Bundle. The input Bundle is expected to contain only elements + * supported by DataMap. Any elements in the Bundle not supported by DataMap will be dropped. + */ + public static DataMap fromBundle(Bundle bundle) { + DataMap res = new DataMap(); + if (bundle != null) { + for (String key : bundle.keySet()) { + res.data.put(key, bundle.get(key)); + } + } + return res; + } + + /** + * @return a DataMap from a byte[]. + */ + public static DataMap fromByteArray(byte[] bytes) { + return null; // TODO + } + + /** + * @return the entry with the given key as an object, or null + */ + public T get(String key) { + return (T) data.get(key); + } + + public Asset getAsset(String key) { + return types.get(key) == StoredType.Asset ? (Asset) data.get(key) : null; + } + + public boolean getBoolean(String key) { + return getBoolean(key, false); + } + + public boolean getBoolean(String key, boolean defaultValue) { + return types.get(key) == StoredType.Boolean ? (Boolean) data.get(key) : defaultValue; + } + + public byte getByte(String key) { + return getByte(key, (byte) 0); + } + + public byte getByte(String key, byte defaultValue) { + return types.get(key) == StoredType.Byte ? (Byte) data.get(key) : defaultValue; + } + + public byte[] getByteArray(String key) { + return types.get(key) == StoredType.ByteArray ? (byte[]) data.get(key) : null; + } + + public DataMap getDataMap(String key) { + return types.get(key) == StoredType.DataMap ? (DataMap) data.get(key) : null; + } + + public ArrayList getDataMapArrayList(String key) { + return types.get(key) == StoredType.DataMapArrayList ? (ArrayList) data.get(key) : null; + } + + public double getDouble(String key) { + return getDouble(key, 0.0); + } + + public double getDouble(String key, double defaultValue) { + return types.get(key) == StoredType.Double ? (Double) data.get(key) : defaultValue; + } + + public float getFloat(String key) { + return getFloat(key, 0.0f); + } + + public float getFloat(String key, float defaultValue) { + return types.get(key) == StoredType.Float ? (Float) data.get(key) : defaultValue; + } + + public float[] getFloatArray(String key) { + return types.get(key) == StoredType.FloatArray ? (float[]) data.get(key) : null; + } + + public int getInt(String key) { + return getInt(key, 0); + } + + public int getInt(String key, int defaultValue) { + return types.get(key) == StoredType.Integer ? (Integer) data.get(key) : defaultValue; + } + + public ArrayList getIntegerArrayList(String key) { + return types.get(key) == StoredType.IntegerArrayList ? (ArrayList) data.get(key) : null; + } + + public long getLong(String key) { + return getLong(key, 0L); + } + + public long getLong(String key, long defaultValue) { + return types.get(key) == StoredType.Long ? (Long) data.get(key) : defaultValue; + } + + public long[] getLongArray(String key) { + return types.get(key) == StoredType.LongArray ? (long[]) data.get(key) : null; + } + + public String getString(String key) { + return getString(key, null); + } + + public String getString(String key, String defaultValue) { + return types.get(key) == StoredType.String ? (String) data.get(key) : defaultValue; + } + + public String[] getStringArray(String key) { + return types.get(key) == StoredType.StringArray ? (String[]) data.get(key) : null; + } + + public ArrayList getStringArrayList(String key) { + return types.get(key) == StoredType.StringArrayList ? (ArrayList) data.get(key) : null; + } + + public int hashCode() { + return data.hashCode(); + } + + public boolean isEmpty() { + return data.isEmpty(); + } + + public Set keySet() { + return data.keySet(); + } + + public void putAll(DataMap dataMap) { + for (String key : dataMap.keySet()) { + data.put(key, dataMap.data.get(key)); + types.put(key, dataMap.types.get(key)); + } + } + + public void putBoolean(String key, boolean value) { + data.put(key, value); + types.put(key, StoredType.Boolean); + } + + public void putByte(String key, byte value) { + data.put(key, value); + types.put(key, StoredType.Byte); + } + + public void putByteArray(String key, byte[] value) { + data.put(key, value); + types.put(key, StoredType.ByteArray); + } + + public void putDataMap(String key, DataMap value) { + data.put(key, value); + types.put(key, StoredType.DataMap); + } + + public void putDataMapArrayList(String key, ArrayList value) { + data.put(key, value); + types.put(key, StoredType.DataMapArrayList); + } + + public void putDouble(String key, double value) { + data.put(key, value); + types.put(key, StoredType.Double); + } + + public void putFloat(String key, float value) { + data.put(key, value); + types.put(key, StoredType.Float); + } + + public void putFloatArray(String key, float[] value) { + data.put(key, value); + types.put(key, StoredType.FloatArray); + } + + public void putInt(String key, int value) { + data.put(key, value); + types.put(key, StoredType.Integer); + } + + public void putIntegerArrayList(String key, ArrayList value) { + data.put(key, value); + types.put(key, StoredType.IntegerArrayList); + } + + public void putLong(String key, long value) { + data.put(key, value); + types.put(key, StoredType.Long); + } + + public void putLongArray(String key, long[] value) { + data.put(key, value); + types.put(key, StoredType.LongArray); + } + + public void putString(String key, String value) { + data.put(key, value); + types.put(key, StoredType.String); + } + + public void putStringArray(String key, String[] value) { + data.put(key, value); + types.put(key, StoredType.StringArray); + } + + public void putStringArrayList(String key, ArrayList value) { + data.put(key, value); + types.put(key, StoredType.StringArrayList); + } + + public Object remove(String key) { + types.remove(key); + return data.remove(key); + } + + public int size() { + return data.size(); + } + + public Bundle toBundle() { + Bundle bundle = new Bundle(); + for (String key : data.keySet()) { + switch (types.get(key)) { + case Asset: + bundle.putParcelable(key, (Asset)data.get(key)); + break; + case Boolean: + bundle.putBoolean(key, (Boolean) data.get(key)); + break; + case Byte: + bundle.putByte(key, (Byte) data.get(key)); + break; + case ByteArray: + bundle.putByteArray(key, (byte[]) data.get(key)); + break; + case DataMap: + bundle.putBundle(key, ((DataMap) data.get(key)).toBundle()); + break; + case DataMapArrayList: + // TODO + break; + case Double: + bundle.putDouble(key, (Double) data.get(key)); + break; + case Float: + bundle.putFloat(key, (Float) data.get(key)); + break; + case FloatArray: + bundle.putFloatArray(key, (float[]) data.get(key)); + break; + case Integer: + bundle.putInt(key, (Integer) data.get(key)); + break; + case IntegerArrayList: + bundle.putIntegerArrayList(key, (ArrayList) data.get(key)); + break; + case Long: + bundle.putLong(key, (Long) data.get(key)); + break; + case LongArray: + bundle.putLongArray(key, (long[]) data.get(key)); + break; + case String: + bundle.putString(key, (String) data.get(key)); + break; + case StringArray: + bundle.putStringArray(key, (String[]) data.get(key)); + break; + case StringArrayList: + bundle.putStringArrayList(key, (ArrayList) data.get(key)); + break; + } + } + return bundle; + } + + public byte[] toByteArray() { + return null; // TODO + } + + public String toString() { + return "DataMap{size=" + size() + "}"; + } + + private enum StoredType { + Asset, Boolean, Byte, ByteArray, DataMap, DataMapArrayList, Double, Float, FloatArray, + Integer, IntegerArrayList, Long, LongArray, String, StringArray, StringArrayList + } +} diff --git a/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataMapItem.java b/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataMapItem.java new file mode 100644 index 00000000..7eb6fb0f --- /dev/null +++ b/play-services-wearable/src/main/java/com/google/android/gms/wearable/DataMapItem.java @@ -0,0 +1,45 @@ +/* + * Copyright 2013-2015 µg 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 org.microg.gms.common.PublicApi; + +/** + * Creates a new dataItem-like object containing structured and serializable data. + */ +@PublicApi +public class DataMapItem { + /** + * Provides a {@link DataMapItem} wrapping a dataItem. + * + * @param dataItem the base for the wrapped {@link DataMapItem}. {@code dataItem} should not + * be modified after wrapping it. + */ + public static DataMapItem fromDataItem(DataItem dataItem) { + return null; + } + + public DataMap getDataMap() { + return null; + } + + public Uri getUri() { + return null; + } +} diff --git a/play-services-wearable/src/main/java/com/google/android/gms/wearable/MessageApi.java b/play-services-wearable/src/main/java/com/google/android/gms/wearable/MessageApi.java index 730ebe4a..999d615f 100644 --- a/play-services-wearable/src/main/java/com/google/android/gms/wearable/MessageApi.java +++ b/play-services-wearable/src/main/java/com/google/android/gms/wearable/MessageApi.java @@ -16,5 +16,73 @@ 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. + *

+ * Callers wishing to be notified of events in the background should use {@link WearableListenerService}. + */ + PendingResult addListener(GoogleApiClient client, MessageListener listener); + + /** + * Removes a message listener which was previously added through + * {@link #addListener(GoogleApiClient, MessageListener)}. + */ + PendingResult 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 sendMessage(GoogleApiClient client, String nodeId, + String path, byte[] data); + + /** + * Used with {@link MessageApi#addListener(GoogleApiClient, MessageListener)} to receive + * message events. + *

+ * 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(); + } } diff --git a/play-services-wearable/src/main/java/com/google/android/gms/wearable/MessageEvent.java b/play-services-wearable/src/main/java/com/google/android/gms/wearable/MessageEvent.java new file mode 100644 index 00000000..c5dd0d33 --- /dev/null +++ b/play-services-wearable/src/main/java/com/google/android/gms/wearable/MessageEvent.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013-2015 µg 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 org.microg.gms.common.PublicApi; + +@PublicApi +public interface MessageEvent { + /** + * @return the data passed by the message. + */ + byte[] getData(); + + /** + * @return the path the message is being delivered to + */ + String getPath(); + + /** + * @return the request id of the message, generated by the sender + */ + int getRequestId(); + + /** + * @return the node ID of the sender. + */ + String getSourceNodeId(); +} diff --git a/play-services-wearable/src/main/java/com/google/android/gms/wearable/NodeApi.java b/play-services-wearable/src/main/java/com/google/android/gms/wearable/NodeApi.java index 4aa57284..86088446 100644 --- a/play-services-wearable/src/main/java/com/google/android/gms/wearable/NodeApi.java +++ b/play-services-wearable/src/main/java/com/google/android/gms/wearable/NodeApi.java @@ -16,5 +16,83 @@ 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; + +import java.util.List; + +/** + * Exposes an API for to learn about local or connected Nodes. + *

+ * Node events are delivered to all applications on a device. + */ +@PublicApi public interface NodeApi { + + /** + * Registers a listener to receive all node events. Calls to this method should balanced with + * {@link #removeListener(GoogleApiClient, NodeListener)}, to avoid leaking resources. + *

+ * Callers wishing to be notified of node events in the background should use WearableListenerService. + */ + PendingResult addListener(GoogleApiClient client, NodeListener listener); + + /** + * Gets a list of nodes to which this device is currently connected. + *

+ * The returned list will not include the {@link #getLocalNode(GoogleApiClient) local node}. + */ + PendingResult getConnectedNodes(GoogleApiClient client); + + /** + * Gets the {@link Node} that refers to this device. The information in the returned Node + * can be passed to other devices using the {@link MessageApi}, for example. + */ + PendingResult getLocalNode(GoogleApiClient client); + + /** + * Removes a listener which was previously added through + * {@link #addListener(GoogleApiClient, NodeListener)}. + */ + PendingResult removeListener(GoogleApiClient client, NodeListener listener); + + + /** + * Contains a list of connected nodes. + */ + interface GetConnectedNodesResult extends Result { + /** + * @return a list of connected nodes. This list doesn't include the local node. + */ + List getNodes(); + } + + /** + * Contains the name and id that represents this device. + */ + interface GetLocalNodeResult extends Result { + /** + * @return a {@link Node} object which represents this device. + */ + Node getNode(); + } + + /** + * Used with {@link NodeApi#addListener(GoogleApiClient, NodeListener)} to receive node events. + */ + interface NodeListener { + /** + * Notification that a peer has been connected. + */ + void onPeerConnected(Node peer); + + /** + * Notification that a peer has been disconnected. + */ + void onPeerDisconnected(Node peer); + } } diff --git a/play-services-wearable/src/main/java/com/google/android/gms/wearable/PutDataMapRequest.java b/play-services-wearable/src/main/java/com/google/android/gms/wearable/PutDataMapRequest.java new file mode 100644 index 00000000..f70e3c6c --- /dev/null +++ b/play-services-wearable/src/main/java/com/google/android/gms/wearable/PutDataMapRequest.java @@ -0,0 +1,83 @@ +/* + * Copyright 2013-2015 µg 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 org.microg.gms.common.PublicApi; + +/** + * PutDataMapRequest is a DataMap-aware version of {@link PutDataRequest}. + */ +@PublicApi +public class PutDataMapRequest { + + private DataMapItem dataMapItem; + + private PutDataMapRequest(DataMapItem dataMapItem) { + this.dataMapItem = dataMapItem; + } + + /** + * Creates a {@link PutDataRequest} containing the data and assets in this + * {@link PutDataMapRequest}. + */ + public PutDataRequest asPutDataRequest() { + // TODO + return new PutDataRequest(); + } + + /** + * Creates a {@link PutDataMapRequest} with the provided, complete, path. + */ + public static PutDataMapRequest create(String path) { + // TODO + return new PutDataMapRequest(null); + } + + /** + * Creates a {@link PutDataMapRequest} from a {@link DataMapItem} using the provided source. + */ + public static PutDataMapRequest createFromDataMapItem(DataMapItem source) { + return new PutDataMapRequest(source); + } + + /** + * Creates a {@link PutDataMapRequest} with a randomly generated id prefixed with the provided + * path. + */ + public static PutDataMapRequest createWithAutoAppendedId(String pathPrefix) { + // TODO + return new PutDataMapRequest(null); + } + + /** + * @return the structured data associated with this data item. + */ + public DataMap getDataMap() { + return dataMapItem.getDataMap(); + } + + /** + * @return a {@link Uri} for the pending data item. If this is a modification of an existing + * data item, {@link Uri#getHost()} will return the id of the node that originally created it. + * Otherwise, a new data item will be created with the requesting device's node. + */ + public Uri getUri() { + return dataMapItem.getUri(); + } +} diff --git a/play-services-wearable/src/main/java/com/google/android/gms/wearable/WearableListenerService.java b/play-services-wearable/src/main/java/com/google/android/gms/wearable/WearableListenerService.java new file mode 100644 index 00000000..61a552d0 --- /dev/null +++ b/play-services-wearable/src/main/java/com/google/android/gms/wearable/WearableListenerService.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013-2015 µg 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.app.Service; +import android.content.Intent; +import android.os.IBinder; + +public abstract class WearableListenerService extends Service implements DataApi.DataListener, MessageApi.MessageListener, NodeApi.NodeListener { + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public void onCreate() { + super.onCreate(); + } + + @Override + public void onDataChanged(DataEventBuffer dataEvents) { + + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + @Override + public void onMessageReceived(MessageEvent messageEvent) { + + } + + @Override + public void onPeerConnected(Node peer) { + + } + + @Override + public void onPeerDisconnected(Node peer) { + + } +} diff --git a/play-services-wearable/src/main/java/org/microg/gms/wearable/DataApiImpl.java b/play-services-wearable/src/main/java/org/microg/gms/wearable/DataApiImpl.java index 5d8f07ec..bdfa778e 100644 --- a/play-services-wearable/src/main/java/org/microg/gms/wearable/DataApiImpl.java +++ b/play-services-wearable/src/main/java/org/microg/gms/wearable/DataApiImpl.java @@ -16,7 +16,60 @@ package org.microg.gms.wearable; +import android.net.Uri; + +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.Asset; import com.google.android.gms.wearable.DataApi; +import com.google.android.gms.wearable.DataItemAsset; +import com.google.android.gms.wearable.DataItemBuffer; +import com.google.android.gms.wearable.PutDataRequest; public class DataApiImpl implements DataApi { + @Override + public PendingResult addListener(GoogleApiClient client, DataListener listener) { + return null; + } + + @Override + public PendingResult deleteDataItems(GoogleApiClient client, Uri uri) { + return null; + } + + @Override + public PendingResult getDataItem(GoogleApiClient client, Uri uri) { + return null; + } + + @Override + public PendingResult getDataItems(GoogleApiClient client) { + return null; + } + + @Override + public PendingResult getDataItems(GoogleApiClient client, Uri uri) { + return null; + } + + @Override + public PendingResult getFdForAsset(GoogleApiClient client, DataItemAsset asset) { + return null; + } + + @Override + public PendingResult getFdForAsset(GoogleApiClient client, Asset asset) { + return null; + } + + @Override + public PendingResult putDataItem(GoogleApiClient client, PutDataRequest request) { + return null; + } + + @Override + public PendingResult removeListener(GoogleApiClient client, DataListener listener) { + return null; + } } diff --git a/play-services-wearable/src/main/java/org/microg/gms/wearable/MessageApiImpl.java b/play-services-wearable/src/main/java/org/microg/gms/wearable/MessageApiImpl.java index 6f055d5e..667eaa77 100644 --- a/play-services-wearable/src/main/java/org/microg/gms/wearable/MessageApiImpl.java +++ b/play-services-wearable/src/main/java/org/microg/gms/wearable/MessageApiImpl.java @@ -16,7 +16,24 @@ package org.microg.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.Status; import com.google.android.gms.wearable.MessageApi; public class MessageApiImpl implements MessageApi { + @Override + public PendingResult addListener(GoogleApiClient client, MessageListener listener) { + return null; + } + + @Override + public PendingResult removeListener(GoogleApiClient client, MessageListener listener) { + return null; + } + + @Override + public PendingResult sendMessage(GoogleApiClient client, String nodeId, String path, byte[] data) { + return null; + } } diff --git a/play-services-wearable/src/main/java/org/microg/gms/wearable/NodeApiImpl.java b/play-services-wearable/src/main/java/org/microg/gms/wearable/NodeApiImpl.java index bf8bf5ed..2aca31ee 100644 --- a/play-services-wearable/src/main/java/org/microg/gms/wearable/NodeApiImpl.java +++ b/play-services-wearable/src/main/java/org/microg/gms/wearable/NodeApiImpl.java @@ -16,7 +16,29 @@ package org.microg.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.Status; import com.google.android.gms.wearable.NodeApi; public class NodeApiImpl implements NodeApi { + @Override + public PendingResult addListener(GoogleApiClient client, NodeListener listener) { + return null; + } + + @Override + public PendingResult getConnectedNodes(GoogleApiClient client) { + return null; + } + + @Override + public PendingResult getLocalNode(GoogleApiClient client) { + return null; + } + + @Override + public PendingResult removeListener(GoogleApiClient client, NodeListener listener) { + return null; + } }