@Test public void testAsyncChild() { TestSubscriber<Integer> ts = new TestSubscriber<Integer>(); Observable.range(0, 100000) .observeOn(Schedulers.newThread()) .observeOn(Schedulers.newThread()) .subscribe(ts); ts.awaitTerminalEvent(); ts.assertNoErrors(); }
/** Confirm that running on a NewThreadScheduler uses the same thread for the entire stream */ @Test public void testObserveOnWithNewThreadScheduler() { final AtomicInteger count = new AtomicInteger(); final int _multiple = 99; Observable.range(1, 100000) .map( new Func1<Integer, Integer>() { @Override public Integer call(Integer t1) { return t1 * _multiple; } }) .observeOn(Schedulers.newThread()) .toBlocking() .forEach( new Action1<Integer>() { @Override public void call(Integer t1) { assertEquals(count.incrementAndGet() * _multiple, t1.intValue()); assertTrue(Thread.currentThread().getName().startsWith("RxNewThreadScheduler")); } }); }
@Override public void onUpdate( final Context context, final AppWidgetManager appWidgetManager, int[] appWidgetIds) { Log.d("TAG", "onUpdate"); ComponentName thisWidget = new ComponentName(context, WeatherWidgetProvider.class); final int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget); WidgetManager widgetManager = new WidgetManager(context); widgetManager .fetchWeatherDataForWidget() .subscribeOn(Schedulers.newThread()) .subscribe( new Subscriber<CityWeather>() { @Override public void onCompleted() {} @Override public void onError(Throwable e) {} @Override public void onNext(CityWeather cityWeather) { updateWeatherData(context, appWidgetManager, allWidgetIds, cityWeather); } }); super.onUpdate(context, appWidgetManager, appWidgetIds); }
@Test public void testBackpressureWithTakeBefore() { final AtomicInteger generated = new AtomicInteger(); Observable<Integer> observable = Observable.from( new Iterable<Integer>() { @Override public Iterator<Integer> iterator() { return new Iterator<Integer>() { @Override public void remove() {} @Override public Integer next() { return generated.getAndIncrement(); } @Override public boolean hasNext() { return true; } }; } }); TestSubscriber<Integer> testSubscriber = new TestSubscriber<Integer>(); observable.take(7).observeOn(Schedulers.newThread()).subscribe(testSubscriber); testSubscriber.awaitTerminalEvent(); testSubscriber.assertReceivedOnNext(Arrays.asList(0, 1, 2, 3, 4, 5, 6)); assertEquals(7, generated.get()); }
// 加载Apk private void loadApks() { // 异步加载, 防止Apk过多, 影响速度 Observable.just(getApkFromInstall()) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(mApkListAdapter::setApkItems); }
/** * Makes an API call to get the top or recent Kus. Checks that it isn't an empty dataset and * updates the view Uses the KuCardAdapter class for button functionality and loading data */ public void UpdateKus(String sort) { ApiClient.getKukyApiClient(AuthHelper.getCreds(getContext())) .getKus(sort, String.valueOf(getUserId())) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( new Subscriber<KuListResponse>() { @Override public final void onCompleted() { // do nothing } @Override public final void onError(Throwable e) { Log.e("KukyAPI Error", e.getMessage()); } @Override public final void onNext(KuListResponse response) { mkuList = response.getKus(); checkForKus(mkuList); mKuCardAdapter.setList(mkuList); mKuCardAdapter.notifyDataSetChanged(); Log.d(TAG, "Received data"); } }); }
public void onServiceConnected(ComponentName className, IBinder service) { // mService = new Messenger(service); rviService = ((RviService.RviBinder) service).getService(); rviService .servicesAvailable() .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( new Observer<String>() { @Override public void onCompleted() {} @Override public void onError(Throwable e) {} @Override public void onNext(String s) { Log.i(TAG, "X: " + s); fragment.onNewServiceDiscovered(s); // Toast.makeText(LockActivity.this, "X: "+s, Toast.LENGTH_SHORT).show(); } }); // Tell the user about this for our demo. Toast.makeText(LockActivity.this, "RVI service connected", Toast.LENGTH_SHORT).show(); }
private void startPresentation(String tag) { RestClient.service() .presentationJoin(presentation.getId(), user.getId(), tag) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .compose(this.<BaseResponse>bindToLifecycle()) .subscribe( new Action1<BaseResponse>() { @Override public void call(BaseResponse joinResponse) { UnityActivity.startActivity(NfcDetectActivity.this, user, presentation); } }, new Action1<Throwable>() { @Override public void call(Throwable throwable) { throwable.printStackTrace(); Toast.makeText( NfcDetectActivity.this, "Unable to join, try again!", Toast.LENGTH_LONG) .show(); } }); }
@Test public void testMergeAsyncThenObserveOn() { int NUM = (int) (RxRingBuffer.SIZE * 4.1); AtomicInteger c1 = new AtomicInteger(); AtomicInteger c2 = new AtomicInteger(); TestSubscriber<Integer> ts = new TestSubscriber<Integer>(); Observable<Integer> merged = Observable.merge( incrementingIntegers(c1).subscribeOn(Schedulers.computation()), incrementingIntegers(c2).subscribeOn(Schedulers.computation())); merged.observeOn(Schedulers.newThread()).take(NUM).subscribe(ts); ts.awaitTerminalEvent(); ts.assertNoErrors(); System.out.println( "testMergeAsyncThenObserveOn => Received: " + ts.getOnNextEvents().size() + " Emitted: " + c1.get() + " / " + c2.get()); assertEquals(NUM, ts.getOnNextEvents().size()); // either one can starve the other, but neither should be capable of doing more than 5 batches // (taking 4.1) // TODO is it possible to make this deterministic rather than one possibly starving the other? // benjchristensen => In general I'd say it's not worth trying to make it so, as "fair" // algoritms generally take a performance hit // akarnokd => run this in a loop over 10k times and never saw values get as high as 7*SIZE, but // since observeOn delays the unsubscription non-deterministically, the test will remain // unreliable assertTrue(c1.get() < RxRingBuffer.SIZE * 7); assertTrue(c2.get() < RxRingBuffer.SIZE * 7); }
public Observable<List<TwitterUser>> searchUsers(String prefix) { if (ThreadLocalRandom.current().nextDouble() < failureProbability) { return Observable.error(new IOException("Broken pipe")); } return Observable.from(users).skip(1).toList().subscribeOn(Schedulers.newThread()); }
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: finish(); break; case R.id.save: subscription = Observable.create( new Observable.OnSubscribe<File>() { @Override public void call(Subscriber<? super File> subscriber) { try { File f = Glide.with(PhotoActivity.this) .load(url) .downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) .get() // needs to be called on background thread ; subscriber.onNext(f); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }) .subscribeOn(Schedulers.newThread()) .observeOn(Schedulers.io()) .map( new Func1<File, String>() { @Override public String call(File file) { Log.i("path", file.getPath()); FileUtil.copyFile( file.getPath(), Environment.getExternalStorageDirectory() + "/friends/" + url.substring(url.lastIndexOf("/") + 1)); return file.getPath(); } }) .observeOn(AndroidSchedulers.mainThread()) .subscribe( new Action1<String>() { @Override public void call(String s) { toast( "已保存至" + Environment.getExternalStorageDirectory() + "/friends/" + url.substring(url.lastIndexOf("/") + 1)); } }); break; } return super.onOptionsItemSelected(item); }
@Test public void testNonBlockingOuterWhileBlockingOnNext() throws InterruptedException { final CountDownLatch completedLatch = new CountDownLatch(1); final CountDownLatch nextLatch = new CountDownLatch(1); final AtomicLong completeTime = new AtomicLong(); // use subscribeOn to make async, observeOn to move Observable.range(1, 2) .subscribeOn(Schedulers.newThread()) .observeOn(Schedulers.newThread()) .subscribe( new Observer<Integer>() { @Override public void onCompleted() { System.out.println("onCompleted"); completeTime.set(System.nanoTime()); completedLatch.countDown(); } @Override public void onError(Throwable e) {} @Override public void onNext(Integer t) { // don't let this thing finish yet try { if (!nextLatch.await(1000, TimeUnit.MILLISECONDS)) { throw new RuntimeException("it shouldn't have timed out"); } } catch (InterruptedException e) { throw new RuntimeException("it shouldn't have failed"); } } }); long afterSubscribeTime = System.nanoTime(); System.out.println("After subscribe: " + completedLatch.getCount()); assertEquals(1, completedLatch.getCount()); nextLatch.countDown(); completedLatch.await(1000, TimeUnit.MILLISECONDS); assertTrue(completeTime.get() > afterSubscribeTime); System.out.println( "onComplete nanos after subscribe: " + (completeTime.get() - afterSubscribeTime)); }
@Override public void checkFavoritesAndSetIcon(int articleId) { Repository.FavoritesRepository favoritesRepository = SQLiteFavoritesRepository.getInstance(); Observable.fromCallable(() -> favoritesRepository.isInFavorites(articleId)) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> view.setFavoritesButton(result)); }
@Test @SuppressWarnings("unchecked") public void testThreadName() throws InterruptedException { System.out.println("Main Thread: " + Thread.currentThread().getName()); Observable<String> obs = Observable.just("one", null, "two", "three", "four"); Observer<String> observer = mock(Observer.class); final String parentThreadName = Thread.currentThread().getName(); final CountDownLatch completedLatch = new CountDownLatch(1); // assert subscribe is on main thread obs = obs.doOnNext( new Action1<String>() { @Override public void call(String s) { String threadName = Thread.currentThread().getName(); System.out.println( "Source ThreadName: " + threadName + " Expected => " + parentThreadName); assertEquals(parentThreadName, threadName); } }); // assert observe is on new thread obs.observeOn(Schedulers.newThread()) .doOnNext( new Action1<String>() { @Override public void call(String t1) { String threadName = Thread.currentThread().getName(); boolean correctThreadName = threadName.startsWith("RxNewThreadScheduler"); System.out.println( "ObserveOn ThreadName: " + threadName + " Correct => " + correctThreadName); assertTrue(correctThreadName); } }) .finallyDo( new Action0() { @Override public void call() { completedLatch.countDown(); } }) .subscribe(observer); if (!completedLatch.await(1000, TimeUnit.MILLISECONDS)) { fail("timed out waiting"); } verify(observer, never()).onError(any(Throwable.class)); verify(observer, times(5)).onNext(any(String.class)); verify(observer, times(1)).onCompleted(); }
@Test public void testQueueFullEmitsError() { final CountDownLatch latch = new CountDownLatch(1); Observable<Integer> observable = Observable.create( new OnSubscribe<Integer>() { @Override public void call(Subscriber<? super Integer> o) { for (int i = 0; i < RxRingBuffer.SIZE + 10; i++) { o.onNext(i); } latch.countDown(); o.onCompleted(); } }); TestSubscriber<Integer> testSubscriber = new TestSubscriber<Integer>( new Observer<Integer>() { @Override public void onCompleted() {} @Override public void onError(Throwable e) {} @Override public void onNext(Integer t) { // force it to be slow and wait until we have queued everything try { latch.await(500, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { e.printStackTrace(); } } }); observable.observeOn(Schedulers.newThread()).subscribe(testSubscriber); testSubscriber.awaitTerminalEvent(); List<Throwable> errors = testSubscriber.getOnErrorEvents(); assertEquals(1, errors.size()); System.out.println("Errors: " + errors); Throwable t = errors.get(0); if (t instanceof MissingBackpressureException) { // success, we expect this } else { if (t.getCause() instanceof MissingBackpressureException) { // this is also okay } else { fail("Expecting MissingBackpressureException"); } } }
@Test(timeout = 2000) public void testTakeObserveOn() { @SuppressWarnings("unchecked") Observer<Object> o = mock(Observer.class); INFINITE_OBSERVABLE.observeOn(Schedulers.newThread()).take(1).subscribe(o); verify(o).onNext(1L); verify(o, never()).onNext(2L); verify(o).onCompleted(); verify(o, never()).onError(any(Throwable.class)); }
@OnClick(R.id.button) public void phetch() { PhetchService service = ((ExampleApplication) getApplication()).getPhetchService(); service .getAsinsByStockId(Collections.singletonList("32735136")) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( asinStocks -> { mTextView.setText(asinStocks.get(0).asin + "::" + asinStocks.get(0).stockId); }); }
@Override public void onClick(View v) { final ObservableSample observableSample = new ObservableSample(); toastMessage("Subscribing to observables...Check logcat output..."); observableSample .strings() .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new MySubscriber()); observableSample .stringsWithError() .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new MySubscriber()); observableSample .numbersBackpressure() .onBackpressureDrop() .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new MySubscriberBackpressure()); }
public static Observable<Integer> hotStream() { return Observable.create( (Subscriber<? super Integer> s) -> { while (!s.isUnsubscribed()) { for (int i = 0; i < Math.random() * 20; i++) { s.onNext(i); } try { Thread.sleep((long) (Math.random() * 1000)); } catch (Exception e) { } } }) .subscribeOn(Schedulers.newThread()); }
// hot -> we need to subscribe to it for it to start emitting any items public static Observable<Integer> hotStream() { return Observable.create( (Subscriber<? super Integer> s) -> { int i = 0; while (!s.isUnsubscribed()) { s.onNext(i++); try { // sleep for a random amount of time Thread.sleep((long) (Math.random() * 100)); } catch (Exception e) { // do nothing } } }) .subscribeOn(Schedulers.newThread()); }
@Test public void testErrorPropagatesWhenNoOutstandingRequests() { Observable<Long> timer = Observable.timer(0, 1, TimeUnit.MICROSECONDS) .doOnEach( new Action1<Notification<? super Long>>() { @Override public void call(Notification<? super Long> n) { // System.out.println("BEFORE " + // n); } }) .observeOn(Schedulers.newThread()) .doOnEach( new Action1<Notification<? super Long>>() { @Override public void call(Notification<? super Long> n) { try { Thread.sleep(100); } catch (InterruptedException e) { } // System.out.println("AFTER " + // n); } }); TestSubscriber<Long> ts = new TestSubscriber<Long>(); Observable.combineLatest( timer, Observable.<Integer>never(), new Func2<Long, Integer, Long>() { @Override public Long call(Long t1, Integer t2) { return t1; } }) .take(RxRingBuffer.SIZE * 2) .subscribe(ts); ts.awaitTerminalEvent(); assertEquals(1, ts.getOnErrorEvents().size()); assertEquals(MissingBackpressureException.class, ts.getOnErrorEvents().get(0).getClass()); }
@Test public void testBackpressureWithTakeAfter() { final AtomicInteger generated = new AtomicInteger(); Observable<Integer> observable = Observable.from( new Iterable<Integer>() { @Override public Iterator<Integer> iterator() { return new Iterator<Integer>() { @Override public void remove() {} @Override public Integer next() { return generated.getAndIncrement(); } @Override public boolean hasNext() { return true; } }; } }); TestSubscriber<Integer> testSubscriber = new TestSubscriber<Integer>() { @Override public void onNext(Integer t) { System.err.println("c t = " + t + " thread " + Thread.currentThread()); super.onNext(t); try { Thread.sleep(10); } catch (InterruptedException e) { } } }; observable.observeOn(Schedulers.newThread()).take(3).subscribe(testSubscriber); testSubscriber.awaitTerminalEvent(); System.err.println(testSubscriber.getOnNextEvents()); testSubscriber.assertReceivedOnNext(Arrays.asList(0, 1, 2)); // it should be between the take num and requested batch size across the async boundary System.out.println("Generated: " + generated.get()); assertTrue(generated.get() >= 3 && generated.get() <= RxRingBuffer.SIZE); }
@Test public void testBackpressureWithTakeAfterAndMultipleBatches() { int numForBatches = RxRingBuffer.SIZE * 3 + 1; // should be 4 batches == ((3*n)+1) items final AtomicInteger generated = new AtomicInteger(); Observable<Integer> observable = Observable.from( new Iterable<Integer>() { @Override public Iterator<Integer> iterator() { return new Iterator<Integer>() { @Override public void remove() {} @Override public Integer next() { return generated.getAndIncrement(); } @Override public boolean hasNext() { return true; } }; } }); TestSubscriber<Integer> testSubscriber = new TestSubscriber<Integer>() { @Override public void onNext(Integer t) { // System.err.println("c t = " + t + " thread " + // Thread.currentThread()); super.onNext(t); } }; observable.observeOn(Schedulers.newThread()).take(numForBatches).subscribe(testSubscriber); testSubscriber.awaitTerminalEvent(); System.err.println(testSubscriber.getOnNextEvents()); // it should be between the take num and requested batch size across the async boundary System.out.println("Generated: " + generated.get()); assertTrue( generated.get() >= numForBatches && generated.get() <= numForBatches + RxRingBuffer.SIZE); }
/** * Connect to first device of bonded devices. Useful when you have only one device paired. See * also {@link BlueDuff#connectToDevice(BluetoothDevice, BlueInterfaces.OnConnectedCallback, * BlueInterfaces.DataReceivedCallback)} * * @param onConnectedCallback send first packet of bytes. You can also swich between views here * @param dataReceivedCallback is being called every time bluetooth adapter receives bytes from * device */ @RequiresPermission(BLUETOOTH) public rx.Subscription connectToFirstDevice( final BlueInterfaces.OnConnectedCallback onConnectedCallback, final BlueInterfaces.DataReceivedCallback dataReceivedCallback) { if (logLevel == LogLevel.VERBOSE) Log.d(TAG, "connectToFirstDevice "); return BlueDuff.getBondedDevices() .flatMap( new Func1<List<BluetoothDevice>, Observable<BluetoothSocket>>() { @Override @RequiresPermission(BLUETOOTH) public Observable<BluetoothSocket> call(List<BluetoothDevice> bluetoothDevices) { if (logLevel == LogLevel.VERBOSE) Log.d(TAG, "call BluetoothSocket observable"); return initCommunication(bluetoothDevices.get(0), ConnectionSecurity.SECURE); } }) .flatMap( new Func1<BluetoothSocket, Observable<Boolean>>() { @Override public Observable<Boolean> call(BluetoothSocket bluetoothSocket) { if (logLevel == LogLevel.VERBOSE) Log.d(TAG, "call BluetoothSocket"); return getStreamsWork(bluetoothSocket, onConnectedCallback, dataReceivedCallback); } }) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.newThread()) .subscribe( new Subscriber<Boolean>() { @Override public void onCompleted() { if (logLevel == LogLevel.VERBOSE) Log.d(TAG, "onCompleted "); } @Override public void onError(Throwable e) { if (logLevel != LogLevel.NONE) e.printStackTrace(); if (onConnectionErrorcallback != null) onConnectionErrorcallback.onError(e); } @Override public void onNext(Boolean aBoolean) { if (logLevel == LogLevel.VERBOSE) Log.d(TAG, "onNext " + aBoolean); } }); }
public static void thread(final MainThread mainThread, final NewThread newThread) { Observable.create( new Observable.OnSubscribe<Message>() { @Override public void call(Subscriber<? super Message> subscriber) { newThread.inNewThread(subscriber); } }) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( new Action1<Message>() { @Override public void call(Message msg) { mainThread.inMainThread(msg); } }); }
@Test public void testNextWithEmpty() { Observable<String> obs = Observable.<String>empty().observeOn(Schedulers.newThread()); Iterator<String> it = next(obs).iterator(); assertFalse(it.hasNext()); try { it.next(); fail("At the end of an iterator should throw a NoSuchElementException"); } catch (NoSuchElementException e) { } // If the observable is completed, hasNext always returns false and next always throw a // NoSuchElementException. assertFalse(it.hasNext()); try { it.next(); fail("At the end of an iterator should throw a NoSuchElementException"); } catch (NoSuchElementException e) { } }
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main_drawer); DaggerGroupComponent.builder() .applicationComponent(getApplicationComponent()) .groupModule(new GroupModule(getAllSendersGroup())) .build() .inject(this); ButterKnife.bind(this); setSupportActionBar((Toolbar) findViewById(R.id.toolbar)); setupDrawer(); if (savedInstanceState == null) { Bundle extras = getIntent().getExtras(); // need to check if group not null since there are some weird stuff going on when using the // launcher if (extras != null && extras.getParcelable(INTENT_EXTRAS_GROUP) != null) { setupFragmentsFromExtras(extras); } else { boolean doesGroupsExists = getSharedPreferences(SHARED_PREFS_NAME, 0) .getBoolean(SHARED_PREFS_GROUPS_EXISTS_KEY, false); if (doesGroupsExists) { addFragment(GroupListFragment.newInstance(), R.id.fl_contentFrame); } else { addFragment(SenderListFragment.newInstance(getAllSendersGroup()), R.id.fl_contentFrame); nw_main.setCheckedItem(R.id.navigation_allSenders); } } if (isFirstLaunch()) { createAllSendersGroupInteractor.execute( new LoggingSubscriber<Long>(), Schedulers.newThread(), AndroidSchedulers.mainThread()); setFirstLaunchDone(); } } }
@Test public void testNumberOfThreadsOnScheduledMerge() { final ConcurrentHashMap<Long, Long> threads = new ConcurrentHashMap<Long, Long>(); // now we parallelMerge into 3 streams and observeOn for each // we expect 3 threads in the output Observable.merge(Observable.parallelMerge(getStreams(), 3, Schedulers.newThread())) .toBlocking() .forEach( new Action1<String>() { @Override public void call(String o) { System.out.println("o: " + o + " Thread: " + Thread.currentThread().getId()); threads.put(Thread.currentThread().getId(), Thread.currentThread().getId()); } }); assertTrue( threads.keySet().size() <= 3); // can be less than since merge doesn't block threads and may not use all of them }
public void loadRepositories() { Observable<Category> call = gingerApiService.getCategoryList(new Location("28.4792943", "77.0430799")); call.observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.newThread()) .retry(5) .subscribe( new Subscriber<Category>() { @Override public void onCompleted() { L.m("Completed"); } @Override public void onError(Throwable e) { if (e instanceof HttpException) { /*ResponseBody body = ((HttpException) e).response().errorBody(); Converter<GlobalErrorObject> converter = (Converter<GlobalErrorObject>) GsonConverterFactory.create().get(GlobalErrorObject.class); try { GlobalErrorObject errorObject = converter.fromBody(body); L.m(errorObject.getErrorMessage()); } catch (IOException e1) { e1.printStackTrace(); }*/ L.m("Error"); } if (e instanceof IOException) { L.m("No Internet"); } } @Override public void onNext(Category category) { L.m(category.getCategories().size() + ""); } }); }
/** * Enables connection to selected device * * @param device BluetoothDevice * @param onConnectedCallback send first packet of bytes. You can also swich between views here * @param dataReceivedCallback is being called every time bluetooth adapter receives bytes from * device */ public rx.Subscription connectToDevice( BluetoothDevice device, final BlueInterfaces.OnConnectedCallback onConnectedCallback, final BlueInterfaces.DataReceivedCallback dataReceivedCallback) { return initCommunication(device, ConnectionSecurity.SECURE) .flatMap( new Func1<BluetoothSocket, Observable<Boolean>>() { @Override public Observable<Boolean> call(BluetoothSocket bluetoothSocket) { return getStreamsWork(bluetoothSocket, onConnectedCallback, dataReceivedCallback); } }) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.newThread()) .subscribe( new Subscriber<Boolean>() { @Override public void onCompleted() { if (logLevel == LogLevel.VERBOSE) Log.d(TAG, "onCompleted "); } @Override public void onError(Throwable e) { if (logLevel != LogLevel.NONE) { Log.e(TAG, "onError " + e.getMessage()); e.printStackTrace(); } if (onConnectionErrorcallback != null) onConnectionErrorcallback.onError(e); } @Override public void onNext(Boolean aBoolean) { if (logLevel == LogLevel.VERBOSE) Log.d(TAG, "onNext " + aBoolean); } }); }