From 4889d0e44eafac5cfae46a2c2ad429d37d3b21c2 Mon Sep 17 00:00:00 2001 From: patloew Date: Sat, 29 Oct 2016 23:31:27 +0200 Subject: [PATCH] RxWear methods are now non-static for better testability. Dependency updates. Use Retrolambda to simplify code. Refactoring. --- .travis.yml | 9 +- build.gradle | 12 +- gradle/wrapper/gradle-wrapper.properties | 2 +- library/build.gradle | 34 +- .../com/patloew/rxwear/BaseObservable.java | 14 +- .../main/java/com/patloew/rxwear/BaseRx.java | 8 +- .../java/com/patloew/rxwear/BaseSingle.java | 14 +- .../java/com/patloew/rxwear/Capability.java | 113 +++ .../rxwear/CapabilityAddLocalSingle.java | 19 +- .../rxwear/CapabilityGetAllSingle.java | 19 +- .../patloew/rxwear/CapabilityGetSingle.java | 19 +- .../rxwear/CapabilityListenerObservable.java | 19 +- .../rxwear/CapabilityRemoveLocalSingle.java | 19 +- .../main/java/com/patloew/rxwear/Channel.java | 158 +++ .../patloew/rxwear/ChannelCloseSingle.java | 5 +- .../rxwear/ChannelGetInputStreamSingle.java | 19 +- .../rxwear/ChannelGetOutputStreamSingle.java | 19 +- .../rxwear/ChannelListenerObservable.java | 26 +- .../com/patloew/rxwear/ChannelOpenSingle.java | 28 +- .../rxwear/ChannelReceiveFileSingle.java | 7 +- .../patloew/rxwear/ChannelSendFileSingle.java | 5 +- .../main/java/com/patloew/rxwear/Data.java | 428 ++++++++ .../patloew/rxwear/DataDeleteItemsSingle.java | 14 +- .../rxwear/DataGetFdForAssetSingle.java | 15 +- .../com/patloew/rxwear/DataGetItemSingle.java | 19 +- .../rxwear/DataGetItemsObservable.java | 34 +- .../rxwear/DataListenerObservable.java | 22 +- .../com/patloew/rxwear/DataPutItemSingle.java | 19 +- .../main/java/com/patloew/rxwear/IOUtil.java | 47 + .../main/java/com/patloew/rxwear/Message.java | 263 +++++ .../rxwear/MessageListenerObservable.java | 19 +- .../com/patloew/rxwear/MessageSendSingle.java | 19 +- .../main/java/com/patloew/rxwear/Node.java | 78 ++ .../rxwear/NodeGetConnectedSingle.java | 20 +- .../patloew/rxwear/NodeGetLocalSingle.java | 20 +- .../rxwear/NodeListenerObservable.java | 13 +- .../main/java/com/patloew/rxwear/RxWear.java | 945 +----------------- .../patloew/rxwear/SingleResultCallBack.java | 50 + ...ck.java => StatusErrorResultCallBack.java} | 10 +- .../com/patloew/rxwear/StatusException.java | 3 +- .../transformers/DataEventGetDataMap.java | 32 +- .../DataEventGetSerializable.java | 40 +- .../transformers/DataItemGetDataMap.java | 21 +- .../transformers/DataItemGetSerializable.java | 32 +- .../transformers/MessageEventGetDataMap.java | 21 +- .../MessageEventGetSerializable.java | 32 +- .../java/com/patloew/rxwear/RxWearTest.java | 115 +-- sample/build.gradle | 20 +- .../patloew/rxwearsample/MainActivity.java | 24 +- wearsample/build.gradle | 16 +- .../patloew/rxwearsample/MainActivity.java | 12 +- 51 files changed, 1467 insertions(+), 1504 deletions(-) create mode 100644 library/src/main/java/com/patloew/rxwear/Capability.java create mode 100644 library/src/main/java/com/patloew/rxwear/Channel.java create mode 100644 library/src/main/java/com/patloew/rxwear/Data.java create mode 100644 library/src/main/java/com/patloew/rxwear/IOUtil.java create mode 100644 library/src/main/java/com/patloew/rxwear/Message.java create mode 100644 library/src/main/java/com/patloew/rxwear/Node.java create mode 100644 library/src/main/java/com/patloew/rxwear/SingleResultCallBack.java rename library/src/main/java/com/patloew/rxwear/{StatusResultCallBack.java => StatusErrorResultCallBack.java} (76%) diff --git a/.travis.yml b/.travis.yml index 6d5f6c4..8853c2e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,10 +9,10 @@ android: - tools # The BuildTools version used by your project - - build-tools-23.0.2 + - build-tools-25.0.0 # The SDK version used to compile your project - - android-23 + - android-25 # Additional components - extra-google-google_play_services @@ -23,8 +23,13 @@ android: before_install: - export JAVA8_HOME=/usr/lib/jvm/java-8-oracle - export JAVA_HOME=$JAVA8_HOME +after_success: + - bash <(curl -s https://codecov.io/bash) before_cache: - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock +script: + - ./gradlew build jacocoTestReport assembleAndroidTest + - ./gradlew connectedCheck cache: directories: - $HOME/.gradle/caches/ diff --git a/build.gradle b/build.gradle index e1e1231..0276507 100644 --- a/build.gradle +++ b/build.gradle @@ -5,20 +5,18 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.0' + classpath 'com.android.tools.build:gradle:2.2.2' - classpath 'me.tatarka:gradle-retrolambda:3.3.0-beta4' - classpath 'me.tatarka.retrolambda.projectlombok:lombok.ast:0.2.3.a2' + classpath 'me.tatarka:gradle-retrolambda:3.3.1' - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.6' - classpath "com.github.dcendents:android-maven-gradle-plugin:1.3" + classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.1' + classpath "com.github.dcendents:android-maven-gradle-plugin:1.5" + classpath 'com.dicedmelon.gradle:jacoco-android:0.1.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } - - configurations.classpath.exclude group: 'com.android.tools.external.lombok' } allprojects { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d0574d2..5642922 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.1-all.zip diff --git a/library/build.gradle b/library/build.gradle index 28659d4..41f067c 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -1,20 +1,22 @@ apply plugin: 'com.android.library' +apply plugin: 'me.tatarka.retrolambda' +apply plugin: 'jacoco-android' apply plugin: 'com.jfrog.bintray' apply plugin: 'com.github.dcendents.android-maven' group = 'com.patloew.rxwear' -version = '1.2.0' +version = '1.3.0' project.archivesBaseName = 'rxwear' android { - compileSdkVersion 23 - buildToolsVersion "23.0.2" + compileSdkVersion 25 + buildToolsVersion "25.0.0" defaultConfig { minSdkVersion 9 - targetSdkVersion 23 - versionCode 3 - versionName "1.2.0" + targetSdkVersion 25 + versionCode 4 + versionName "1.3.0" } buildTypes { release { @@ -22,21 +24,31 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } testOptions { unitTests.returnDefaultValues = true } + lintOptions { + abortOnError false + } +} + +retrolambda { + javaVersion JavaVersion.VERSION_1_6 } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'io.reactivex:rxjava:1.1.5' - compile 'com.google.android.gms:play-services-wearable:8.4.0' + compile 'io.reactivex:rxjava:1.2.1' + compile 'com.google.android.gms:play-services-wearable:9.8.0' testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:1.10.19' - testCompile "org.powermock:powermock-module-junit4:1.6.4" - testCompile "org.powermock:powermock-module-junit4-rule:1.6.4" - testCompile "org.powermock:powermock-api-mockito:1.6.4" + testCompile "org.powermock:powermock-module-junit4:1.6.5" + testCompile "org.powermock:powermock-api-mockito:1.6.5" } task generateSourcesJar(type: Jar) { diff --git a/library/src/main/java/com/patloew/rxwear/BaseObservable.java b/library/src/main/java/com/patloew/rxwear/BaseObservable.java index 3bf96f3..5ecca8d 100644 --- a/library/src/main/java/com/patloew/rxwear/BaseObservable.java +++ b/library/src/main/java/com/patloew/rxwear/BaseObservable.java @@ -10,7 +10,6 @@ import rx.Observable; import rx.Subscriber; -import rx.functions.Action0; import rx.subscriptions.Subscriptions; /* Copyright (C) 2015 Michał Charmas (http://blog.charmas.pl) @@ -32,7 +31,7 @@ * FILE MODIFIED by Patrick Löwenstein, 2016 * */ -public abstract class BaseObservable extends BaseRx implements Observable.OnSubscribe { +abstract class BaseObservable extends BaseRx implements Observable.OnSubscribe { protected BaseObservable(@NonNull RxWear rxWear, Long timeout, TimeUnit timeUnit) { super(rxWear, timeout, timeUnit); @@ -48,13 +47,10 @@ public final void call(Subscriber subscriber) { subscriber.onError(ex); } - subscriber.add(Subscriptions.create(new Action0() { - @Override - public void call() { - if (apiClient.isConnected() || apiClient.isConnecting()) { - onUnsubscribed(apiClient); - apiClient.disconnect(); - } + subscriber.add(Subscriptions.create(() -> { + if (apiClient.isConnected() || apiClient.isConnecting()) { + onUnsubscribed(apiClient); + apiClient.disconnect(); } })); } diff --git a/library/src/main/java/com/patloew/rxwear/BaseRx.java b/library/src/main/java/com/patloew/rxwear/BaseRx.java index b4547b0..aecef51 100644 --- a/library/src/main/java/com/patloew/rxwear/BaseRx.java +++ b/library/src/main/java/com/patloew/rxwear/BaseRx.java @@ -32,7 +32,7 @@ * FILE MODIFIED by Patrick Löwenstein, 2016 * */ -public abstract class BaseRx { +abstract class BaseRx { private final Context ctx; private final Api[] services; private final Scope[] scopes; @@ -40,7 +40,7 @@ public abstract class BaseRx { private final TimeUnit timeoutUnit; protected BaseRx(@NonNull RxWear rxWear, Long timeout, TimeUnit timeUnit) { - this.ctx = rxWear.getContext(); + this.ctx = rxWear.ctx; this.services = new Api[] {Wearable.API }; this.scopes = null; @@ -48,8 +48,8 @@ protected BaseRx(@NonNull RxWear rxWear, Long timeout, TimeUnit timeUnit) { this.timeoutTime = timeout; this.timeoutUnit = timeUnit; } else { - this.timeoutTime = RxWear.getDefaultTimeout(); - this.timeoutUnit = RxWear.getDefaultTimeoutUnit(); + this.timeoutTime = rxWear.timeoutTime; + this.timeoutUnit = rxWear.timeoutUnit; } } diff --git a/library/src/main/java/com/patloew/rxwear/BaseSingle.java b/library/src/main/java/com/patloew/rxwear/BaseSingle.java index dad0717..225331c 100644 --- a/library/src/main/java/com/patloew/rxwear/BaseSingle.java +++ b/library/src/main/java/com/patloew/rxwear/BaseSingle.java @@ -13,7 +13,6 @@ import rx.Single; import rx.SingleSubscriber; -import rx.functions.Action0; import rx.subscriptions.Subscriptions; /* Copyright (C) 2015 Michał Charmas (http://blog.charmas.pl) @@ -35,7 +34,7 @@ * FILE MODIFIED by Patrick Löwenstein, 2016 * */ -public abstract class BaseSingle extends BaseRx implements Single.OnSubscribe { +abstract class BaseSingle extends BaseRx implements Single.OnSubscribe { protected BaseSingle(@NonNull RxWear rxWear, Long timeout, TimeUnit timeUnit) { super(rxWear, timeout, timeUnit); @@ -55,13 +54,10 @@ public final void call(SingleSubscriber subscriber) { subscriber.onError(ex); } - subscriber.add(Subscriptions.create(new Action0() { - @Override - public void call() { - if (apiClient.isConnected() || apiClient.isConnecting()) { - onUnsubscribed(apiClient); - apiClient.disconnect(); - } + subscriber.add(Subscriptions.create(() -> { + if (apiClient.isConnected() || apiClient.isConnecting()) { + onUnsubscribed(apiClient); + apiClient.disconnect(); } })); } diff --git a/library/src/main/java/com/patloew/rxwear/Capability.java b/library/src/main/java/com/patloew/rxwear/Capability.java new file mode 100644 index 0000000..24c099f --- /dev/null +++ b/library/src/main/java/com/patloew/rxwear/Capability.java @@ -0,0 +1,113 @@ +package com.patloew.rxwear; + +import android.net.Uri; +import android.support.annotation.NonNull; + +import com.google.android.gms.common.api.Status; +import com.google.android.gms.wearable.CapabilityInfo; + +import java.util.concurrent.TimeUnit; + +import rx.Observable; +import rx.Single; + +/* Copyright 2016 Patrick Löwenstein + * + * 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. */ +public class Capability { + + private final RxWear rxWear; + + Capability(RxWear rxWear) { + this.rxWear = rxWear; + } + + // listen + + public Observable listen(@NonNull String capability) { + return listenInternal(capability, null, null, null, null); + } + + public Observable listen(@NonNull String capability, long timeout, @NonNull TimeUnit timeUnit) { + return listenInternal(capability, null, null, timeout, timeUnit); + } + + public Observable listen(@NonNull Uri uri, int filterType) { + return listenInternal(null, uri, filterType, null, null); + } + + public Observable listen(@NonNull Uri uri, int filterType, long timeout, @NonNull TimeUnit timeUnit) { + return listenInternal(null, uri, filterType, timeout, timeUnit); + } + + private Observable listenInternal(String capability, Uri uri, Integer filterType, Long timeout, TimeUnit timeUnit) { + return Observable.create(new CapabilityListenerObservable(rxWear, capability, uri, filterType, timeout, timeUnit)); + } + + // getAll + + public Observable getAll(int nodeFilter) { + return getAllInternal(nodeFilter, null, null); + } + + public Observable getAll(int nodeFilter, long timeout, @NonNull TimeUnit timeUnit) { + return getAllInternal(nodeFilter, timeout, timeUnit); + } + + private Observable getAllInternal(int nodeFilter, Long timeout, TimeUnit timeUnit) { + return Single.create(new CapabilityGetAllSingle(rxWear, nodeFilter, timeout, timeUnit)) + .flatMapObservable(capabilityInfoMap -> Observable.from(capabilityInfoMap.values())); + } + + // get + + public Single get(@NonNull String capability, int nodeFilter) { + return getInternal(capability, nodeFilter, null, null); + } + + public Single get(@NonNull String capability, int nodeFilter, long timeout, @NonNull TimeUnit timeUnit) { + return getInternal(capability, nodeFilter, timeout, timeUnit); + } + + private Single getInternal(String capability, int nodeFilter, Long timeout, TimeUnit timeUnit) { + return Single.create(new CapabilityGetSingle(rxWear, capability, nodeFilter, timeout, timeUnit)); + } + + // addLocal + + public Single addLocal(@NonNull String capability) { + return addLocalInternal(capability, null, null); + } + + public Single addLocal(@NonNull String capability, long timeout, @NonNull TimeUnit timeUnit) { + return addLocalInternal(capability, timeout, timeUnit); + } + + private Single addLocalInternal(String capability, Long timeout, TimeUnit timeUnit) { + return Single.create(new CapabilityAddLocalSingle(rxWear, capability, timeout, timeUnit)); + } + + // removeLocal + + public Single removeLocal(@NonNull String capability) { + return removeLocalInternal(capability, null, null); + } + + public Single removeLocal(@NonNull String capability, long timeout, @NonNull TimeUnit timeUnit) { + return removeLocalInternal(capability, timeout, timeUnit); + } + + private Single removeLocalInternal(String capability, Long timeout, TimeUnit timeUnit) { + return Single.create(new CapabilityRemoveLocalSingle(rxWear, capability, timeout, timeUnit)); + } +} diff --git a/library/src/main/java/com/patloew/rxwear/CapabilityAddLocalSingle.java b/library/src/main/java/com/patloew/rxwear/CapabilityAddLocalSingle.java index 07c2213..87cb4d8 100644 --- a/library/src/main/java/com/patloew/rxwear/CapabilityAddLocalSingle.java +++ b/library/src/main/java/com/patloew/rxwear/CapabilityAddLocalSingle.java @@ -1,9 +1,6 @@ package com.patloew.rxwear; -import android.support.annotation.NonNull; - import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.common.api.Status; import com.google.android.gms.wearable.CapabilityApi; import com.google.android.gms.wearable.Wearable; @@ -25,7 +22,7 @@ * 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. */ -public class CapabilityAddLocalSingle extends BaseSingle { +class CapabilityAddLocalSingle extends BaseSingle { private final String capability; @@ -36,15 +33,9 @@ public class CapabilityAddLocalSingle extends BaseSingle { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final SingleSubscriber subscriber) { - setupWearPendingResult(Wearable.CapabilityApi.addLocalCapability(apiClient, capability), new ResultCallback() { - @Override - public void onResult(@NonNull CapabilityApi.AddLocalCapabilityResult addLocalCapabilityResult) { - if (!addLocalCapabilityResult.getStatus().isSuccess()) { - subscriber.onError(new StatusException(addLocalCapabilityResult.getStatus())); - } else { - subscriber.onSuccess(addLocalCapabilityResult.getStatus()); - } - } - }); + setupWearPendingResult( + Wearable.CapabilityApi.addLocalCapability(apiClient, capability), + SingleResultCallBack.get(subscriber, CapabilityApi.AddLocalCapabilityResult::getStatus) + ); } } diff --git a/library/src/main/java/com/patloew/rxwear/CapabilityGetAllSingle.java b/library/src/main/java/com/patloew/rxwear/CapabilityGetAllSingle.java index d2ba98a..b666d44 100644 --- a/library/src/main/java/com/patloew/rxwear/CapabilityGetAllSingle.java +++ b/library/src/main/java/com/patloew/rxwear/CapabilityGetAllSingle.java @@ -1,9 +1,6 @@ package com.patloew.rxwear; -import android.support.annotation.NonNull; - import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.wearable.CapabilityApi; import com.google.android.gms.wearable.CapabilityInfo; import com.google.android.gms.wearable.Wearable; @@ -26,7 +23,7 @@ * 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. */ -public class CapabilityGetAllSingle extends BaseSingle> { +class CapabilityGetAllSingle extends BaseSingle> { private final int nodeFilter; @@ -37,15 +34,9 @@ public class CapabilityGetAllSingle extends BaseSingle> subscriber) { - setupWearPendingResult(Wearable.CapabilityApi.getAllCapabilities(apiClient, nodeFilter), new ResultCallback() { - @Override - public void onResult(@NonNull CapabilityApi.GetAllCapabilitiesResult getAllCapabilitiesResult) { - if (!getAllCapabilitiesResult.getStatus().isSuccess()) { - subscriber.onError(new StatusException(getAllCapabilitiesResult.getStatus())); - } else { - subscriber.onSuccess(getAllCapabilitiesResult.getAllCapabilities()); - } - } - }); + setupWearPendingResult( + Wearable.CapabilityApi.getAllCapabilities(apiClient, nodeFilter), + SingleResultCallBack.get(subscriber, CapabilityApi.GetAllCapabilitiesResult::getAllCapabilities) + ); } } diff --git a/library/src/main/java/com/patloew/rxwear/CapabilityGetSingle.java b/library/src/main/java/com/patloew/rxwear/CapabilityGetSingle.java index c1d7b36..e0618e3 100644 --- a/library/src/main/java/com/patloew/rxwear/CapabilityGetSingle.java +++ b/library/src/main/java/com/patloew/rxwear/CapabilityGetSingle.java @@ -1,9 +1,6 @@ package com.patloew.rxwear; -import android.support.annotation.NonNull; - import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.wearable.CapabilityApi; import com.google.android.gms.wearable.CapabilityInfo; import com.google.android.gms.wearable.Wearable; @@ -25,7 +22,7 @@ * 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. */ -public class CapabilityGetSingle extends BaseSingle { +class CapabilityGetSingle extends BaseSingle { private final String capability; private final int nodeFilter; @@ -38,15 +35,9 @@ public class CapabilityGetSingle extends BaseSingle { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final SingleSubscriber subscriber) { - setupWearPendingResult(Wearable.CapabilityApi.getCapability(apiClient, capability, nodeFilter), new ResultCallback() { - @Override - public void onResult(@NonNull CapabilityApi.GetCapabilityResult getCapabilitiesResult) { - if (!getCapabilitiesResult.getStatus().isSuccess()) { - subscriber.onError(new StatusException(getCapabilitiesResult.getStatus())); - } else { - subscriber.onSuccess(getCapabilitiesResult.getCapability()); - } - } - }); + setupWearPendingResult( + Wearable.CapabilityApi.getCapability(apiClient, capability, nodeFilter), + SingleResultCallBack.get(subscriber, CapabilityApi.GetCapabilityResult::getCapability) + ); } } diff --git a/library/src/main/java/com/patloew/rxwear/CapabilityListenerObservable.java b/library/src/main/java/com/patloew/rxwear/CapabilityListenerObservable.java index 88e8b03..ae6cf9a 100644 --- a/library/src/main/java/com/patloew/rxwear/CapabilityListenerObservable.java +++ b/library/src/main/java/com/patloew/rxwear/CapabilityListenerObservable.java @@ -1,7 +1,6 @@ package com.patloew.rxwear; import android.net.Uri; -import android.support.annotation.NonNull; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.ResultCallback; @@ -27,7 +26,7 @@ * 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. */ -public class CapabilityListenerObservable extends BaseObservable { +class CapabilityListenerObservable extends BaseObservable { private final String capability; private final Uri uri; @@ -44,21 +43,9 @@ public class CapabilityListenerObservable extends BaseObservable @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final Subscriber subscriber) { - listener = new CapabilityApi.CapabilityListener() { - @Override - public void onCapabilityChanged(CapabilityInfo capabilityInfo) { - subscriber.onNext(capabilityInfo); - } - }; + listener = subscriber::onNext; - ResultCallback resultCallback = new ResultCallback() { - @Override - public void onResult(@NonNull Status status) { - if (!status.isSuccess()) { - subscriber.onError(new StatusException(status)); - } - } - }; + ResultCallback resultCallback = new StatusErrorResultCallBack(subscriber); if(capability != null) { setupWearPendingResult(Wearable.CapabilityApi.addCapabilityListener(apiClient, listener, capability), resultCallback); diff --git a/library/src/main/java/com/patloew/rxwear/CapabilityRemoveLocalSingle.java b/library/src/main/java/com/patloew/rxwear/CapabilityRemoveLocalSingle.java index 12c35ff..bdd8b76 100644 --- a/library/src/main/java/com/patloew/rxwear/CapabilityRemoveLocalSingle.java +++ b/library/src/main/java/com/patloew/rxwear/CapabilityRemoveLocalSingle.java @@ -1,9 +1,6 @@ package com.patloew.rxwear; -import android.support.annotation.NonNull; - import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.common.api.Status; import com.google.android.gms.wearable.CapabilityApi; import com.google.android.gms.wearable.Wearable; @@ -25,7 +22,7 @@ * 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. */ -public class CapabilityRemoveLocalSingle extends BaseSingle { +class CapabilityRemoveLocalSingle extends BaseSingle { private final String capability; @@ -36,15 +33,9 @@ public class CapabilityRemoveLocalSingle extends BaseSingle { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final SingleSubscriber subscriber) { - setupWearPendingResult(Wearable.CapabilityApi.removeLocalCapability(apiClient, capability), new ResultCallback() { - @Override - public void onResult(@NonNull CapabilityApi.RemoveLocalCapabilityResult removeLocalCapabilityResult) { - if (!removeLocalCapabilityResult.getStatus().isSuccess()) { - subscriber.onError(new StatusException(removeLocalCapabilityResult.getStatus())); - } else { - subscriber.onSuccess(removeLocalCapabilityResult.getStatus()); - } - } - }); + setupWearPendingResult( + Wearable.CapabilityApi.removeLocalCapability(apiClient, capability), + SingleResultCallBack.get(subscriber, CapabilityApi.RemoveLocalCapabilityResult::getStatus) + ); } } diff --git a/library/src/main/java/com/patloew/rxwear/Channel.java b/library/src/main/java/com/patloew/rxwear/Channel.java new file mode 100644 index 0000000..c2731b5 --- /dev/null +++ b/library/src/main/java/com/patloew/rxwear/Channel.java @@ -0,0 +1,158 @@ +package com.patloew.rxwear; + +import android.net.Uri; +import android.support.annotation.NonNull; + +import com.google.android.gms.common.api.Status; +import com.patloew.rxwear.events.ChannelEvent; + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.concurrent.TimeUnit; + +import rx.Observable; +import rx.Single; + +/* Copyright 2016 Patrick Löwenstein + * + * 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. */ +public class Channel { + + private final RxWear rxWear; + + Channel(RxWear rxWear) { + this.rxWear = rxWear; + } + + // listen + + public Observable listen() { + return listenInternal(null, null, null); + } + + public Observable listen(long timeout, @NonNull TimeUnit timeUnit) { + return listenInternal(null, timeout, timeUnit); + } + + public Observable listen(@NonNull com.google.android.gms.wearable.Channel channel) { + return listenInternal(channel, null, null); + } + + public Observable listen(@NonNull com.google.android.gms.wearable.Channel channel, long timeout, @NonNull TimeUnit timeUnit) { + return listenInternal(channel, timeout, timeUnit); + } + + private Observable listenInternal(com.google.android.gms.wearable.Channel channel, Long timeout, TimeUnit timeUnit) { + return Observable.create(new ChannelListenerObservable(rxWear, channel, timeout, timeUnit)); + } + + // close + + public Single close(@NonNull com.google.android.gms.wearable.Channel channel) { + return closeInternal(channel, null, null, null); + } + + public Single close(@NonNull com.google.android.gms.wearable.Channel channel, long timeout, @NonNull TimeUnit timeUnit) { + return closeInternal(channel, null, timeout, timeUnit); + } + + public Single close(@NonNull com.google.android.gms.wearable.Channel channel, int errorCode) { + return closeInternal(channel, errorCode, null, null); + } + + public Single close(@NonNull com.google.android.gms.wearable.Channel channel, int errorCode, long timeout, @NonNull TimeUnit timeUnit) { + return closeInternal(channel, errorCode, timeout, timeUnit); + } + + private Single closeInternal(com.google.android.gms.wearable.Channel channel, Integer errorCode, Long timeout, TimeUnit timeUnit) { + return Single.create(new ChannelCloseSingle(rxWear, channel, errorCode, timeout, timeUnit)); + } + + // sendFile + + public Single sendFile(@NonNull com.google.android.gms.wearable.Channel channel, @NonNull Uri uri) { + return sendFileInternal(channel, uri, null, null, null, null); + } + + public Single sendFile(@NonNull com.google.android.gms.wearable.Channel channel, @NonNull Uri uri, long timeout, @NonNull TimeUnit timeUnit) { + return sendFileInternal(channel, uri, null, null, timeout, timeUnit); + } + + public Single sendFile(@NonNull com.google.android.gms.wearable.Channel channel, @NonNull Uri uri, long startOffset, long length) { + return sendFileInternal(channel, uri, startOffset, length, null, null); + } + + public Single sendFile(@NonNull com.google.android.gms.wearable.Channel channel, @NonNull Uri uri, long startOffset, long length, long timeout, @NonNull TimeUnit timeUnit) { + return sendFileInternal(channel, uri, startOffset, length, timeout, timeUnit); + } + + private Single sendFileInternal(com.google.android.gms.wearable.Channel channel, Uri uri, Long startOffset, Long length, Long timeout, TimeUnit timeUnit) { + return Single.create(new ChannelSendFileSingle(rxWear, channel, uri, startOffset, length, timeout, timeUnit)); + } + + // receiveFile + + public Single receiveFile(@NonNull com.google.android.gms.wearable.Channel channel, @NonNull Uri uri, boolean append) { + return receiveFileInternal(channel, uri, append, null, null); + } + + public Single receiveFile(@NonNull com.google.android.gms.wearable.Channel channel, @NonNull Uri uri, boolean append, long timeout, @NonNull TimeUnit timeUnit) { + return receiveFileInternal(channel, uri, append, timeout, timeUnit); + } + + private Single receiveFileInternal(com.google.android.gms.wearable.Channel channel, Uri uri, boolean append, Long timeout, TimeUnit timeUnit) { + return Single.create(new ChannelReceiveFileSingle(rxWear, channel, uri, append, timeout, timeUnit)); + } + + // getInputStream + + public Single getInputStream(@NonNull com.google.android.gms.wearable.Channel channel) { + return getInputStreamInternal(channel, null, null); + } + + public Single getInputStream(@NonNull com.google.android.gms.wearable.Channel channel, long timeout, @NonNull TimeUnit timeUnit) { + return getInputStreamInternal(channel, timeout, timeUnit); + } + + private Single getInputStreamInternal(com.google.android.gms.wearable.Channel channel, Long timeout, TimeUnit timeUnit) { + return Single.create(new ChannelGetInputStreamSingle(rxWear, channel, timeout, timeUnit)); + } + + // getOutputStream + + public Single getOutputStream(@NonNull com.google.android.gms.wearable.Channel channel) { + return getOutputStreamInternal(channel, null, null); + } + + public Single getOutputStream(@NonNull com.google.android.gms.wearable.Channel channel, long timeout, @NonNull TimeUnit timeUnit) { + return getOutputStreamInternal(channel, timeout, timeUnit); + } + + private Single getOutputStreamInternal(com.google.android.gms.wearable.Channel channel, Long timeout, TimeUnit timeUnit) { + return Single.create(new ChannelGetOutputStreamSingle(rxWear, channel, timeout, timeUnit)); + } + + // open + + public Single open(@NonNull String nodeId, @NonNull String path) { + return openInternal(nodeId, path, null, null); + } + + public Single open(@NonNull String nodeId, @NonNull String path, long timeout, @NonNull TimeUnit timeUnit) { + return openInternal(nodeId, path, timeout, timeUnit); + } + + private Single openInternal(String nodeId, String path, Long timeout, TimeUnit timeUnit) { + return Single.create(new ChannelOpenSingle(rxWear, nodeId, path, timeout, timeUnit)); + } +} diff --git a/library/src/main/java/com/patloew/rxwear/ChannelCloseSingle.java b/library/src/main/java/com/patloew/rxwear/ChannelCloseSingle.java index 11e0e8e..c75a686 100644 --- a/library/src/main/java/com/patloew/rxwear/ChannelCloseSingle.java +++ b/library/src/main/java/com/patloew/rxwear/ChannelCloseSingle.java @@ -1,6 +1,7 @@ package com.patloew.rxwear; import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.common.api.Status; import com.google.android.gms.wearable.Channel; @@ -21,7 +22,7 @@ * 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. */ -public class ChannelCloseSingle extends BaseSingle { +class ChannelCloseSingle extends BaseSingle { private final Channel channel; private final Integer errorCode; @@ -34,7 +35,7 @@ public class ChannelCloseSingle extends BaseSingle { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final SingleSubscriber subscriber) { - StatusResultCallBack resultCallBack = new StatusResultCallBack(subscriber); + ResultCallback resultCallBack = SingleResultCallBack.get(subscriber); if(errorCode != null) { setupWearPendingResult(channel.close(apiClient, errorCode), resultCallBack); diff --git a/library/src/main/java/com/patloew/rxwear/ChannelGetInputStreamSingle.java b/library/src/main/java/com/patloew/rxwear/ChannelGetInputStreamSingle.java index f039e17..f869d94 100644 --- a/library/src/main/java/com/patloew/rxwear/ChannelGetInputStreamSingle.java +++ b/library/src/main/java/com/patloew/rxwear/ChannelGetInputStreamSingle.java @@ -1,9 +1,6 @@ package com.patloew.rxwear; -import android.support.annotation.NonNull; - import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.wearable.Channel; import java.io.InputStream; @@ -24,7 +21,7 @@ * 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. */ -public class ChannelGetInputStreamSingle extends BaseSingle { +class ChannelGetInputStreamSingle extends BaseSingle { private final Channel channel; @@ -35,15 +32,9 @@ public class ChannelGetInputStreamSingle extends BaseSingle { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final SingleSubscriber subscriber) { - setupWearPendingResult(channel.getInputStream(apiClient), new ResultCallback() { - @Override - public void onResult(@NonNull Channel.GetInputStreamResult getInputStreamResult) { - if (!getInputStreamResult.getStatus().isSuccess()) { - subscriber.onError(new StatusException(getInputStreamResult.getStatus())); - } else { - subscriber.onSuccess(getInputStreamResult.getInputStream()); - } - } - }); + setupWearPendingResult( + channel.getInputStream(apiClient), + SingleResultCallBack.get(subscriber, Channel.GetInputStreamResult::getInputStream) + ); } } diff --git a/library/src/main/java/com/patloew/rxwear/ChannelGetOutputStreamSingle.java b/library/src/main/java/com/patloew/rxwear/ChannelGetOutputStreamSingle.java index 679d847..25ba1ce 100644 --- a/library/src/main/java/com/patloew/rxwear/ChannelGetOutputStreamSingle.java +++ b/library/src/main/java/com/patloew/rxwear/ChannelGetOutputStreamSingle.java @@ -1,9 +1,6 @@ package com.patloew.rxwear; -import android.support.annotation.NonNull; - import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.wearable.Channel; import java.io.OutputStream; @@ -24,7 +21,7 @@ * 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. */ -public class ChannelGetOutputStreamSingle extends BaseSingle { +class ChannelGetOutputStreamSingle extends BaseSingle { private final Channel channel; @@ -35,15 +32,9 @@ public class ChannelGetOutputStreamSingle extends BaseSingle { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final SingleSubscriber subscriber) { - setupWearPendingResult(channel.getOutputStream(apiClient), new ResultCallback() { - @Override - public void onResult(@NonNull Channel.GetOutputStreamResult getOutputStreamResult) { - if (!getOutputStreamResult.getStatus().isSuccess()) { - subscriber.onError(new StatusException(getOutputStreamResult.getStatus())); - } else { - subscriber.onSuccess(getOutputStreamResult.getOutputStream()); - } - } - }); + setupWearPendingResult( + channel.getOutputStream(apiClient), + SingleResultCallBack.get(subscriber, Channel.GetOutputStreamResult::getOutputStream) + ); } } diff --git a/library/src/main/java/com/patloew/rxwear/ChannelListenerObservable.java b/library/src/main/java/com/patloew/rxwear/ChannelListenerObservable.java index 9df0729..b710780 100644 --- a/library/src/main/java/com/patloew/rxwear/ChannelListenerObservable.java +++ b/library/src/main/java/com/patloew/rxwear/ChannelListenerObservable.java @@ -1,7 +1,5 @@ package com.patloew.rxwear; -import android.support.annotation.NonNull; - import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.common.api.Status; @@ -31,7 +29,7 @@ * 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. */ -public class ChannelListenerObservable extends BaseObservable { +class ChannelListenerObservable extends BaseObservable { private final Channel channel; private ChannelApi.ChannelListener listener; @@ -44,36 +42,24 @@ public class ChannelListenerObservable extends BaseObservable { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final Subscriber subscriber) { listener = new ChannelApi.ChannelListener() { - - @Override - public void onChannelOpened(Channel channel) { + @Override public void onChannelOpened(Channel channel) { subscriber.onNext(new ChannelOpenedEvent(channel)); } - @Override - public void onChannelClosed(Channel channel, int closeReason, int appSpecificErrorCode) { + @Override public void onChannelClosed(Channel channel, int closeReason, int appSpecificErrorCode) { subscriber.onNext(new ChannelClosedEvent(channel, closeReason, appSpecificErrorCode)); } - @Override - public void onInputClosed(Channel channel, int closeReason, int appSpecificErrorCode) { + @Override public void onInputClosed(Channel channel, int closeReason, int appSpecificErrorCode) { subscriber.onNext(new InputClosedEvent(channel, closeReason, appSpecificErrorCode)); } - @Override - public void onOutputClosed(Channel channel, int closeReason, int appSpecificErrorCode) { + @Override public void onOutputClosed(Channel channel, int closeReason, int appSpecificErrorCode) { subscriber.onNext(new OutputClosedEvent(channel, closeReason, appSpecificErrorCode)); } }; - ResultCallback resultCallback = new ResultCallback() { - @Override - public void onResult(@NonNull Status status) { - if (!status.isSuccess()) { - subscriber.onError(new StatusException(status)); - } - } - }; + ResultCallback resultCallback = new StatusErrorResultCallBack(subscriber); if(channel != null) { setupWearPendingResult(channel.addListener(apiClient, listener), resultCallback); diff --git a/library/src/main/java/com/patloew/rxwear/ChannelOpenSingle.java b/library/src/main/java/com/patloew/rxwear/ChannelOpenSingle.java index 97821d6..5c21750 100644 --- a/library/src/main/java/com/patloew/rxwear/ChannelOpenSingle.java +++ b/library/src/main/java/com/patloew/rxwear/ChannelOpenSingle.java @@ -1,11 +1,7 @@ package com.patloew.rxwear; -import android.support.annotation.NonNull; - import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.wearable.Channel; -import com.google.android.gms.wearable.ChannelApi; import com.google.android.gms.wearable.Wearable; import java.io.IOException; @@ -26,7 +22,7 @@ * 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. */ -public class ChannelOpenSingle extends BaseSingle { +class ChannelOpenSingle extends BaseSingle { private final String nodeId; private final String path; @@ -39,19 +35,19 @@ public class ChannelOpenSingle extends BaseSingle { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final SingleSubscriber subscriber) { - setupWearPendingResult(Wearable.ChannelApi.openChannel(apiClient, nodeId, path), new ResultCallback() { - @Override - public void onResult(@NonNull ChannelApi.OpenChannelResult openChannelResult) { - if (!openChannelResult.getStatus().isSuccess()) { - subscriber.onError(new StatusException(openChannelResult.getStatus())); - } else { - if(openChannelResult.getChannel() != null) { - subscriber.onSuccess(openChannelResult.getChannel()); + setupWearPendingResult( + Wearable.ChannelApi.openChannel(apiClient, nodeId, path), + openChannelResult -> { + if (!openChannelResult.getStatus().isSuccess()) { + subscriber.onError(new StatusException(openChannelResult.getStatus())); } else { - subscriber.onError(new IOException("Channel connection could not be opened")); + if(openChannelResult.getChannel() != null) { + subscriber.onSuccess(openChannelResult.getChannel()); + } else { + subscriber.onError(new IOException("Channel connection could not be opened")); + } } } - } - }); + ); } } diff --git a/library/src/main/java/com/patloew/rxwear/ChannelReceiveFileSingle.java b/library/src/main/java/com/patloew/rxwear/ChannelReceiveFileSingle.java index 6d5ca9c..fc2524e 100644 --- a/library/src/main/java/com/patloew/rxwear/ChannelReceiveFileSingle.java +++ b/library/src/main/java/com/patloew/rxwear/ChannelReceiveFileSingle.java @@ -23,7 +23,7 @@ * 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. */ -public class ChannelReceiveFileSingle extends BaseSingle { +class ChannelReceiveFileSingle extends BaseSingle { private final Channel channel; private final Uri uri; @@ -38,6 +38,9 @@ public class ChannelReceiveFileSingle extends BaseSingle { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final SingleSubscriber subscriber) { - setupWearPendingResult(channel.receiveFile(apiClient, uri, append), new StatusResultCallBack(subscriber)); + setupWearPendingResult( + channel.receiveFile(apiClient, uri, append), + SingleResultCallBack.get(subscriber) + ); } } diff --git a/library/src/main/java/com/patloew/rxwear/ChannelSendFileSingle.java b/library/src/main/java/com/patloew/rxwear/ChannelSendFileSingle.java index f84ef2e..93af703 100644 --- a/library/src/main/java/com/patloew/rxwear/ChannelSendFileSingle.java +++ b/library/src/main/java/com/patloew/rxwear/ChannelSendFileSingle.java @@ -3,6 +3,7 @@ import android.net.Uri; import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.common.api.Status; import com.google.android.gms.wearable.Channel; @@ -23,7 +24,7 @@ * 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. */ -public class ChannelSendFileSingle extends BaseSingle { +class ChannelSendFileSingle extends BaseSingle { private final Channel channel; private final Uri uri; @@ -40,7 +41,7 @@ public class ChannelSendFileSingle extends BaseSingle { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final SingleSubscriber subscriber) { - StatusResultCallBack resultCallBack = new StatusResultCallBack(subscriber); + ResultCallback resultCallBack = SingleResultCallBack.get(subscriber); if(startOffset != null && length != null) { setupWearPendingResult(channel.sendFile(apiClient, uri, startOffset, length), resultCallBack); diff --git a/library/src/main/java/com/patloew/rxwear/Data.java b/library/src/main/java/com/patloew/rxwear/Data.java new file mode 100644 index 0000000..8ba4061 --- /dev/null +++ b/library/src/main/java/com/patloew/rxwear/Data.java @@ -0,0 +1,428 @@ +package com.patloew.rxwear; + +import android.net.Uri; +import android.support.annotation.NonNull; + +import com.google.android.gms.wearable.Asset; +import com.google.android.gms.wearable.DataApi; +import com.google.android.gms.wearable.DataEvent; +import com.google.android.gms.wearable.DataItem; +import com.google.android.gms.wearable.DataItemAsset; +import com.google.android.gms.wearable.DataMap; +import com.google.android.gms.wearable.DataMapItem; +import com.google.android.gms.wearable.PutDataMapRequest; +import com.google.android.gms.wearable.PutDataRequest; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.concurrent.TimeUnit; + +import rx.Observable; +import rx.Single; + +import static com.patloew.rxwear.IOUtil.closeSilently; + +/* Copyright 2016 Patrick Löwenstein + * + * 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. */ +public class Data { + + private final RxWear rxWear; + + Data(RxWear rxWear) { + this.rxWear = rxWear; + } + + // listen + + public Observable listen() { + return listenInternal(null, null, null, null); + } + + public Observable listen(long timeout, @NonNull TimeUnit timeUnit) { + return listenInternal(null, null, timeout, timeUnit); + } + + public Observable listen(@NonNull Uri uri, int filterType) { + return listenInternal(uri, filterType, null, null); + } + + public Observable listen(@NonNull Uri uri, int filterType, long timeout, @NonNull TimeUnit timeUnit) { + return listenInternal(uri, filterType, timeout, timeUnit); + } + + public Observable listen(@NonNull String path, int filterType) { + return listenInternal(new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).path(path).build(), filterType, null, null); + } + + public Observable listen(@NonNull String path, int filterType, long timeout, @NonNull TimeUnit timeUnit) { + return listenInternal(new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).path(path).build(), filterType, timeout, timeUnit); + } + + private Observable listenInternal(Uri uri, Integer filterType, Long timeout, TimeUnit timeUnit) { + return Observable.create(new DataListenerObservable(rxWear, uri, filterType, timeout, timeUnit)); + } + + // delete + + public Single delete(@NonNull Uri uri) { + return deleteInternal(uri, null, null, null); + } + + public Single delete(@NonNull Uri uri, @NonNull Long timeout, @NonNull TimeUnit timeUnit) { + return deleteInternal(uri, null, timeout, timeUnit); + } + + public Single delete(@NonNull Uri uri, int filterType) { + return deleteInternal(uri, filterType, null, null); + } + + public Single delete(@NonNull Uri uri, int filterType, long timeout, @NonNull TimeUnit timeUnit) { + return deleteInternal(uri, filterType, timeout, timeUnit); + } + + private Single deleteInternal(Uri uri, Integer filterType, Long timeout, TimeUnit timeUnit) { + return Single.create(new DataDeleteItemsSingle(rxWear, uri, filterType, timeout, timeUnit)); + } + + // put + + public Single put(@NonNull PutDataRequest putDataRequest) { + return putInternal(putDataRequest, null, null); + } + + public Single put(@NonNull PutDataRequest putDataRequest, long timeout, @NonNull TimeUnit timeUnit) { + return putInternal(putDataRequest, timeout, timeUnit); + } + + public Single put(@NonNull PutDataMapRequest putDataMapRequest) { + return putInternal(putDataMapRequest.asPutDataRequest(), null, null); + } + + public Single put(@NonNull PutDataMapRequest putDataMapRequest, long timeout, @NonNull TimeUnit timeUnit) { + return putInternal(putDataMapRequest.asPutDataRequest(), timeout, timeUnit); + } + + private Single putInternal(PutDataRequest putDataRequest, Long timeout, TimeUnit timeUnit) { + return Single.create(new DataPutItemSingle(rxWear, putDataRequest, timeout, timeUnit)); + } + + + // getSingle + + @Deprecated + // use get() instead + public Single getSingle(@NonNull Uri uri) { + return getSingleInternal(uri, null, null); + } + + @Deprecated + // use get() instead + public Single getSingle(@NonNull Uri uri, long timeout, @NonNull TimeUnit timeUnit) { + return getSingleInternal(uri, timeout, timeUnit); + } + + private Single getSingleInternal(Uri uri, Long timeout, TimeUnit timeUnit) { + return Single.create(new DataGetItemSingle(rxWear, uri, timeout, timeUnit)); + } + + // get + + public Observable get(@NonNull Uri uri, int filterType) { + return getInternal(uri, filterType, null, null); + } + + public Observable get(@NonNull Uri uri, int filterType, long timeout, @NonNull TimeUnit timeUnit) { + return getInternal(uri, filterType, timeout, timeUnit); + } + + public Observable get(@NonNull String path, int filterType) { + return getInternal(new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).path(path).build(), filterType, null, null); + } + + public Observable get(@NonNull String path, int filterType, long timeout, @NonNull TimeUnit timeUnit) { + return getInternal(new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).path(path).build(), filterType, timeout, timeUnit); + } + + public Observable get(@NonNull Uri uri) { + return getInternal(uri, null, null, null); + } + + public Observable get(@NonNull Uri uri, long timeout, @NonNull TimeUnit timeUnit) { + return getInternal(uri, null, timeout, timeUnit); + } + + public Observable get(@NonNull String path) { + return getInternal(new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).path(path).build(), null, null, null); + } + + public Observable get(@NonNull String path, long timeout, @NonNull TimeUnit timeUnit) { + return getInternal(new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).path(path).build(), null, timeout, timeUnit); + } + + public Observable get() { + return getInternal(null, null, null, null); + } + + public Observable get(long timeout, @NonNull TimeUnit timeUnit) { + return getInternal(null, null, timeout, timeUnit); + } + + private Observable getInternal(Uri uri, Integer filterType, Long timeout, TimeUnit timeUnit) { + return Observable.create(new DataGetItemsObservable(rxWear, uri, filterType, timeout, timeUnit)); + } + + // getFdForAsset + + public Single getFdForAsset(@NonNull DataItemAsset dataItemAsset) { + return getFdForAssetInternal(dataItemAsset, null, null, null); + } + + public Single getFdForAsset(@NonNull DataItemAsset dataItemAsset, long timeout, @NonNull TimeUnit timeUnit) { + return getFdForAssetInternal(dataItemAsset, null, timeout, timeUnit); + } + + public Single getFdForAsset(@NonNull Asset asset) { + return getFdForAssetInternal(null, asset, null, null); + } + + public Single getFdForAsset(@NonNull Asset asset, long timeout, @NonNull TimeUnit timeUnit) { + return getFdForAssetInternal(null, asset, timeout, timeUnit); + } + + private Single getFdForAssetInternal(DataItemAsset dataItemAsset, Asset asset, Long timeout, TimeUnit timeUnit) { + return Single.create(new DataGetFdForAssetSingle(rxWear, dataItemAsset, asset, timeout, timeUnit)); + } + + + // Helper + + public PutDataMap putDataMap() { + return new PutDataMap(); + } + + public PutSerializable putSerializable(Serializable serializable) { + return new PutSerializable(serializable); + } + + + /* A helper class for putting a Serializable. + * + * Example: + * rxWear.data().putSerializable(serializable).urgent().to("/path") + * .subscribe(dataItem -> { + * // do something + * }); + */ + public class PutSerializable { + + private final Serializable serializable; + private boolean urgent = false; + + PutSerializable(Serializable serializable) { + this.serializable = serializable; + } + + public PutSerializable urgent() { + urgent = true; + return this; + } + + public Single withDataItem(DataItem dataItem) { + PutDataRequest request = PutDataRequest.createFromDataItem(dataItem); + if(urgent) { request.setUrgent(); } + return createPutSerializableSingle(request); + } + + public Single withAutoAppendedId(String pathPrefix) { + PutDataRequest request = PutDataRequest.createWithAutoAppendedId(pathPrefix); + if(urgent) { request.setUrgent(); } + return createPutSerializableSingle(request); + } + + public Single to(String path) { + PutDataRequest request = PutDataRequest.create(path); + if(urgent) { request.setUrgent(); } + return createPutSerializableSingle(request); + } + + private Single createPutSerializableSingle(PutDataRequest request) { + ObjectOutputStream oos = null; + + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + oos = new ObjectOutputStream(baos); + oos.writeObject(serializable); + oos.flush(); + request.setData(baos.toByteArray()); + return putInternal(request, null, null); + + } catch(IOException e) { + return Single.error(e); + + } finally { + closeSilently(oos); + } + } + } + + /* A helper class with a fluent interface for putting a DataItem + * based on a DataMap. + * + * Example: + * rxWear.data().putDataMap().urgent().to("/path") + * .putString("key", "value") + * .putInt("key", 0) + * .toSingle() + * .subscribe(dataItem -> { + * // do something + * }); + */ + public class PutDataMap { + + PutDataMap() { } + + private boolean urgent = false; + + public PutDataMap urgent() { + urgent = true; + return this; + } + + public RxFitPutDataMapRequest withDataMapItem(DataMapItem source) { + return new RxFitPutDataMapRequest(null, source, null, urgent); + } + + public RxFitPutDataMapRequest withAutoAppendedId(String pathPrefix) { + return new RxFitPutDataMapRequest( null, null, pathPrefix, urgent); + } + + public RxFitPutDataMapRequest to(String path) { + return new RxFitPutDataMapRequest(path, null, null, urgent); + } + } + + + public class RxFitPutDataMapRequest { + private final PutDataMapRequest request; + + private RxFitPutDataMapRequest(String path, DataMapItem dataMapItem, String pathPrefix, boolean urgent) { + if(path != null) { + request = PutDataMapRequest.create(path); + } else if(dataMapItem != null) { + request = PutDataMapRequest.createFromDataMapItem(dataMapItem); + } else { + request = PutDataMapRequest.createWithAutoAppendedId(pathPrefix); + } + + if(urgent) { request.setUrgent(); } + } + + public RxFitPutDataMapRequest putAll(DataMap dataMap) { + request.getDataMap().putAll(dataMap); + return this; + } + + public RxFitPutDataMapRequest putBoolean(String key, boolean value) { + request.getDataMap().putBoolean(key, value); + return this; + } + + public RxFitPutDataMapRequest putByte(String key, byte value) { + request.getDataMap().putByte(key, value); + return this; + } + + public RxFitPutDataMapRequest putInt(String key, int value) { + request.getDataMap().putInt(key, value); + return this; + } + + public RxFitPutDataMapRequest putLong(String key, long value) { + request.getDataMap().putLong(key, value); + return this; + } + + public RxFitPutDataMapRequest putFloat(String key, float value) { + request.getDataMap().putFloat(key, value); + return this; + } + + public RxFitPutDataMapRequest putDouble(String key, double value) { + request.getDataMap().putDouble(key, value); + return this; + } + + public RxFitPutDataMapRequest putString(String key, String value) { + request.getDataMap().putString(key, value); + return this; + } + + public RxFitPutDataMapRequest putAsset(String key, Asset value) { + request.getDataMap().putAsset(key, value); + return this; + } + + public RxFitPutDataMapRequest putDataMap(String key, DataMap value) { + request.getDataMap().putDataMap(key, value); + return this; + } + + public RxFitPutDataMapRequest putDataMapArrayList(String key, ArrayList value) { + request.getDataMap().putDataMapArrayList(key, value); + return this; + } + + public RxFitPutDataMapRequest putIntegerArrayList(String key, ArrayList value) { + request.getDataMap().putIntegerArrayList(key, value); + return this; + } + + public RxFitPutDataMapRequest putStringArrayList(String key, ArrayList value) { + request.getDataMap().putStringArrayList(key, value); + return this; + } + + public RxFitPutDataMapRequest putByteArray(String key, byte[] value) { + request.getDataMap().putByteArray(key, value); + return this; + } + + public RxFitPutDataMapRequest putLongArray(String key, long[] value) { + request.getDataMap().putLongArray(key, value); + return this; + } + + public RxFitPutDataMapRequest putFloatArray(String key, float[] value) { + request.getDataMap().putFloatArray(key, value); + return this; + } + + public RxFitPutDataMapRequest putStringArray(String key, String[] value) { + request.getDataMap().putStringArray(key, value); + return this; + } + + public Single toSingle() { + return putInternal(request.asPutDataRequest(), null, null); + } + + public Observable toObservable() { + return putInternal(request.asPutDataRequest(), null, null).toObservable(); + } + } + +} diff --git a/library/src/main/java/com/patloew/rxwear/DataDeleteItemsSingle.java b/library/src/main/java/com/patloew/rxwear/DataDeleteItemsSingle.java index 047037f..537f769 100644 --- a/library/src/main/java/com/patloew/rxwear/DataDeleteItemsSingle.java +++ b/library/src/main/java/com/patloew/rxwear/DataDeleteItemsSingle.java @@ -1,7 +1,6 @@ package com.patloew.rxwear; import android.net.Uri; -import android.support.annotation.NonNull; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.ResultCallback; @@ -25,7 +24,7 @@ * 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. */ -public class DataDeleteItemsSingle extends BaseSingle { +class DataDeleteItemsSingle extends BaseSingle { private final Uri uri; private final Integer filterType; @@ -38,16 +37,7 @@ public class DataDeleteItemsSingle extends BaseSingle { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final SingleSubscriber subscriber) { - ResultCallback resultResultCallback = new ResultCallback() { - @Override - public void onResult(@NonNull DataApi.DeleteDataItemsResult deleteDataItemsResult) { - if (!deleteDataItemsResult.getStatus().isSuccess()) { - subscriber.onError(new StatusException(deleteDataItemsResult.getStatus())); - } else { - subscriber.onSuccess(deleteDataItemsResult.getNumDeleted()); - } - } - }; + ResultCallback resultResultCallback = SingleResultCallBack.get(subscriber, DataApi.DeleteDataItemsResult::getNumDeleted); if(filterType == null) { setupWearPendingResult(Wearable.DataApi.deleteDataItems(apiClient, uri), resultResultCallback); diff --git a/library/src/main/java/com/patloew/rxwear/DataGetFdForAssetSingle.java b/library/src/main/java/com/patloew/rxwear/DataGetFdForAssetSingle.java index 6f3de1d..25f3eff 100644 --- a/library/src/main/java/com/patloew/rxwear/DataGetFdForAssetSingle.java +++ b/library/src/main/java/com/patloew/rxwear/DataGetFdForAssetSingle.java @@ -1,7 +1,5 @@ package com.patloew.rxwear; -import android.support.annotation.NonNull; - import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.wearable.Asset; @@ -26,7 +24,7 @@ * 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. */ -public class DataGetFdForAssetSingle extends BaseSingle { +class DataGetFdForAssetSingle extends BaseSingle { private final DataItemAsset dataItemAsset; private final Asset asset; @@ -39,16 +37,7 @@ public class DataGetFdForAssetSingle extends BaseSingle subscriber) { - ResultCallback resultCallback = new ResultCallback() { - @Override - public void onResult(@NonNull DataApi.GetFdForAssetResult getFdForAssetResult) { - if (!getFdForAssetResult.getStatus().isSuccess()) { - subscriber.onError(new StatusException(getFdForAssetResult.getStatus())); - } else { - subscriber.onSuccess(getFdForAssetResult); - } - } - }; + ResultCallback resultCallback = SingleResultCallBack.get(subscriber); if(asset != null) { setupWearPendingResult(Wearable.DataApi.getFdForAsset(apiClient, asset), resultCallback); diff --git a/library/src/main/java/com/patloew/rxwear/DataGetItemSingle.java b/library/src/main/java/com/patloew/rxwear/DataGetItemSingle.java index aa935e8..02a393f 100644 --- a/library/src/main/java/com/patloew/rxwear/DataGetItemSingle.java +++ b/library/src/main/java/com/patloew/rxwear/DataGetItemSingle.java @@ -1,11 +1,8 @@ package com.patloew.rxwear; import android.net.Uri; -import android.support.annotation.NonNull; import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.common.api.ResultCallback; -import com.google.android.gms.wearable.DataApi; import com.google.android.gms.wearable.DataItem; import com.google.android.gms.wearable.Wearable; @@ -26,7 +23,7 @@ * 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. */ -public class DataGetItemSingle extends BaseSingle { +class DataGetItemSingle extends BaseSingle { private final Uri uri; @@ -37,15 +34,9 @@ public class DataGetItemSingle extends BaseSingle { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final SingleSubscriber subscriber) { - setupWearPendingResult(Wearable.DataApi.getDataItem(apiClient, uri), new ResultCallback() { - @Override - public void onResult(@NonNull DataApi.DataItemResult dataItemResult) { - if (!dataItemResult.getStatus().isSuccess()) { - subscriber.onError(new StatusException(dataItemResult.getStatus())); - } else { - subscriber.onSuccess(dataItemResult.getDataItem().freeze()); - } - } - }); + setupWearPendingResult( + Wearable.DataApi.getDataItem(apiClient, uri), + SingleResultCallBack.get(subscriber, dataItemResult -> dataItemResult.getDataItem().freeze()) + ); } } diff --git a/library/src/main/java/com/patloew/rxwear/DataGetItemsObservable.java b/library/src/main/java/com/patloew/rxwear/DataGetItemsObservable.java index ed399f1..9f1a7c6 100644 --- a/library/src/main/java/com/patloew/rxwear/DataGetItemsObservable.java +++ b/library/src/main/java/com/patloew/rxwear/DataGetItemsObservable.java @@ -1,7 +1,6 @@ package com.patloew.rxwear; import android.net.Uri; -import android.support.annotation.NonNull; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.ResultCallback; @@ -26,7 +25,7 @@ * 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. */ -public class DataGetItemsObservable extends BaseObservable { +class DataGetItemsObservable extends BaseObservable { private final Uri uri; private final Integer filterType; @@ -39,25 +38,22 @@ public class DataGetItemsObservable extends BaseObservable { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final Subscriber subscriber) { - ResultCallback resultCallback = new ResultCallback() { - @Override - public void onResult(@NonNull DataItemBuffer dataItemBuffer) { - try { - if(!dataItemBuffer.getStatus().isSuccess()) { - subscriber.onError(new StatusException(dataItemBuffer.getStatus())); - } else { - for (int i = 0; i < dataItemBuffer.getCount(); i++) { - if(subscriber.isUnsubscribed()) { break; } - subscriber.onNext(dataItemBuffer.get(i).freeze()); - } - - subscriber.onCompleted(); + ResultCallback resultCallback = dataItemBuffer -> { + try { + if(!dataItemBuffer.getStatus().isSuccess()) { + subscriber.onError(new StatusException(dataItemBuffer.getStatus())); + } else { + for (int i = 0; i < dataItemBuffer.getCount(); i++) { + if(subscriber.isUnsubscribed()) { break; } + subscriber.onNext(dataItemBuffer.get(i).freeze()); } - } catch(Throwable throwable) { - subscriber.onError(throwable); - } finally { - dataItemBuffer.release(); + + subscriber.onCompleted(); } + } catch(Throwable throwable) { + subscriber.onError(throwable); + } finally { + dataItemBuffer.release(); } }; diff --git a/library/src/main/java/com/patloew/rxwear/DataListenerObservable.java b/library/src/main/java/com/patloew/rxwear/DataListenerObservable.java index 51e6ec3..b1c8711 100644 --- a/library/src/main/java/com/patloew/rxwear/DataListenerObservable.java +++ b/library/src/main/java/com/patloew/rxwear/DataListenerObservable.java @@ -1,14 +1,12 @@ package com.patloew.rxwear; import android.net.Uri; -import android.support.annotation.NonNull; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.common.api.Status; import com.google.android.gms.wearable.DataApi; import com.google.android.gms.wearable.DataEvent; -import com.google.android.gms.wearable.DataEventBuffer; import com.google.android.gms.wearable.Wearable; import java.util.concurrent.TimeUnit; @@ -28,7 +26,7 @@ * 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. */ -public class DataListenerObservable extends BaseObservable { +class DataListenerObservable extends BaseObservable { private final Uri uri; private final Integer filterType; @@ -43,23 +41,13 @@ public class DataListenerObservable extends BaseObservable { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final Subscriber subscriber) { - listener = new DataApi.DataListener() { - @Override - public void onDataChanged(DataEventBuffer dataEventBuffer) { - for(int i=0; i { + for(int i=0; i resultCallback = new ResultCallback() { - @Override - public void onResult(@NonNull Status status) { - if (!status.isSuccess()) { - subscriber.onError(new StatusException(status)); - } - } - }; + ResultCallback resultCallback = new StatusErrorResultCallBack(subscriber); if(uri != null && filterType != null) { setupWearPendingResult(Wearable.DataApi.addListener(apiClient, listener, uri, filterType), resultCallback); diff --git a/library/src/main/java/com/patloew/rxwear/DataPutItemSingle.java b/library/src/main/java/com/patloew/rxwear/DataPutItemSingle.java index 527e0ec..1d6088f 100644 --- a/library/src/main/java/com/patloew/rxwear/DataPutItemSingle.java +++ b/library/src/main/java/com/patloew/rxwear/DataPutItemSingle.java @@ -1,9 +1,6 @@ package com.patloew.rxwear; -import android.support.annotation.NonNull; - import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.wearable.DataApi; import com.google.android.gms.wearable.DataItem; import com.google.android.gms.wearable.PutDataRequest; @@ -26,7 +23,7 @@ * 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. */ -public class DataPutItemSingle extends BaseSingle { +class DataPutItemSingle extends BaseSingle { private final PutDataRequest putDataRequest; @@ -37,15 +34,9 @@ public class DataPutItemSingle extends BaseSingle { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final SingleSubscriber subscriber) { - setupWearPendingResult(Wearable.DataApi.putDataItem(apiClient, putDataRequest), new ResultCallback() { - @Override - public void onResult(@NonNull DataApi.DataItemResult dataItemResult) { - if (!dataItemResult.getStatus().isSuccess()) { - subscriber.onError(new StatusException(dataItemResult.getStatus())); - } else { - subscriber.onSuccess(dataItemResult.getDataItem()); - } - } - }); + setupWearPendingResult( + Wearable.DataApi.putDataItem(apiClient, putDataRequest), + SingleResultCallBack.get(subscriber, DataApi.DataItemResult::getDataItem) + ); } } diff --git a/library/src/main/java/com/patloew/rxwear/IOUtil.java b/library/src/main/java/com/patloew/rxwear/IOUtil.java new file mode 100644 index 0000000..ad89e75 --- /dev/null +++ b/library/src/main/java/com/patloew/rxwear/IOUtil.java @@ -0,0 +1,47 @@ +package com.patloew.rxwear; + +import java.io.ByteArrayInputStream; +import java.io.Closeable; +import java.io.IOException; +import java.io.ObjectInputStream; + +import rx.exceptions.Exceptions; + +/* Copyright 2016 Patrick Löwenstein + * + * 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. */ +public class IOUtil { + + @SuppressWarnings("unchecked") + public static T readObjectFromByteArray(byte[] data) throws RuntimeException { + ObjectInputStream ois = null; + + try { + ByteArrayInputStream bais = new ByteArrayInputStream(data); + ois = new ObjectInputStream(bais); + return (T) ois.readObject(); + + } catch(Exception e) { + throw Exceptions.propagate(e); + + } finally { + closeSilently(ois); + } + } + + public static void closeSilently(Closeable closable) { + try { + if(closable != null) { closable.close(); } + } catch(IOException ignore) { } + } +} diff --git a/library/src/main/java/com/patloew/rxwear/Message.java b/library/src/main/java/com/patloew/rxwear/Message.java new file mode 100644 index 0000000..dc36e68 --- /dev/null +++ b/library/src/main/java/com/patloew/rxwear/Message.java @@ -0,0 +1,263 @@ +package com.patloew.rxwear; + +import android.net.Uri; +import android.support.annotation.NonNull; + +import com.google.android.gms.wearable.Asset; +import com.google.android.gms.wearable.DataMap; +import com.google.android.gms.wearable.MessageEvent; +import com.google.android.gms.wearable.PutDataRequest; + +import java.io.ByteArrayOutputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.concurrent.TimeUnit; + +import rx.Observable; +import rx.Single; + +/* Copyright 2016 Patrick Löwenstein + * + * 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. */ +public class Message { + + private final RxWear rxWear; + + Message(RxWear rxWear) { + this.rxWear = rxWear; + } + + // listen + + public Observable listen() { + return listenInternal(null, null, null, null); + } + + public Observable listen(@NonNull Long timeout, @NonNull TimeUnit timeUnit) { + return listenInternal(null, null, timeout, timeUnit); + } + + public Observable listen(@NonNull Uri uri, int filterType) { + return listenInternal(uri, filterType, null, null); + } + + public Observable listen(@NonNull Uri uri, int filterType, long timeout, @NonNull TimeUnit timeUnit) { + return listenInternal(uri, filterType, timeout, timeUnit); + } + + public Observable listen(@NonNull String path, int filterType) { + return listenInternal(new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).path(path).build(), filterType, null, null); + } + + public Observable listen(@NonNull String path, int filterType, long timeout, @NonNull TimeUnit timeUnit) { + return listenInternal(new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).path(path).build(), filterType, timeout, timeUnit); + } + + private Observable listenInternal(Uri uri, Integer filterType, Long timeout, TimeUnit timeUnit) { + return Observable.create(new MessageListenerObservable(rxWear, uri, filterType, timeout, timeUnit)); + } + + // send + + public Single send(@NonNull String nodeId, @NonNull String path, @NonNull byte[] data) { + return sendInternal(nodeId, path, data, null, null); + } + + public Single send(@NonNull String nodeId, @NonNull String path, @NonNull byte[] data, long timeout, @NonNull TimeUnit timeUnit) { + return sendInternal(nodeId, path, data, timeout, timeUnit); + } + + private Single sendInternal(String nodeId, String path, byte[] data, Long timeout, TimeUnit timeUnit) { + return Single.create(new MessageSendSingle(rxWear, nodeId, path, data, timeout, timeUnit)); + } + + // sendToAllRemoteNodes + + public Observable sendToAllRemoteNodes(@NonNull final String path, @NonNull final byte[] data) { + return sendToAllRemoteNodesInternal(path, data, null, null); + } + + public Observable sendToAllRemoteNodes(@NonNull final String path, @NonNull final byte[] data, final long timeout, @NonNull final TimeUnit timeUnit) { + return sendToAllRemoteNodesInternal(path, data, timeout, timeUnit); + } + + private Observable sendToAllRemoteNodesInternal(final String path, final byte[] data, final Long timeout, final TimeUnit timeUnit) { + return rxWear.node().getConnectedNodesInternal(timeout, timeUnit) + .flatMap(node -> sendInternal(node.getId(), path, data, timeout, timeUnit).toObservable()); + } + + // Helper Methods + + public SendDataMap sendDataMap(String nodeId, String path) { + return new SendDataMap(this, nodeId, path, false); + } + + public SendDataMap sendDataMapToAllRemoteNodes(String path) { + return new SendDataMap(this, null, path, true); + } + + public Single sendSerializable(String nodeId, String path, Serializable serializable) { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new ObjectOutputStream(out).writeObject(serializable); + return sendInternal(nodeId, path, out.toByteArray(), null, null); + } catch(Throwable throwable) { + return Single.error(throwable); + } + } + + public Observable sendSerializableToAllRemoteNodes(String path, Serializable serializable) { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new ObjectOutputStream(out).writeObject(serializable); + return sendToAllRemoteNodesInternal(path, out.toByteArray(), null, null); + } catch(Throwable throwable) { + return Observable.error(throwable); + } + } + + /* A helper class with a fluent interface for sending a DataMap. + * + * Example: + * rxWear.message().sendDataMap().to(nodeId, "/path") + * .putString("key", "value") + * .putInt("key", 0) + * .toSingle() + * .subscribe(requestId -> { + * // do something + * }); + */ + public static class SendDataMap { + private final String nodeId; + private final String path; + private final DataMap dataMap = new DataMap(); + private final boolean toAllRemoteNodes; + private final Message message; + + private SendDataMap(Message message, String nodeId, String path, boolean toAllRemoteNodes) { + this.message = message; + this.nodeId = nodeId; + this.path = path; + this.toAllRemoteNodes = toAllRemoteNodes; + } + + + public SendDataMap putAll(DataMap dataMap) { + dataMap.putAll(dataMap); + return this; + } + + public SendDataMap putBoolean(String key, boolean value) { + dataMap.putBoolean(key, value); + return this; + } + + public SendDataMap putByte(String key, byte value) { + dataMap.putByte(key, value); + return this; + } + + public SendDataMap putInt(String key, int value) { + dataMap.putInt(key, value); + return this; + } + + public SendDataMap putLong(String key, long value) { + dataMap.putLong(key, value); + return this; + } + + public SendDataMap putFloat(String key, float value) { + dataMap.putFloat(key, value); + return this; + } + + public SendDataMap putDouble(String key, double value) { + dataMap.putDouble(key, value); + return this; + } + + public SendDataMap putString(String key, String value) { + dataMap.putString(key, value); + return this; + } + + public SendDataMap putAsset(String key, Asset value) { + dataMap.putAsset(key, value); + return this; + } + + public SendDataMap putDataMap(String key, DataMap value) { + dataMap.putDataMap(key, value); + return this; + } + + public SendDataMap putDataMapArrayList(String key, ArrayList value) { + dataMap.putDataMapArrayList(key, value); + return this; + } + + public SendDataMap putIntegerArrayList(String key, ArrayList value) { + dataMap.putIntegerArrayList(key, value); + return this; + } + + public SendDataMap putStringArrayList(String key, ArrayList value) { + dataMap.putStringArrayList(key, value); + return this; + } + + public SendDataMap putByteArray(String key, byte[] value) { + dataMap.putByteArray(key, value); + return this; + } + + public SendDataMap putLongArray(String key, long[] value) { + dataMap.putLongArray(key, value); + return this; + } + + public SendDataMap putFloatArray(String key, float[] value) { + dataMap.putFloatArray(key, value); + return this; + } + + public SendDataMap putStringArray(String key, String[] value) { + dataMap.putStringArray(key, value); + return this; + } + + public Observable toObservable() { + if(toAllRemoteNodes) { + return message.sendToAllRemoteNodesInternal(path, dataMap.toByteArray(), null, null); + } else { + return message.sendInternal(nodeId, path, dataMap.toByteArray(), null, null).toObservable(); + } + } + + /* This should only be used with to(). If used with + * toAllRemoteNodes(), an Exception will be thrown + * if more than one item is emitted (i.e. more than one + * node is connected). + */ + public Single toSingle() { + if(toAllRemoteNodes) { + return Single.error(new UnsupportedOperationException("toSingle() can not be used with toAllRemoteNodes()")); + } else { + return message.sendInternal(nodeId, path, dataMap.toByteArray(), null, null); + } + } + } + +} diff --git a/library/src/main/java/com/patloew/rxwear/MessageListenerObservable.java b/library/src/main/java/com/patloew/rxwear/MessageListenerObservable.java index cd3d9de..49c8ede 100644 --- a/library/src/main/java/com/patloew/rxwear/MessageListenerObservable.java +++ b/library/src/main/java/com/patloew/rxwear/MessageListenerObservable.java @@ -1,7 +1,6 @@ package com.patloew.rxwear; import android.net.Uri; -import android.support.annotation.NonNull; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.ResultCallback; @@ -27,7 +26,7 @@ * 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. */ -public class MessageListenerObservable extends BaseObservable { +class MessageListenerObservable extends BaseObservable { private final Uri uri; private final Integer filterType; @@ -42,21 +41,9 @@ public class MessageListenerObservable extends BaseObservable { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final Subscriber subscriber) { - listener = new MessageApi.MessageListener() { - @Override - public void onMessageReceived(MessageEvent messageEvent) { - subscriber.onNext(messageEvent); - } - }; + listener = subscriber::onNext; - ResultCallback resultCallback = new ResultCallback() { - @Override - public void onResult(@NonNull Status status) { - if (!status.isSuccess()) { - subscriber.onError(new StatusException(status)); - } - } - }; + ResultCallback resultCallback = new StatusErrorResultCallBack(subscriber); if(uri != null) { setupWearPendingResult(Wearable.MessageApi.addListener(apiClient, listener, uri, filterType), resultCallback); diff --git a/library/src/main/java/com/patloew/rxwear/MessageSendSingle.java b/library/src/main/java/com/patloew/rxwear/MessageSendSingle.java index 3a25325..645af12 100644 --- a/library/src/main/java/com/patloew/rxwear/MessageSendSingle.java +++ b/library/src/main/java/com/patloew/rxwear/MessageSendSingle.java @@ -1,9 +1,6 @@ package com.patloew.rxwear; -import android.support.annotation.NonNull; - import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.wearable.MessageApi; import com.google.android.gms.wearable.Wearable; @@ -24,7 +21,7 @@ * 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. */ -public class MessageSendSingle extends BaseSingle { +class MessageSendSingle extends BaseSingle { private final String nodeId; private final String path; @@ -39,15 +36,9 @@ public class MessageSendSingle extends BaseSingle { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final SingleSubscriber subscriber) { - setupWearPendingResult(Wearable.MessageApi.sendMessage(apiClient, nodeId, path, data), new ResultCallback() { - @Override - public void onResult(@NonNull MessageApi.SendMessageResult sendMessageResult) { - if (!sendMessageResult.getStatus().isSuccess()) { - subscriber.onError(new StatusException(sendMessageResult.getStatus())); - } else { - subscriber.onSuccess(sendMessageResult.getRequestId()); - } - } - }); + setupWearPendingResult( + Wearable.MessageApi.sendMessage(apiClient, nodeId, path, data), + SingleResultCallBack.get(subscriber, MessageApi.SendMessageResult::getRequestId) + ); } } diff --git a/library/src/main/java/com/patloew/rxwear/Node.java b/library/src/main/java/com/patloew/rxwear/Node.java new file mode 100644 index 0000000..86aaab7 --- /dev/null +++ b/library/src/main/java/com/patloew/rxwear/Node.java @@ -0,0 +1,78 @@ +package com.patloew.rxwear; + +import android.support.annotation.NonNull; + +import com.patloew.rxwear.events.NodeEvent; + +import java.util.concurrent.TimeUnit; + +import rx.Observable; +import rx.Single; + +/* Copyright 2016 Patrick Löwenstein + * + * 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. */ +public class Node { + + private final RxWear rxWear; + + Node(RxWear rxWear) { + this.rxWear = rxWear; + } + + // listen + + @Deprecated + public Observable listen() { + return listenInternal(null, null); + } + + @Deprecated + public Observable listen(long timeout, @NonNull TimeUnit timeUnit) { + return listenInternal(timeout, timeUnit); + } + + private Observable listenInternal(Long timeout, TimeUnit timeUnit) { + return Observable.create(new NodeListenerObservable(rxWear, timeout, timeUnit)); + } + + // getConnectedNodes + + public Observable getConnectedNodes() { + return getConnectedNodesInternal(null, null); + } + + public Observable getConnectedNodes(long timeout, @NonNull TimeUnit timeUnit) { + return getConnectedNodesInternal(timeout, timeUnit); + } + + Observable getConnectedNodesInternal(Long timeout, TimeUnit timeUnit) { + return Single.create(new NodeGetConnectedSingle(rxWear, timeout, timeUnit)) + .flatMapObservable(Observable::from); + } + + // getLocalNode + + public Single getLocalNode() { + return getLocalNodeInternal(null, null); + } + + public Single getLocalNode(long timeout, @NonNull TimeUnit timeUnit) { + return getLocalNodeInternal(timeout, timeUnit); + } + + private Single getLocalNodeInternal(Long timeout, TimeUnit timeUnit) { + return Single.create(new NodeGetLocalSingle(rxWear, timeout, timeUnit)); + } + +} diff --git a/library/src/main/java/com/patloew/rxwear/NodeGetConnectedSingle.java b/library/src/main/java/com/patloew/rxwear/NodeGetConnectedSingle.java index ea785f2..2b06716 100644 --- a/library/src/main/java/com/patloew/rxwear/NodeGetConnectedSingle.java +++ b/library/src/main/java/com/patloew/rxwear/NodeGetConnectedSingle.java @@ -1,9 +1,6 @@ package com.patloew.rxwear; -import android.support.annotation.NonNull; - import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.wearable.Node; import com.google.android.gms.wearable.NodeApi; import com.google.android.gms.wearable.Wearable; @@ -26,7 +23,7 @@ * 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. */ -public class NodeGetConnectedSingle extends BaseSingle> { +class NodeGetConnectedSingle extends BaseSingle> { NodeGetConnectedSingle(RxWear rxWear, Long timeout, TimeUnit timeUnit) { super(rxWear, timeout, timeUnit); @@ -34,16 +31,9 @@ public class NodeGetConnectedSingle extends BaseSingle> { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final SingleSubscriber> subscriber) { - setupWearPendingResult(Wearable.NodeApi.getConnectedNodes(apiClient), new ResultCallback() { - @Override - public void onResult(@NonNull NodeApi.GetConnectedNodesResult getConnectedNodesResult) { - if (!getConnectedNodesResult.getStatus().isSuccess()) { - subscriber.onError(new StatusException(getConnectedNodesResult.getStatus())); - } else { - subscriber.onSuccess(getConnectedNodesResult.getNodes()); - } - } - }); - + setupWearPendingResult( + Wearable.NodeApi.getConnectedNodes(apiClient), + SingleResultCallBack.get(subscriber, NodeApi.GetConnectedNodesResult::getNodes) + ); } } diff --git a/library/src/main/java/com/patloew/rxwear/NodeGetLocalSingle.java b/library/src/main/java/com/patloew/rxwear/NodeGetLocalSingle.java index b43fa2c..b135168 100644 --- a/library/src/main/java/com/patloew/rxwear/NodeGetLocalSingle.java +++ b/library/src/main/java/com/patloew/rxwear/NodeGetLocalSingle.java @@ -1,9 +1,6 @@ package com.patloew.rxwear; -import android.support.annotation.NonNull; - import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.wearable.Node; import com.google.android.gms.wearable.NodeApi; import com.google.android.gms.wearable.Wearable; @@ -25,7 +22,7 @@ * 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. */ -public class NodeGetLocalSingle extends BaseSingle { +class NodeGetLocalSingle extends BaseSingle { NodeGetLocalSingle(RxWear rxWear, Long timeout, TimeUnit timeUnit) { super(rxWear, timeout, timeUnit); @@ -33,16 +30,9 @@ public class NodeGetLocalSingle extends BaseSingle { @Override protected void onGoogleApiClientReady(GoogleApiClient apiClient, final SingleSubscriber subscriber) { - setupWearPendingResult(Wearable.NodeApi.getLocalNode(apiClient), new ResultCallback() { - @Override - public void onResult(@NonNull NodeApi.GetLocalNodeResult getLocalNodeResult) { - if (!getLocalNodeResult.getStatus().isSuccess()) { - subscriber.onError(new StatusException(getLocalNodeResult.getStatus())); - } else { - subscriber.onSuccess(getLocalNodeResult.getNode()); - } - } - }); - + setupWearPendingResult( + Wearable.NodeApi.getLocalNode(apiClient), + SingleResultCallBack.get(subscriber, NodeApi.GetLocalNodeResult::getNode) + ); } } diff --git a/library/src/main/java/com/patloew/rxwear/NodeListenerObservable.java b/library/src/main/java/com/patloew/rxwear/NodeListenerObservable.java index 194e6ab..fc6f67b 100644 --- a/library/src/main/java/com/patloew/rxwear/NodeListenerObservable.java +++ b/library/src/main/java/com/patloew/rxwear/NodeListenerObservable.java @@ -1,7 +1,5 @@ package com.patloew.rxwear; -import android.support.annotation.NonNull; - import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.common.api.Status; @@ -27,7 +25,7 @@ * 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. */ -public class NodeListenerObservable extends BaseObservable { +class NodeListenerObservable extends BaseObservable { private NodeApi.NodeListener listener; @@ -50,14 +48,7 @@ public void onPeerDisconnected(Node node) { } }; - ResultCallback resultCallback = new ResultCallback() { - @Override - public void onResult(@NonNull Status status) { - if (!status.isSuccess()) { - subscriber.onError(new StatusException(status)); - } - } - }; + ResultCallback resultCallback = new StatusErrorResultCallBack(subscriber); setupWearPendingResult(Wearable.NodeApi.addListener(apiClient, listener), resultCallback); } diff --git a/library/src/main/java/com/patloew/rxwear/RxWear.java b/library/src/main/java/com/patloew/rxwear/RxWear.java index 7940457..3d2b379 100644 --- a/library/src/main/java/com/patloew/rxwear/RxWear.java +++ b/library/src/main/java/com/patloew/rxwear/RxWear.java @@ -1,41 +1,15 @@ package com.patloew.rxwear; import android.content.Context; -import android.net.Uri; import android.support.annotation.NonNull; import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.common.api.Status; -import com.google.android.gms.wearable.Asset; -import com.google.android.gms.wearable.CapabilityInfo; -import com.google.android.gms.wearable.DataApi; -import com.google.android.gms.wearable.DataEvent; -import com.google.android.gms.wearable.DataItem; -import com.google.android.gms.wearable.DataItemAsset; -import com.google.android.gms.wearable.DataMap; -import com.google.android.gms.wearable.DataMapItem; -import com.google.android.gms.wearable.MessageEvent; -import com.google.android.gms.wearable.PutDataMapRequest; -import com.google.android.gms.wearable.PutDataRequest; import com.google.android.gms.wearable.Wearable; -import com.patloew.rxwear.events.ChannelEvent; -import com.patloew.rxwear.events.NodeEvent; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; import java.util.concurrent.TimeUnit; import rx.Completable; -import rx.Observable; import rx.Single; -import rx.functions.Func1; /* Copyright 2016 Patrick Löwenstein * @@ -50,33 +24,29 @@ * 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. - * - * ------------------------------- - * - * Factory for Google Wearable API observables. - * */ public class RxWear { - private static RxWear instance = null; + Long timeoutTime = null; + TimeUnit timeoutUnit = null; - private static Long timeoutTime = null; - private static TimeUnit timeoutUnit = null; + final Context ctx; - private final Context ctx; + private final Capability capability = new Capability(this); + private final Channel channel = new Channel(this); + private final Data data = new Data(this); + private final Message message = new Message(this); + private final Node node = new Node(this); - /* Initializes the singleton instance of RxWear - * - * @param ctx Context. - */ - public static void init(@NonNull Context ctx) { - if(instance == null) { instance = new RxWear(ctx); } + + public RxWear(@NonNull Context ctx) { + this.ctx = ctx.getApplicationContext(); } /* Set a default timeout for all requests to the Wearable API made in the lib. * When a timeout occurs, onError() is called with a StatusException. */ - public static void setDefaultTimeout(long time, @NonNull TimeUnit timeUnit) { + public void setDefaultTimeout(long time, @NonNull TimeUnit timeUnit) { if(timeUnit != null) { timeoutTime = time; timeoutUnit = timeUnit; @@ -87,905 +57,42 @@ public static void setDefaultTimeout(long time, @NonNull TimeUnit timeUnit) { /* Reset the default timeout. */ - public static void resetDefaultTimeout() { + public void resetDefaultTimeout() { timeoutTime = null; timeoutUnit = null; } - /* Gets the singleton instance of RxWear, after it was initialized. - */ - private static RxWear get() { - if(instance == null) { throw new IllegalStateException("RxWear not initialized"); } - return instance; - } - - - private RxWear(@NonNull Context ctx) { - this.ctx = ctx.getApplicationContext(); - } - - Context getContext() { - return ctx; - } - - static Long getDefaultTimeout() { - return timeoutTime; - } - - static TimeUnit getDefaultTimeoutUnit() { - return timeoutUnit; - } - /* Can be used to check whether connection to Wearable API was successful. * * This Completable completes if the connection was successful. */ - public static Completable checkConnection() { + public Completable checkConnection() { return Completable.fromSingle(getWearableClient()); } - public static Single getWearableClient() { - return GoogleAPIClientSingle.create(RxWear.get().getContext(), Wearable.API); + public Single getWearableClient() { + return GoogleAPIClientSingle.create(ctx, Wearable.API); } - public static class Capability { - - private Capability() { } - // listen - - public static Observable listen(@NonNull String capability) { - return listenInternal(capability, null, null, null, null); - } - - public static Observable listen(@NonNull String capability, long timeout, @NonNull TimeUnit timeUnit) { - return listenInternal(capability, null, null, timeout, timeUnit); - } - - public static Observable listen(@NonNull Uri uri, int filterType) { - return listenInternal(null, uri, filterType, null, null); - } - - public static Observable listen(@NonNull Uri uri, int filterType, long timeout, @NonNull TimeUnit timeUnit) { - return listenInternal(null, uri, filterType, timeout, timeUnit); - } - - private static Observable listenInternal(String capability, Uri uri, Integer filterType, Long timeout, TimeUnit timeUnit) { - return Observable.create(new CapabilityListenerObservable(RxWear.get(), capability, uri, filterType, timeout, timeUnit)); - } - - // getAll - - public static Observable getAll(int nodeFilter) { - return getAllInternal(nodeFilter, null, null); - } - - public static Observable getAll(int nodeFilter, long timeout, @NonNull TimeUnit timeUnit) { - return getAllInternal(nodeFilter, timeout, timeUnit); - } - - private static Observable getAllInternal(int nodeFilter, Long timeout, TimeUnit timeUnit) { - return Single.create(new CapabilityGetAllSingle(RxWear.get(), nodeFilter, timeout, timeUnit)) - .flatMapObservable(new Func1, Observable>() { - @Override - public Observable call(Map capabilityInfoMap) { - return Observable.from(capabilityInfoMap.values()); - } - }); - } - - // get - - public static Single get(@NonNull String capability, int nodeFilter) { - return getInternal(capability, nodeFilter, null, null); - } - - public static Single get(@NonNull String capability, int nodeFilter, long timeout, @NonNull TimeUnit timeUnit) { - return getInternal(capability, nodeFilter, timeout, timeUnit); - } - - private static Single getInternal(String capability, int nodeFilter, Long timeout, TimeUnit timeUnit) { - return Single.create(new CapabilityGetSingle(RxWear.get(), capability, nodeFilter, timeout, timeUnit)); - } - - // addLocal - - public static Single addLocal(@NonNull String capability) { - return addLocalInternal(capability, null, null); - } - - public static Single addLocal(@NonNull String capability, long timeout, @NonNull TimeUnit timeUnit) { - return addLocalInternal(capability, timeout, timeUnit); - } - - private static Single addLocalInternal(String capability, Long timeout, TimeUnit timeUnit) { - return Single.create(new CapabilityAddLocalSingle(RxWear.get(), capability, timeout, timeUnit)); - } - - // removeLocal - - public static Single removeLocal(@NonNull String capability) { - return removeLocalInternal(capability, null, null); - } - - public static Single removeLocal(@NonNull String capability, long timeout, @NonNull TimeUnit timeUnit) { - return removeLocalInternal(capability, timeout, timeUnit); - } - - private static Single removeLocalInternal(String capability, Long timeout, TimeUnit timeUnit) { - return Single.create(new CapabilityRemoveLocalSingle(RxWear.get(), capability, timeout, timeUnit)); - } + public Capability capability() { + return capability; } - - public static class Channel { - - private Channel() { } - - // listen - - public static Observable listen() { - return listenInternal(null, null, null); - } - - public static Observable listen(long timeout, @NonNull TimeUnit timeUnit) { - return listenInternal(null, timeout, timeUnit); - } - - public static Observable listen(@NonNull com.google.android.gms.wearable.Channel channel) { - return listenInternal(channel, null, null); - } - - public static Observable listen(@NonNull com.google.android.gms.wearable.Channel channel, long timeout, @NonNull TimeUnit timeUnit) { - return listenInternal(channel, timeout, timeUnit); - } - - private static Observable listenInternal(com.google.android.gms.wearable.Channel channel, Long timeout, TimeUnit timeUnit) { - return Observable.create(new ChannelListenerObservable(RxWear.get(), channel, timeout, timeUnit)); - } - - // close - - public static Single close(@NonNull com.google.android.gms.wearable.Channel channel) { - return closeInternal(channel, null, null, null); - } - - public static Single close(@NonNull com.google.android.gms.wearable.Channel channel, long timeout, @NonNull TimeUnit timeUnit) { - return closeInternal(channel, null, timeout, timeUnit); - } - - public static Single close(@NonNull com.google.android.gms.wearable.Channel channel, int errorCode) { - return closeInternal(channel, errorCode, null, null); - } - - public static Single close(@NonNull com.google.android.gms.wearable.Channel channel, int errorCode, long timeout, @NonNull TimeUnit timeUnit) { - return closeInternal(channel, errorCode, timeout, timeUnit); - } - - private static Single closeInternal(com.google.android.gms.wearable.Channel channel, Integer errorCode, Long timeout, TimeUnit timeUnit) { - return Single.create(new ChannelCloseSingle(RxWear.get(), channel, errorCode, timeout, timeUnit)); - } - - // sendFile - - public static Single sendFile(@NonNull com.google.android.gms.wearable.Channel channel, @NonNull Uri uri) { - return sendFileInternal(channel, uri, null, null, null, null); - } - - public static Single sendFile(@NonNull com.google.android.gms.wearable.Channel channel, @NonNull Uri uri, long timeout, @NonNull TimeUnit timeUnit) { - return sendFileInternal(channel, uri, null, null, timeout, timeUnit); - } - - public static Single sendFile(@NonNull com.google.android.gms.wearable.Channel channel, @NonNull Uri uri, long startOffset, long length) { - return sendFileInternal(channel, uri, startOffset, length, null, null); - } - - public static Single sendFile(@NonNull com.google.android.gms.wearable.Channel channel, @NonNull Uri uri, long startOffset, long length, long timeout, @NonNull TimeUnit timeUnit) { - return sendFileInternal(channel, uri, startOffset, length, timeout, timeUnit); - } - - private static Single sendFileInternal(com.google.android.gms.wearable.Channel channel, Uri uri, Long startOffset, Long length, Long timeout, TimeUnit timeUnit) { - return Single.create(new ChannelSendFileSingle(RxWear.get(), channel, uri, startOffset, length, timeout, timeUnit)); - } - - // receiveFile - - public static Single receiveFile(@NonNull com.google.android.gms.wearable.Channel channel, @NonNull Uri uri, boolean append) { - return receiveFileInternal(channel, uri, append, null, null); - } - - public static Single receiveFile(@NonNull com.google.android.gms.wearable.Channel channel, @NonNull Uri uri, boolean append, long timeout, @NonNull TimeUnit timeUnit) { - return receiveFileInternal(channel, uri, append, timeout, timeUnit); - } - - private static Single receiveFileInternal(com.google.android.gms.wearable.Channel channel, Uri uri, boolean append, Long timeout, TimeUnit timeUnit) { - return Single.create(new ChannelReceiveFileSingle(RxWear.get(), channel, uri, append, timeout, timeUnit)); - } - - // getInputStream - - public static Single getInputStream(@NonNull com.google.android.gms.wearable.Channel channel) { - return getInputStreamInternal(channel, null, null); - } - - public static Single getInputStream(@NonNull com.google.android.gms.wearable.Channel channel, long timeout, @NonNull TimeUnit timeUnit) { - return getInputStreamInternal(channel, timeout, timeUnit); - } - - private static Single getInputStreamInternal(com.google.android.gms.wearable.Channel channel, Long timeout, TimeUnit timeUnit) { - return Single.create(new ChannelGetInputStreamSingle(RxWear.get(), channel, timeout, timeUnit)); - } - - // getOutputStream - - public static Single getOutputStream(@NonNull com.google.android.gms.wearable.Channel channel) { - return getOutputStreamInternal(channel, null, null); - } - - public static Single getOutputStream(@NonNull com.google.android.gms.wearable.Channel channel, long timeout, @NonNull TimeUnit timeUnit) { - return getOutputStreamInternal(channel, timeout, timeUnit); - } - - private static Single getOutputStreamInternal(com.google.android.gms.wearable.Channel channel, Long timeout, TimeUnit timeUnit) { - return Single.create(new ChannelGetOutputStreamSingle(RxWear.get(), channel, timeout, timeUnit)); - } - - // open - - public static Single open(@NonNull String nodeId, @NonNull String path) { - return openInternal(nodeId, path, null, null); - } - - public static Single open(@NonNull String nodeId, @NonNull String path, long timeout, @NonNull TimeUnit timeUnit) { - return openInternal(nodeId, path, timeout, timeUnit); - } - - private static Single openInternal(String nodeId, String path, Long timeout, TimeUnit timeUnit) { - return Single.create(new ChannelOpenSingle(RxWear.get(), nodeId, path, timeout, timeUnit)); - } + public Channel channel() { + return channel; } - public static class Data { - - private Data() { } - - // listen - - public static Observable listen() { - return listenInternal(null, null, null, null); - } - - public static Observable listen(long timeout, @NonNull TimeUnit timeUnit) { - return listenInternal(null, null, timeout, timeUnit); - } - - public static Observable listen(@NonNull Uri uri, int filterType) { - return listenInternal(uri, filterType, null, null); - } - - public static Observable listen(@NonNull Uri uri, int filterType, long timeout, @NonNull TimeUnit timeUnit) { - return listenInternal(uri, filterType, timeout, timeUnit); - } - - public static Observable listen(@NonNull String path, int filterType) { - return listenInternal(new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).path(path).build(), filterType, null, null); - } - - public static Observable listen(@NonNull String path, int filterType, long timeout, @NonNull TimeUnit timeUnit) { - return listenInternal(new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).path(path).build(), filterType, timeout, timeUnit); - } - - private static Observable listenInternal(Uri uri, Integer filterType, Long timeout, TimeUnit timeUnit) { - return Observable.create(new DataListenerObservable(RxWear.get(), uri, filterType, timeout, timeUnit)); - } - - // delete - - public static Single delete(@NonNull Uri uri) { - return deleteInternal(uri, null, null, null); - } - - public static Single delete(@NonNull Uri uri, @NonNull Long timeout, @NonNull TimeUnit timeUnit) { - return deleteInternal(uri, null, timeout, timeUnit); - } - - public static Single delete(@NonNull Uri uri, int filterType) { - return deleteInternal(uri, filterType, null, null); - } - - public static Single delete(@NonNull Uri uri, int filterType, long timeout, @NonNull TimeUnit timeUnit) { - return deleteInternal(uri, filterType, timeout, timeUnit); - } - - private static Single deleteInternal(Uri uri, Integer filterType, Long timeout, TimeUnit timeUnit) { - return Single.create(new DataDeleteItemsSingle(RxWear.get(), uri, filterType, timeout, timeUnit)); - } - - // put - - public static Single put(@NonNull PutDataRequest putDataRequest) { - return putInternal(putDataRequest, null, null); - } - - public static Single put(@NonNull PutDataRequest putDataRequest, long timeout, @NonNull TimeUnit timeUnit) { - return putInternal(putDataRequest, timeout, timeUnit); - } - - public static Single put(@NonNull PutDataMapRequest putDataMapRequest) { - return putInternal(putDataMapRequest.asPutDataRequest(), null, null); - } - - public static Single put(@NonNull PutDataMapRequest putDataMapRequest, long timeout, @NonNull TimeUnit timeUnit) { - return putInternal(putDataMapRequest.asPutDataRequest(), timeout, timeUnit); - } - - private static Single putInternal(PutDataRequest putDataRequest, Long timeout, TimeUnit timeUnit) { - return Single.create(new DataPutItemSingle(RxWear.get(), putDataRequest, timeout, timeUnit)); - } - - - // getSingle - - @Deprecated - // use get() instead - public static Single getSingle(@NonNull Uri uri) { - return getSingleInternal(uri, null, null); - } - - @Deprecated - // use get() instead - public static Single getSingle(@NonNull Uri uri, long timeout, @NonNull TimeUnit timeUnit) { - return getSingleInternal(uri, timeout, timeUnit); - } - - private static Single getSingleInternal(Uri uri, Long timeout, TimeUnit timeUnit) { - return Single.create(new DataGetItemSingle(RxWear.get(), uri, timeout, timeUnit)); - } - - // get - - public static Observable get(@NonNull Uri uri, int filterType) { - return getInternal(uri, filterType, null, null); - } - - public static Observable get(@NonNull Uri uri, int filterType, long timeout, @NonNull TimeUnit timeUnit) { - return getInternal(uri, filterType, timeout, timeUnit); - } - - public static Observable get(@NonNull String path, int filterType) { - return getInternal(new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).path(path).build(), filterType, null, null); - } - - public static Observable get(@NonNull String path, int filterType, long timeout, @NonNull TimeUnit timeUnit) { - return getInternal(new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).path(path).build(), filterType, timeout, timeUnit); - } - - public static Observable get(@NonNull Uri uri) { - return getInternal(uri, null, null, null); - } - - public static Observable get(@NonNull Uri uri, long timeout, @NonNull TimeUnit timeUnit) { - return getInternal(uri, null, timeout, timeUnit); - } - - public static Observable get(@NonNull String path) { - return getInternal(new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).path(path).build(), null, null, null); - } - - public static Observable get(@NonNull String path, long timeout, @NonNull TimeUnit timeUnit) { - return getInternal(new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).path(path).build(), null, timeout, timeUnit); - } - - public static Observable get() { - return getInternal(null, null, null, null); - } - - public static Observable get(long timeout, @NonNull TimeUnit timeUnit) { - return getInternal(null, null, timeout, timeUnit); - } - - private static Observable getInternal(Uri uri, Integer filterType, Long timeout, TimeUnit timeUnit) { - return Observable.create(new DataGetItemsObservable(RxWear.get(), uri, filterType, timeout, timeUnit)); - } - - // getFdForAsset - - public static Single getFdForAsset(@NonNull DataItemAsset dataItemAsset) { - return getFdForAssetInternal(dataItemAsset, null, null, null); - } - - public static Single getFdForAsset(@NonNull DataItemAsset dataItemAsset, long timeout, @NonNull TimeUnit timeUnit) { - return getFdForAssetInternal(dataItemAsset, null, timeout, timeUnit); - } - - public static Single getFdForAsset(@NonNull Asset asset) { - return getFdForAssetInternal(null, asset, null, null); - } - - public static Single getFdForAsset(@NonNull Asset asset, long timeout, @NonNull TimeUnit timeUnit) { - return getFdForAssetInternal(null, asset, timeout, timeUnit); - } - - private static Single getFdForAssetInternal(DataItemAsset dataItemAsset, Asset asset, Long timeout, TimeUnit timeUnit) { - return Single.create(new DataGetFdForAssetSingle(RxWear.get(), dataItemAsset, asset, timeout, timeUnit)); - } - - /* A helper class with a fluent interface for putting a Serializable - * based on a DataMap. - * - * Example: - * RxWear.Data.PutSerializable.urgentTo("/path", serializable) - * .subscribe(dataItem -> { - * // do something - * }); - */ - public static class PutSerializable { - - private PutSerializable() { } - - public static Single withDataItem(DataItem dataItem, Serializable serializable) { - return createSingle(PutDataRequest.createFromDataItem(dataItem), serializable); - } - - public static Single urgentWithDataItem(DataItem dataItem, Serializable serializable) { - return createSingle(PutDataRequest.createFromDataItem(dataItem).setUrgent(), serializable); - } - - public static Single withAutoAppendedId(String pathPrefix, Serializable serializable) { - return createSingle(PutDataRequest.createWithAutoAppendedId(pathPrefix), serializable); - } - - public static Single urgentWithAutoAppendedId(String pathPrefix, Serializable serializable) { - return createSingle(PutDataRequest.createWithAutoAppendedId(pathPrefix).setUrgent(), serializable); - } - - public static Single to(String path, Serializable serializable) { - return createSingle(PutDataRequest.create(path), serializable); - } - - public static Single urgentTo(String path, Serializable serializable) { - return createSingle(PutDataRequest.create(path).setUrgent(), serializable); - } - - private static Single createSingle(PutDataRequest request, Serializable serializable) { - try { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - new ObjectOutputStream(out).writeObject(serializable); - request.setData(out.toByteArray()); - return putInternal(request, null, null); - } catch(IOException e) { - return Single.error(e); - } - } - - } - - /* A helper class with a fluent interface for putting a DataItem - * based on a DataMap. - * - * Example: - * RxWear.Data.PutDataMap.to("/path") - * .putString("key", "value") - * .putInt("key", 0) - * .toSingle() - * .subscribe(dataItem -> { - * // do something - * }); - */ - public static class PutDataMap { - private final PutDataMapRequest request; - - private PutDataMap(String path, DataMapItem dataMapItem, String pathPrefix) { - if(path != null) { - request = PutDataMapRequest.create(path); - } else if(dataMapItem != null) { - request = PutDataMapRequest.createFromDataMapItem(dataMapItem); - } else { - request = PutDataMapRequest.createWithAutoAppendedId(pathPrefix); - } - } - - public static PutDataMap withDataMapItem(DataMapItem source) { - return new PutDataMap(null, source, null); - } - - public static PutDataMap withAutoAppendedId(String pathPrefix) { - return new PutDataMap(null, null, pathPrefix); - } - - public static PutDataMap to(String path) { - return new PutDataMap(path, null, null); - } - - public PutDataMap setUrgent() { - request.setUrgent(); - return this; - } - - public PutDataMap putAll(DataMap dataMap) { - request.getDataMap().putAll(dataMap); - return this; - } - - public PutDataMap putBoolean(String key, boolean value) { - request.getDataMap().putBoolean(key, value); - return this; - } - - public PutDataMap putByte(String key, byte value) { - request.getDataMap().putByte(key, value); - return this; - } - - public PutDataMap putInt(String key, int value) { - request.getDataMap().putInt(key, value); - return this; - } - - public PutDataMap putLong(String key, long value) { - request.getDataMap().putLong(key, value); - return this; - } - - public PutDataMap putFloat(String key, float value) { - request.getDataMap().putFloat(key, value); - return this; - } - - public PutDataMap putDouble(String key, double value) { - request.getDataMap().putDouble(key, value); - return this; - } - - public PutDataMap putString(String key, String value) { - request.getDataMap().putString(key, value); - return this; - } - - public PutDataMap putAsset(String key, Asset value) { - request.getDataMap().putAsset(key, value); - return this; - } - - public PutDataMap putDataMap(String key, DataMap value) { - request.getDataMap().putDataMap(key, value); - return this; - } - - public PutDataMap putDataMapArrayList(String key, ArrayList value) { - request.getDataMap().putDataMapArrayList(key, value); - return this; - } - - public PutDataMap putIntegerArrayList(String key, ArrayList value) { - request.getDataMap().putIntegerArrayList(key, value); - return this; - } - - public PutDataMap putStringArrayList(String key, ArrayList value) { - request.getDataMap().putStringArrayList(key, value); - return this; - } - - public PutDataMap putByteArray(String key, byte[] value) { - request.getDataMap().putByteArray(key, value); - return this; - } - - public PutDataMap putLongArray(String key, long[] value) { - request.getDataMap().putLongArray(key, value); - return this; - } - - public PutDataMap putFloatArray(String key, float[] value) { - request.getDataMap().putFloatArray(key, value); - return this; - } - - public PutDataMap putStringArray(String key, String[] value) { - request.getDataMap().putStringArray(key, value); - return this; - } - - public Single toSingle() { - return putInternal(request.asPutDataRequest(), null, null); - } - - public Observable toObservable() { - return putInternal(request.asPutDataRequest(), null, null).toObservable(); - } - } - + public Data data() { + return data; } - public static class Message { - - private Message() { } - - // listen - - public static Observable listen() { - return listenInternal(null, null, null, null); - } - - public static Observable listen(@NonNull Long timeout, @NonNull TimeUnit timeUnit) { - return listenInternal(null, null, timeout, timeUnit); - } - - public static Observable listen(@NonNull Uri uri, int filterType) { - return listenInternal(uri, filterType, null, null); - } - - public static Observable listen(@NonNull Uri uri, int filterType, long timeout, @NonNull TimeUnit timeUnit) { - return listenInternal(uri, filterType, timeout, timeUnit); - } - - public static Observable listen(@NonNull String path, int filterType) { - return listenInternal(new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).path(path).build(), filterType, null, null); - } - - public static Observable listen(@NonNull String path, int filterType, long timeout, @NonNull TimeUnit timeUnit) { - return listenInternal(new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).path(path).build(), filterType, timeout, timeUnit); - } - - private static Observable listenInternal(Uri uri, Integer filterType, Long timeout, TimeUnit timeUnit) { - return Observable.create(new MessageListenerObservable(RxWear.get(), uri, filterType, timeout, timeUnit)); - } - - // send - - public static Single send(@NonNull String nodeId, @NonNull String path, @NonNull byte[] data) { - return sendInternal(nodeId, path, data, null, null); - } - - public static Single send(@NonNull String nodeId, @NonNull String path, @NonNull byte[] data, long timeout, @NonNull TimeUnit timeUnit) { - return sendInternal(nodeId, path, data, timeout, timeUnit); - } - - private static Single sendInternal(String nodeId, String path, byte[] data, Long timeout, TimeUnit timeUnit) { - return Single.create(new MessageSendSingle(RxWear.get(), nodeId, path, data, timeout, timeUnit)); - } - - // sendToAllRemoteNodes - - public static Observable sendToAllRemoteNodes(@NonNull final String path, @NonNull final byte[] data) { - return sendToAllRemoteNodesInternal(path, data, null, null); - } - - public static Observable sendToAllRemoteNodes(@NonNull final String path, @NonNull final byte[] data, final long timeout, @NonNull final TimeUnit timeUnit) { - return sendToAllRemoteNodesInternal(path, data, timeout, timeUnit); - } - - private static Observable sendToAllRemoteNodesInternal(final String path, final byte[] data, final Long timeout, final TimeUnit timeUnit) { - return Node.getConnectedNodesInternal(timeout, timeUnit).flatMap(new Func1>() { - @Override - public Observable call(com.google.android.gms.wearable.Node node) { - return sendInternal(node.getId(), path, data, timeout, timeUnit).toObservable(); - } - }); - } - - /* A helper class to send a Serializable in a message */ - public static class SendSerializable { - - private SendSerializable() { } - - public static Single to(String nodeId, String path, Serializable serializable) { - try { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - new ObjectOutputStream(out).writeObject(serializable); - return sendInternal(nodeId, path, out.toByteArray(), null, null); - } catch(Throwable throwable) { - return Single.error(throwable); - } - } - - public static Observable toAllRemoteNodes(String path, Serializable serializable) { - try { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - new ObjectOutputStream(out).writeObject(serializable); - return sendToAllRemoteNodesInternal(path, out.toByteArray(), null, null); - } catch(Throwable throwable) { - return Observable.error(throwable); - } - } - } - - /* A helper class with a fluent interface for putting a DataItem - * based on a DataMap. - * - * Example: - * RxWear.Message.SendDataMap.to(nodeId, "/path") - * .putString("key", "value") - * .putInt("key", 0) - * .toSingle() - * .subscribe(requestId -> { - * // do something - * }); - */ - public static class SendDataMap { - private final String nodeId; - private final String path; - private final DataMap dataMap = new DataMap(); - private final boolean toAllRemoteNodes; - - private SendDataMap(String nodeId, String path, boolean toAllRemoteNodes) { - this.nodeId = nodeId; - this.path = path; - this.toAllRemoteNodes = toAllRemoteNodes; - } - - public static SendDataMap to(String nodeId, String path) { - return new SendDataMap(nodeId, path, false); - } - - public static SendDataMap toAllRemoteNodes(String path) { - return new SendDataMap(null, path, true); - } - - public SendDataMap putAll(DataMap dataMap) { - dataMap.putAll(dataMap); - return this; - } - - public SendDataMap putBoolean(String key, boolean value) { - dataMap.putBoolean(key, value); - return this; - } - - public SendDataMap putByte(String key, byte value) { - dataMap.putByte(key, value); - return this; - } - - public SendDataMap putInt(String key, int value) { - dataMap.putInt(key, value); - return this; - } - - public SendDataMap putLong(String key, long value) { - dataMap.putLong(key, value); - return this; - } - - public SendDataMap putFloat(String key, float value) { - dataMap.putFloat(key, value); - return this; - } - - public SendDataMap putDouble(String key, double value) { - dataMap.putDouble(key, value); - return this; - } - - public SendDataMap putString(String key, String value) { - dataMap.putString(key, value); - return this; - } - - public SendDataMap putAsset(String key, Asset value) { - dataMap.putAsset(key, value); - return this; - } - - public SendDataMap putDataMap(String key, DataMap value) { - dataMap.putDataMap(key, value); - return this; - } - - public SendDataMap putDataMapArrayList(String key, ArrayList value) { - dataMap.putDataMapArrayList(key, value); - return this; - } - - public SendDataMap putIntegerArrayList(String key, ArrayList value) { - dataMap.putIntegerArrayList(key, value); - return this; - } - - public SendDataMap putStringArrayList(String key, ArrayList value) { - dataMap.putStringArrayList(key, value); - return this; - } - - public SendDataMap putByteArray(String key, byte[] value) { - dataMap.putByteArray(key, value); - return this; - } - - public SendDataMap putLongArray(String key, long[] value) { - dataMap.putLongArray(key, value); - return this; - } - - public SendDataMap putFloatArray(String key, float[] value) { - dataMap.putFloatArray(key, value); - return this; - } - - public SendDataMap putStringArray(String key, String[] value) { - dataMap.putStringArray(key, value); - return this; - } - - public Observable toObservable() { - if(toAllRemoteNodes) { - return Message.sendToAllRemoteNodesInternal(path, dataMap.toByteArray(), null, null); - } else { - return Message.sendInternal(nodeId, path, dataMap.toByteArray(), null, null).toObservable(); - } - } - - /* This should only be used with to(). If used with - * toAllRemoteNodes(), an Exception will be thrown - * if more than one item is emitted (i.e. more than one - * node is connected). - */ - public Single toSingle() { - if(toAllRemoteNodes) { - return Single.error(new UnsupportedOperationException("toSingle() can not be used with toAllRemoteNodes()")); - } else { - return Message.sendInternal(nodeId, path, dataMap.toByteArray(), null, null); - } - } - } - + public Message message() { + return message; } - - public static class Node { - - private Node() { } - - // listen - - @Deprecated - public static Observable listen() { - return listenInternal(null, null); - } - - @Deprecated - public static Observable listen(long timeout, @NonNull TimeUnit timeUnit) { - return listenInternal(timeout, timeUnit); - } - - private static Observable listenInternal(Long timeout, TimeUnit timeUnit) { - return Observable.create(new NodeListenerObservable(RxWear.get(), timeout, timeUnit)); - } - - // getConnectedNodes - - public static Observable getConnectedNodes() { - return getConnectedNodesInternal(null, null); - } - - public static Observable getConnectedNodes(long timeout, @NonNull TimeUnit timeUnit) { - return getConnectedNodesInternal(timeout, timeUnit); - } - - private static Observable getConnectedNodesInternal(Long timeout, TimeUnit timeUnit) { - return Single.create(new NodeGetConnectedSingle(RxWear.get(), timeout, timeUnit)).flatMapObservable(new Func1, Observable>() { - @Override - public Observable call(List nodes) { - return Observable.from(nodes); - } - }); - } - - // getLocalNode - - public static Single getLocalNode() { - return getLocalNodeInternal(null, null); - } - - public static Single getLocalNode(long timeout, @NonNull TimeUnit timeUnit) { - return getLocalNodeInternal(timeout, timeUnit); - } - - private static Single getLocalNodeInternal(Long timeout, TimeUnit timeUnit) { - return Single.create(new NodeGetLocalSingle(RxWear.get(), timeout, timeUnit)); - } - + public Node node() { + return node; } } diff --git a/library/src/main/java/com/patloew/rxwear/SingleResultCallBack.java b/library/src/main/java/com/patloew/rxwear/SingleResultCallBack.java new file mode 100644 index 0000000..576b8b2 --- /dev/null +++ b/library/src/main/java/com/patloew/rxwear/SingleResultCallBack.java @@ -0,0 +1,50 @@ +package com.patloew.rxwear; + +import android.support.annotation.NonNull; + +import com.google.android.gms.common.api.Result; +import com.google.android.gms.common.api.ResultCallback; + +import rx.SingleSubscriber; +import rx.functions.Func1; + +/* Copyright 2016 Patrick Löwenstein + * + * 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. */ +class SingleResultCallBack implements ResultCallback { + + private final SingleSubscriber subscriber; + private final Func1 mapper; + + static ResultCallback get(@NonNull SingleSubscriber subscriber, @NonNull Func1 mapper) { + return new SingleResultCallBack<>(subscriber, mapper); + } + + static ResultCallback get(@NonNull SingleSubscriber subscriber) { + return new SingleResultCallBack<>(subscriber, input -> input); + } + + private SingleResultCallBack(@NonNull SingleSubscriber subscriber, @NonNull Func1 mapper) { + this.subscriber = subscriber; + this.mapper = mapper; + } + + @Override + public void onResult(@NonNull T result) { + if (!result.getStatus().isSuccess()) { + subscriber.onError(new StatusException(result.getStatus())); + } else { + subscriber.onSuccess(mapper.call(result)); + } + } +} diff --git a/library/src/main/java/com/patloew/rxwear/StatusResultCallBack.java b/library/src/main/java/com/patloew/rxwear/StatusErrorResultCallBack.java similarity index 76% rename from library/src/main/java/com/patloew/rxwear/StatusResultCallBack.java rename to library/src/main/java/com/patloew/rxwear/StatusErrorResultCallBack.java index 4034e25..06baa0b 100644 --- a/library/src/main/java/com/patloew/rxwear/StatusResultCallBack.java +++ b/library/src/main/java/com/patloew/rxwear/StatusErrorResultCallBack.java @@ -5,7 +5,7 @@ import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.common.api.Status; -import rx.SingleSubscriber; +import rx.Subscriber; /* Copyright 2016 Patrick Löwenstein * @@ -20,11 +20,11 @@ * 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. */ -public class StatusResultCallBack implements ResultCallback { +class StatusErrorResultCallBack implements ResultCallback { - private final SingleSubscriber subscriber; + private final Subscriber subscriber; - public StatusResultCallBack(@NonNull SingleSubscriber subscriber) { + StatusErrorResultCallBack(@NonNull Subscriber subscriber) { this.subscriber = subscriber; } @@ -32,8 +32,6 @@ public StatusResultCallBack(@NonNull SingleSubscriber subscriber public void onResult(@NonNull Status status) { if (!status.isSuccess()) { subscriber.onError(new StatusException(status)); - } else { - subscriber.onSuccess(status); } } } diff --git a/library/src/main/java/com/patloew/rxwear/StatusException.java b/library/src/main/java/com/patloew/rxwear/StatusException.java index e6216b9..edda473 100644 --- a/library/src/main/java/com/patloew/rxwear/StatusException.java +++ b/library/src/main/java/com/patloew/rxwear/StatusException.java @@ -16,10 +16,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -public class StatusException extends Throwable { +public class StatusException extends Exception { private final Status status; public StatusException(Status status) { + super(status.toString()); this.status = status; } diff --git a/library/src/main/java/com/patloew/rxwear/transformers/DataEventGetDataMap.java b/library/src/main/java/com/patloew/rxwear/transformers/DataEventGetDataMap.java index ee9665a..2df10db 100644 --- a/library/src/main/java/com/patloew/rxwear/transformers/DataEventGetDataMap.java +++ b/library/src/main/java/com/patloew/rxwear/transformers/DataEventGetDataMap.java @@ -5,7 +5,6 @@ import com.google.android.gms.wearable.DataMapItem; import rx.Observable; -import rx.functions.Func1; /* Copyright 2016 Patrick Löwenstein * @@ -65,32 +64,23 @@ public static Observable.Transformer filterByType(int type) @Override public Observable call(Observable observable) { if(type != null) { - observable = observable.filter(new Func1() { - @Override - public Boolean call(DataEvent dataEvent) { - return dataEvent.getType() == type; - } - }); + observable = observable.filter(dataEvent -> dataEvent.getType() == type); } if(path != null) { - observable = observable.filter(new Func1() { - @Override - public Boolean call(DataEvent dataEvent) { - if (isPrefix) { - return dataEvent.getDataItem().getUri().getPath().startsWith(path); - } else { - return dataEvent.getDataItem().getUri().getPath().equals(path); - } + observable = observable.filter(dataEvent -> { + if (isPrefix) { + return dataEvent.getDataItem().getUri().getPath().startsWith(path); + } else { + return dataEvent.getDataItem().getUri().getPath().equals(path); } }); } - return observable.map(new Func1() { - @Override - public DataMap call(DataEvent dataEvent) { - return DataMapItem.fromDataItem(dataEvent.getDataItem()).getDataMap(); - } - }); + return observable.map(this::getDataMap); + } + + private DataMap getDataMap(DataEvent dataEvent) { + return DataMapItem.fromDataItem(dataEvent.getDataItem()).getDataMap(); } } diff --git a/library/src/main/java/com/patloew/rxwear/transformers/DataEventGetSerializable.java b/library/src/main/java/com/patloew/rxwear/transformers/DataEventGetSerializable.java index 61229f6..96bf784 100644 --- a/library/src/main/java/com/patloew/rxwear/transformers/DataEventGetSerializable.java +++ b/library/src/main/java/com/patloew/rxwear/transformers/DataEventGetSerializable.java @@ -1,14 +1,12 @@ package com.patloew.rxwear.transformers; import com.google.android.gms.wearable.DataEvent; +import com.patloew.rxwear.IOUtil; -import java.io.ByteArrayInputStream; -import java.io.ObjectInputStream; import java.io.Serializable; import rx.Observable; -import rx.exceptions.Exceptions; -import rx.functions.Func1; + /* Copyright 2016 Patrick Löwenstein * @@ -71,39 +69,19 @@ public static Observable.Transformer filt @Override public Observable call(Observable observable) { if(type != null) { - observable = observable.filter(new Func1() { - @Override - public Boolean call(DataEvent dataEvent) { - return dataEvent.getType() == type; - } - }); + observable = observable.filter(dataEvent -> dataEvent.getType() == type); } if(path != null) { - observable = observable.filter(new Func1() { - @Override - public Boolean call(DataEvent dataEvent) { - if (isPrefix) { - return dataEvent.getDataItem().getUri().getPath().startsWith(path); - } else { - return dataEvent.getDataItem().getUri().getPath().equals(path); - } + observable = observable.filter(dataEvent -> { + if (isPrefix) { + return dataEvent.getDataItem().getUri().getPath().startsWith(path); + } else { + return dataEvent.getDataItem().getUri().getPath().equals(path); } }); } - return observable.map(new Func1() { - @SuppressWarnings({"unchecked", "ThrowableResultOfMethodCallIgnored"}) - @Override - public T call(DataEvent dataEvent) { - try { - ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(dataEvent.getDataItem().getData())); - return (T) objectInputStream.readObject(); - } catch(Exception e) { - Exceptions.propagate(e); - return null; - } - } - }); + return observable.map(dataEvent -> IOUtil.readObjectFromByteArray(dataEvent.getDataItem().getData())); } } diff --git a/library/src/main/java/com/patloew/rxwear/transformers/DataItemGetDataMap.java b/library/src/main/java/com/patloew/rxwear/transformers/DataItemGetDataMap.java index 79e11af..d081d3b 100644 --- a/library/src/main/java/com/patloew/rxwear/transformers/DataItemGetDataMap.java +++ b/library/src/main/java/com/patloew/rxwear/transformers/DataItemGetDataMap.java @@ -5,7 +5,6 @@ import com.google.android.gms.wearable.DataMapItem; import rx.Observable; -import rx.functions.Func1; /* Copyright 2016 Patrick Löwenstein * @@ -51,23 +50,15 @@ public static Observable.Transformer filterByPathPrefix(Strin @Override public Observable call(Observable observable) { if(path != null) { - observable = observable.filter(new Func1() { - @Override - public Boolean call(DataItem dataItem) { - if (isPrefix) { - return dataItem.getUri().getPath().startsWith(path); - } else { - return dataItem.getUri().getPath().equals(path); - } + observable = observable.filter(dataItem -> { + if (isPrefix) { + return dataItem.getUri().getPath().startsWith(path); + } else { + return dataItem.getUri().getPath().equals(path); } }); } - return observable.map(new Func1() { - @Override - public DataMap call(DataItem dataItem) { - return DataMapItem.fromDataItem(dataItem).getDataMap(); - } - }); + return observable.map(dataItem -> DataMapItem.fromDataItem(dataItem).getDataMap()); } } diff --git a/library/src/main/java/com/patloew/rxwear/transformers/DataItemGetSerializable.java b/library/src/main/java/com/patloew/rxwear/transformers/DataItemGetSerializable.java index 4e0169e..f21c522 100644 --- a/library/src/main/java/com/patloew/rxwear/transformers/DataItemGetSerializable.java +++ b/library/src/main/java/com/patloew/rxwear/transformers/DataItemGetSerializable.java @@ -1,14 +1,11 @@ package com.patloew.rxwear.transformers; import com.google.android.gms.wearable.DataItem; +import com.patloew.rxwear.IOUtil; -import java.io.ByteArrayInputStream; -import java.io.ObjectInputStream; import java.io.Serializable; import rx.Observable; -import rx.exceptions.Exceptions; -import rx.functions.Func1; /* Copyright 2016 Patrick Löwenstein * @@ -55,30 +52,15 @@ public static Observable.Transformer filte @Override public Observable call(Observable observable) { if(path != null) { - observable = observable.filter(new Func1() { - @Override - public Boolean call(DataItem dataItem) { - if (isPrefix) { - return dataItem.getUri().getPath().startsWith(path); - } else { - return dataItem.getUri().getPath().equals(path); - } + observable = observable.filter(dataItem -> { + if (isPrefix) { + return dataItem.getUri().getPath().startsWith(path); + } else { + return dataItem.getUri().getPath().equals(path); } }); } - return observable.map(new Func1() { - @SuppressWarnings({"unchecked", "ThrowableResultOfMethodCallIgnored"}) - @Override - public T call(DataItem dataItem) { - try { - ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(dataItem.getData())); - return (T) objectInputStream.readObject(); - } catch(Exception e) { - Exceptions.propagate(e); - return null; - } - } - }); + return observable.map(dataItem -> IOUtil.readObjectFromByteArray(dataItem.getData())); } } diff --git a/library/src/main/java/com/patloew/rxwear/transformers/MessageEventGetDataMap.java b/library/src/main/java/com/patloew/rxwear/transformers/MessageEventGetDataMap.java index 1eff7f5..24b4c5b 100644 --- a/library/src/main/java/com/patloew/rxwear/transformers/MessageEventGetDataMap.java +++ b/library/src/main/java/com/patloew/rxwear/transformers/MessageEventGetDataMap.java @@ -4,7 +4,6 @@ import com.google.android.gms.wearable.MessageEvent; import rx.Observable; -import rx.functions.Func1; /* Copyright 2016 Patrick Löwenstein * @@ -50,23 +49,15 @@ public static Observable.Transformer filterByPathPrefix(S @Override public Observable call(Observable observable) { if(path != null) { - observable = observable.filter(new Func1() { - @Override - public Boolean call(MessageEvent messageEvent) { - if (isPrefix) { - return messageEvent.getPath().startsWith(path); - } else { - return messageEvent.getPath().equals(path); - } + observable = observable.filter(messageEvent -> { + if (isPrefix) { + return messageEvent.getPath().startsWith(path); + } else { + return messageEvent.getPath().equals(path); } }); } - return observable.map(new Func1() { - @Override - public DataMap call(MessageEvent messageEvent) { - return DataMap.fromByteArray(messageEvent.getData()); - } - }); + return observable.map(messageEvent -> DataMap.fromByteArray(messageEvent.getData())); } } diff --git a/library/src/main/java/com/patloew/rxwear/transformers/MessageEventGetSerializable.java b/library/src/main/java/com/patloew/rxwear/transformers/MessageEventGetSerializable.java index f89da97..7936737 100644 --- a/library/src/main/java/com/patloew/rxwear/transformers/MessageEventGetSerializable.java +++ b/library/src/main/java/com/patloew/rxwear/transformers/MessageEventGetSerializable.java @@ -1,14 +1,11 @@ package com.patloew.rxwear.transformers; import com.google.android.gms.wearable.MessageEvent; +import com.patloew.rxwear.IOUtil; -import java.io.ByteArrayInputStream; -import java.io.ObjectInputStream; import java.io.Serializable; import rx.Observable; -import rx.exceptions.Exceptions; -import rx.functions.Func1; /* Copyright 2016 Patrick Löwenstein * @@ -56,30 +53,15 @@ public static Observable.Transformer f @Override public Observable call(Observable observable) { if(path != null) { - observable = observable.filter(new Func1() { - @Override - public Boolean call(MessageEvent messageEvent) { - if (isPrefix) { - return messageEvent.getPath().startsWith(path); - } else { - return messageEvent.getPath().equals(path); - } + observable = observable.filter(messageEvent -> { + if (isPrefix) { + return messageEvent.getPath().startsWith(path); + } else { + return messageEvent.getPath().equals(path); } }); } - return observable.map(new Func1() { - @SuppressWarnings({"unchecked", "ThrowableResultOfMethodCallIgnored"}) - @Override - public T call(MessageEvent messageEvent) { - try { - ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(messageEvent.getData())); - return (T) objectInputStream.readObject(); - } catch(Exception e) { - Exceptions.propagate(e); - return null; - } - } - }); + return observable.map(messageEvent -> IOUtil.readObjectFromByteArray(messageEvent.getData())); } } \ No newline at end of file diff --git a/library/src/test/java/com/patloew/rxwear/RxWearTest.java b/library/src/test/java/com/patloew/rxwear/RxWearTest.java index fdb09ac..e89179c 100644 --- a/library/src/test/java/com/patloew/rxwear/RxWearTest.java +++ b/library/src/test/java/com/patloew/rxwear/RxWearTest.java @@ -61,6 +61,7 @@ import rx.observers.TestSubscriber; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; /* Copyright 2016 Patrick Löwenstein @@ -101,12 +102,14 @@ public class RxWearTest { @Mock MessageApi messageApi; @Mock NodeApi nodeApi; - @Mock RxWear rxWear; + RxWear rxWear; @Before public void setup() { MockitoAnnotations.initMocks(this); + rxWear = new RxWear(ctx); + PowerMockito.mockStatic(Wearable.class); Whitebox.setInternalState(Wearable.class, capabilityApi); Whitebox.setInternalState(Wearable.class, channelApi); @@ -114,7 +117,8 @@ public void setup() { Whitebox.setInternalState(Wearable.class, messageApi); Whitebox.setInternalState(Wearable.class, nodeApi); - when(ctx.getApplicationContext()).thenReturn(ctx); + doReturn(status).when(status).getStatus(); + doReturn(ctx).when(ctx).getApplicationContext(); } ////////////////// @@ -129,21 +133,15 @@ private void setupBaseObservableSuccess(final BaseObservable baseObservab // Mock GoogleApiClient connection success behaviour private void setupBaseObservableSuccess(final BaseObservable baseObservable, final GoogleApiClient apiClient) { - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - final Subscriber subscriber = ((BaseObservable.ApiClientConnectionCallbacks)invocation.getArguments()[0]).subscriber; - - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - baseObservable.onGoogleApiClientReady(apiClient, subscriber); - return null; - } - }).when(apiClient).connect(); - - return apiClient; - } + doAnswer(invocation -> { + final Subscriber subscriber = invocation.getArgumentAt(0, BaseObservable.ApiClientConnectionCallbacks.class).subscriber; + + doAnswer(invocation1 -> { + baseObservable.onGoogleApiClientReady(apiClient, subscriber); + return null; + }).when(apiClient).connect(); + + return apiClient; }).when(baseObservable).createApiClient(Matchers.any(BaseRx.ApiClientConnectionCallbacks.class)); } @@ -154,73 +152,52 @@ private void setupBaseSingleSuccess(final BaseSingle baseSingle) { // Mock GoogleApiClient connection success behaviour private void setupBaseSingleSuccess(final BaseSingle baseSingle, final GoogleApiClient apiClient) { - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - final SingleSubscriber subscriber = ((BaseSingle.ApiClientConnectionCallbacks)invocation.getArguments()[0]).subscriber; - - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - baseSingle.onGoogleApiClientReady(apiClient, subscriber); - return null; - } - }).when(apiClient).connect(); - - return apiClient; - } + doAnswer(invocation -> { + final SingleSubscriber subscriber = invocation.getArgumentAt(0, BaseSingle.ApiClientConnectionCallbacks.class).subscriber; + + doAnswer(invocation1 -> { + baseSingle.onGoogleApiClientReady(apiClient, subscriber); + return null; + }).when(apiClient).connect(); + + return apiClient; }).when(baseSingle).createApiClient(Matchers.any(BaseRx.ApiClientConnectionCallbacks.class)); } // Mock GoogleApiClient connection error behaviour private void setupBaseObservableError(final BaseObservable baseObservable) { - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - final Subscriber subscriber = ((BaseObservable.ApiClientConnectionCallbacks)invocation.getArguments()[0]).subscriber; - - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - subscriber.onError(new GoogleAPIConnectionException("Error connecting to GoogleApiClient.", connectionResult)); - return null; - } - }).when(apiClient).connect(); - - return apiClient; - } + doAnswer(invocation -> { + final Subscriber subscriber = invocation.getArgumentAt(0, BaseObservable.ApiClientConnectionCallbacks.class).subscriber; + + doAnswer(invocation1 -> { + subscriber.onError(new GoogleAPIConnectionException("Error connecting to GoogleApiClient.", connectionResult)); + return null; + }).when(apiClient).connect(); + + return apiClient; }).when(baseObservable).createApiClient(Matchers.any(BaseRx.ApiClientConnectionCallbacks.class)); } // Mock GoogleApiClient connection error behaviour private void setupBaseSingleError(final BaseSingle baseSingle) { - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - final SingleSubscriber subscriber = ((BaseSingle.ApiClientConnectionCallbacks)invocation.getArguments()[0]).subscriber; - - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - subscriber.onError(new GoogleAPIConnectionException("Error connecting to GoogleApiClient.", connectionResult)); - return null; - } - }).when(apiClient).connect(); - - return apiClient; - } + doAnswer(invocation -> { + final SingleSubscriber subscriber = invocation.getArgumentAt(0, BaseSingle.ApiClientConnectionCallbacks.class).subscriber; + + doAnswer(invocation1 -> { + subscriber.onError(new GoogleAPIConnectionException("Error connecting to GoogleApiClient.", connectionResult)); + return null; + }).when(apiClient).connect(); + + return apiClient; }).when(baseSingle).createApiClient(Matchers.any(BaseRx.ApiClientConnectionCallbacks.class)); } @SuppressWarnings("unchecked") private void setPendingResultValue(final Result result) { - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - ((ResultCallback)invocation.getArguments()[0]).onResult(result); - return null; - } - }).when(pendingResult).setResultCallback(Matchers.any()); + doAnswer(invocation -> { + invocation.getArgumentAt(0, ResultCallback.class).onResult(result); + return null; + }).when(pendingResult).setResultCallback(Matchers.any()); } private static void assertError(TestSubscriber sub, Class errorClass) { diff --git a/sample/build.gradle b/sample/build.gradle index 630ddd6..545c498 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -2,13 +2,13 @@ apply plugin: 'com.android.application' apply plugin: 'me.tatarka.retrolambda' android { - compileSdkVersion 23 - buildToolsVersion "23.0.2" + compileSdkVersion 25 + buildToolsVersion "25.0.0" defaultConfig { applicationId "com.patloew.rxwearsample" minSdkVersion 14 - targetSdkVersion 23 + targetSdkVersion 25 versionCode 1 versionName "1.0.0" } @@ -33,16 +33,16 @@ dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' - compile 'com.android.support:appcompat-v7:23.4.0' - compile "com.android.support:design:23.4.0" - compile "com.android.support:gridlayout-v7:23.4.0" + compile 'com.android.support:appcompat-v7:25.0.0' + compile "com.android.support:design:25.0.0" + compile "com.android.support:gridlayout-v7:25.0.0" compile project(':library') - //compile 'com.patloew.rxwear:rxwear:1.2.0' + //compile 'com.patloew.rxwear:rxwear:1.3.0' - compile 'io.reactivex:rxjava:1.1.5' - compile 'io.reactivex:rxandroid:1.2.0' + compile 'io.reactivex:rxjava:1.2.1' + compile 'io.reactivex:rxandroid:1.2.1' compile 'com.jakewharton.rxbinding:rxbinding:0.4.0' - compile 'com.google.android.gms:play-services-wearable:8.4.0' + compile 'com.google.android.gms:play-services-wearable:9.8.0' } diff --git a/sample/src/main/java/com/patloew/rxwearsample/MainActivity.java b/sample/src/main/java/com/patloew/rxwearsample/MainActivity.java index 6377919..7fec3a2 100644 --- a/sample/src/main/java/com/patloew/rxwearsample/MainActivity.java +++ b/sample/src/main/java/com/patloew/rxwearsample/MainActivity.java @@ -12,11 +12,16 @@ import android.widget.EditText; import com.jakewharton.rxbinding.view.RxView; +import com.patloew.rxwear.Data; import com.patloew.rxwear.GoogleAPIConnectionException; +import com.patloew.rxwear.Message; import com.patloew.rxwear.RxWear; import com.patloew.rxwear.transformers.DataItemGetDataMap; +import rx.Emitter; import rx.Observable; +import rx.Single; +import rx.functions.Action1; import rx.subscriptions.CompositeSubscription; public class MainActivity extends AppCompatActivity { @@ -31,13 +36,14 @@ public class MainActivity extends AppCompatActivity { private CompositeSubscription subscription = new CompositeSubscription(); private Observable validator; + private RxWear rxWear; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - RxWear.init(this); + rxWear = new RxWear(this); coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinator_layout); titleEditText = (EditText) findViewById(R.id.et_title); @@ -50,8 +56,7 @@ protected void onCreate(Bundle savedInstanceState) { .doOnNext(click -> hideKeyboard()) .flatMap(click2 -> validate()) .filter(isValid -> isValid) - .flatMap(valid -> - RxWear.Message.SendDataMap.toAllRemoteNodes("/message") + .flatMap(valid -> rxWear.message().sendDataMapToAllRemoteNodes("/message") .putString("title", titleEditText.getText().toString()) .putString("message", messageEditText.getText().toString()) .toObservable() @@ -69,7 +74,7 @@ protected void onCreate(Bundle savedInstanceState) { subscription.add(RxView.clicks(setPersistentButton) .doOnNext(click -> hideKeyboard()) - .flatMap(click2 -> RxWear.Data.PutDataMap.to("/persistentText").setUrgent().putString("text", persistentEditText.getText().toString()).toObservable()) + .flatMap(click2 -> rxWear.data().putDataMap().urgent().to("/persistentText").putString("text", persistentEditText.getText().toString()).toObservable()) .subscribe(dataItem1 -> Snackbar.make(coordinatorLayout, "Set persistent text", Snackbar.LENGTH_LONG).show(), throwable -> { Log.e("MainActivity", "Error on setting persistent text", throwable); @@ -81,7 +86,7 @@ protected void onCreate(Bundle savedInstanceState) { } })); - subscription.add(RxWear.Data.get("/persistentText") + subscription.add(rxWear.data().get("/persistentText") .compose(DataItemGetDataMap.noFilter()) .map(dataMap -> dataMap.getString("text")) .subscribe(text -> persistentEditText.setText(text))); @@ -103,21 +108,20 @@ private void hideKeyboard() { private Observable validate() { if(validator == null) { - validator = Observable.create((Observable.OnSubscribe) subscriber -> { + validator = Observable.fromCallable(() -> { boolean valid = true; - if(TextUtils.isEmpty(titleEditText.getText())) { + if (TextUtils.isEmpty(titleEditText.getText())) { titleEditText.setError("Please enter title"); valid = false; } - if(TextUtils.isEmpty(messageEditText.getText())) { + if (TextUtils.isEmpty(messageEditText.getText())) { messageEditText.setError("Please enter message"); valid = false; } - subscriber.onNext(valid); - subscriber.onCompleted(); + return valid; }); } diff --git a/wearsample/build.gradle b/wearsample/build.gradle index 7d80f02..d6f55b7 100644 --- a/wearsample/build.gradle +++ b/wearsample/build.gradle @@ -2,13 +2,13 @@ apply plugin: 'com.android.application' apply plugin: 'me.tatarka.retrolambda' android { - compileSdkVersion 23 - buildToolsVersion "23.0.2" + compileSdkVersion 25 + buildToolsVersion "25.0.0" defaultConfig { applicationId "com.patloew.rxwearsample" minSdkVersion 22 - targetSdkVersion 23 + targetSdkVersion 25 versionCode 1 versionName "1.0.0" } @@ -31,13 +31,13 @@ retrolambda { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.google.android.support:wearable:1.3.0' - compile 'com.google.android.gms:play-services-wearable:8.4.0' + compile 'com.google.android.support:wearable:1.4.0' + compile 'com.google.android.gms:play-services-wearable:9.8.0' compile project(':library') - //compile 'com.patloew.rxwear:rxwear:1.2.0' + //compile 'com.patloew.rxwear:rxwear:1.3.0' - compile 'io.reactivex:rxjava:1.1.5' - compile 'io.reactivex:rxandroid:1.2.0' + compile 'io.reactivex:rxjava:1.2.1' + compile 'io.reactivex:rxandroid:1.2.1' compile 'com.jakewharton.rxbinding:rxbinding:0.4.0' } diff --git a/wearsample/src/main/java/com/patloew/rxwearsample/MainActivity.java b/wearsample/src/main/java/com/patloew/rxwearsample/MainActivity.java index fe5ee23..19469a4 100644 --- a/wearsample/src/main/java/com/patloew/rxwearsample/MainActivity.java +++ b/wearsample/src/main/java/com/patloew/rxwearsample/MainActivity.java @@ -9,6 +9,8 @@ import com.google.android.gms.wearable.DataApi; import com.google.android.gms.wearable.DataEvent; import com.google.android.gms.wearable.MessageApi; +import com.patloew.rxwear.Data; +import com.patloew.rxwear.Message; import com.patloew.rxwear.RxWear; import com.patloew.rxwear.transformers.DataEventGetDataMap; import com.patloew.rxwear.transformers.DataItemGetDataMap; @@ -26,6 +28,8 @@ public class MainActivity extends WearableActivity { private CompositeSubscription subscription = new CompositeSubscription(); + private RxWear rxWear; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -37,9 +41,9 @@ protected void onCreate(Bundle savedInstanceState) { mMessageText = (TextView) findViewById(R.id.message); mPersistentText = (TextView) findViewById(R.id.persistent); - RxWear.init(this); + rxWear = new RxWear(this); - subscription.add(RxWear.Message.listen("/message", MessageApi.FILTER_LITERAL) + subscription.add(rxWear.message().listen("/message", MessageApi.FILTER_LITERAL) .compose(MessageEventGetDataMap.noFilter()) .subscribe(dataMap -> { mTitleText.setText(dataMap.getString("title", getString(R.string.no_message))); @@ -48,8 +52,8 @@ protected void onCreate(Bundle savedInstanceState) { subscription.add( Observable.concat( - RxWear.Data.get("/persistentText").compose(DataItemGetDataMap.noFilter()), - RxWear.Data.listen("/persistentText", DataApi.FILTER_LITERAL).compose(DataEventGetDataMap.filterByType(DataEvent.TYPE_CHANGED)) + rxWear.data().get("/persistentText").compose(DataItemGetDataMap.noFilter()), + rxWear.data().listen("/persistentText", DataApi.FILTER_LITERAL).compose(DataEventGetDataMap.filterByType(DataEvent.TYPE_CHANGED)) ).map(dataMap -> dataMap.getString("text")) .subscribe(text -> mPersistentText.setText(text), throwable -> Toast.makeText(this, "Error on data listen", Toast.LENGTH_LONG))