diff --git a/.travis.yml b/.travis.yml
index 8eb672e..1a8b19f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,17 +1,22 @@
 language: android
-android:
-  components:
-    - platform-tools
-    - tools
-    - build-tools-27.0.3
-    - android-27
-    - extra-android-support
-    - extra-android-m2repository
 
-jdk: oraclejdk8
+jdk:
+  - oraclejdk8
 
-before_script:
-    - chmod +x gradlew
+before_install:
+  # Install SDK license so Android Gradle plugin can install deps.
+  - mkdir "$ANDROID_HOME/licenses" || true
+  - echo "d56f5187479451eabf01fb78af6dfcb131a6481e" > "$ANDROID_HOME/licenses/android-sdk-license"
 
-script:
-    ./gradlew build
\ No newline at end of file
+install: true
+
+script: ./gradlew clean build
+
+before_cache:
+  - rm -f  $HOME/.gradle/caches/modules-2/modules-2.lock
+  - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
+cache:
+  directories:
+    - $HOME/.gradle/caches/
+    - $HOME/.gradle/wrapper/
+    - $HOME/.android/build-cache
diff --git a/app/build.gradle b/app/build.gradle
index ec2b8d4..2da0fe6 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -2,7 +2,6 @@ apply plugin: 'com.android.application'
 
 android {
   compileSdkVersion COMPILE_SDK_VERSION
-  buildToolsVersion BUILD_TOOLS_VERSION
 
   defaultConfig {
     applicationId "com.github.ivbaranov.rxbluetooth.example"
@@ -24,6 +23,5 @@ android {
 
 dependencies {
   implementation project(':rxbluetooth')
-  implementation "com.android.support:appcompat-v7:$SUPPORT_LIBRARY_VERSION"
-  implementation "com.android.support:design:$SUPPORT_LIBRARY_VERSION"
-}
\ No newline at end of file
+  implementation "androidx.appcompat:appcompat:$ANDROIDX_APPCOMPAT_VERSION"
+}
diff --git a/app/src/main/java/com/github/ivbaranov/rxbluetooth/example/BluetoothService.java b/app/src/main/java/com/github/ivbaranov/rxbluetooth/example/BluetoothService.java
index 2447fb6..57ecbe8 100644
--- a/app/src/main/java/com/github/ivbaranov/rxbluetooth/example/BluetoothService.java
+++ b/app/src/main/java/com/github/ivbaranov/rxbluetooth/example/BluetoothService.java
@@ -4,7 +4,7 @@
 import android.bluetooth.BluetoothDevice;
 import android.content.Intent;
 import android.os.IBinder;
-import android.support.annotation.Nullable;
+import androidx.annotation.Nullable;
 import android.util.Log;
 import com.github.ivbaranov.rxbluetooth.RxBluetooth;
 import io.reactivex.disposables.CompositeDisposable;
diff --git a/app/src/main/java/com/github/ivbaranov/rxbluetooth/example/MainActivity.java b/app/src/main/java/com/github/ivbaranov/rxbluetooth/example/MainActivity.java
index 67370dd..2e899d5 100644
--- a/app/src/main/java/com/github/ivbaranov/rxbluetooth/example/MainActivity.java
+++ b/app/src/main/java/com/github/ivbaranov/rxbluetooth/example/MainActivity.java
@@ -5,11 +5,11 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
+import androidx.annotation.NonNull;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.MenuItem;
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 339057d..ca25e35 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -6,7 +6,7 @@
               android:orientation="vertical"
               tools:context=".MainActivity">
 
-  <android.support.v7.widget.Toolbar
+  <androidx.appcompat.widget.Toolbar
       android:id="@+id/toolbar"
       android:layout_width="match_parent"
       android:layout_height="?attr/actionBarSize"
diff --git a/gradle.properties b/gradle.properties
index dd12f0e..11aca80 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,28 +1,26 @@
 # suppress inspection "UnusedProperty" for whole file
 
 # Compile SDK version (SDK platform to compile with)
-COMPILE_SDK_VERSION=android-27
-
-# Build tools version (Build tools version to build with)
-BUILD_TOOLS_VERSION=27.0.3
+COMPILE_SDK_VERSION=android-28
 
 # Minimum SDK version (lowest SDK platform to target)
-MIN_SDK_VERSION=11
+MIN_SDK_VERSION=14
 
 # Target SDK version (highest SDK platform to target)
-TARGET_SDK_VERSION=26
+TARGET_SDK_VERSION=28
 
 # Current library version
 VERSION_NAME=2.0.4
 VERSION_CODE=19
 
 # Dependency versions (library)
-SUPPORT_LIBRARY_VERSION=25.3.1
-RXANDROID_VERSION=2.0.2
-RXJAVA_VERSION=2.1.12
+RXANDROID_VERSION=2.1.0
+RXJAVA_VERSION=2.2.5
+ANDROIDX_ANNOTATION_VERSION=1.0.1
+ANDROIDX_APPCOMPAT_VERSION=1.0.0
 
 # Dependency versions (plugins)
-GRADLE_PLUGIN_VERSION=3.1.2
+GRADLE_PLUGIN_VERSION=3.2.1
 BINTRAY_RELEASE=0.8.1
 
 # Maven
@@ -30,6 +28,9 @@ USER_ORG=ivbaranov
 GROUP=com.github.ivbaranov
 ARTIFACT_ID=rxbluetooth2
 
+android.useAndroidX=true
+android.enableJetifier=false
+
 POM_DESCRIPTION=Android reactive bluetooth
 POM_URL=https://github.com/ivbaranov/RxBluetooth
 POM_SCM_URL=https://github.com/ivbaranov/RxBluetooth
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 8c0fb64..87b738c 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 4a28b95..ae45383 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,5 @@
-#Thu May 10 13:07:46 MSK 2018
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
diff --git a/gradlew b/gradlew
index 91a7e26..ad6d902 100755
--- a/gradlew
+++ b/gradlew
@@ -1,4 +1,4 @@
-#!/usr/bin/env bash
+#!/usr/bin/env sh
 
 ##############################################################################
 ##
@@ -6,20 +6,38 @@
 ##
 ##############################################################################
 
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
 
 APP_NAME="Gradle"
 APP_BASE_NAME=`basename "$0"`
 
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=''
+
 # Use the maximum available, or set MAX_FD != -1 to use that value.
 MAX_FD="maximum"
 
-warn ( ) {
+warn () {
     echo "$*"
 }
 
-die ( ) {
+die () {
     echo
     echo "$*"
     echo
@@ -30,6 +48,7 @@ die ( ) {
 cygwin=false
 msys=false
 darwin=false
+nonstop=false
 case "`uname`" in
   CYGWIN* )
     cygwin=true
@@ -40,31 +59,11 @@ case "`uname`" in
   MINGW* )
     msys=true
     ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
 esac
 
-# For Cygwin, ensure paths are in UNIX format before anything is touched.
-if $cygwin ; then
-    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
-fi
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >&-
-APP_HOME="`pwd -P`"
-cd "$SAVED" >&-
-
 CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 
 # Determine the Java command to use to start the JVM.
@@ -90,7 +89,7 @@ location of your Java installation."
 fi
 
 # Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
     MAX_FD_LIMIT=`ulimit -H -n`
     if [ $? -eq 0 ] ; then
         if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@@ -114,6 +113,7 @@ fi
 if $cygwin ; then
     APP_HOME=`cygpath --path --mixed "$APP_HOME"`
     CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
 
     # We build the pattern for arguments to be converted via cygpath
     ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
@@ -154,11 +154,19 @@ if $cygwin ; then
     esac
 fi
 
-# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
-function splitJvmOpts() {
-    JVM_OPTS=("$@")
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
 }
-eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
-JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
 
-exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
index 8a0b282..f955316 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -8,14 +8,14 @@
 @rem Set local scope for the variables with windows NT shell
 if "%OS%"=="Windows_NT" setlocal
 
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
 set DIRNAME=%~dp0
 if "%DIRNAME%" == "" set DIRNAME=.
 set APP_BASE_NAME=%~n0
 set APP_HOME=%DIRNAME%
 
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
 @rem Find java.exe
 if defined JAVA_HOME goto findJavaFromJavaHome
 
@@ -46,10 +46,9 @@ echo location of your Java installation.
 goto fail
 
 :init
-@rem Get command-line arguments, handling Windowz variants
+@rem Get command-line arguments, handling Windows variants
 
 if not "%OS%" == "Windows_NT" goto win9xME_args
-if "%@eval[2+2]" == "4" goto 4NT_args
 
 :win9xME_args
 @rem Slurp the command line arguments.
@@ -60,11 +59,6 @@ set _SKIP=2
 if "x%~1" == "x" goto execute
 
 set CMD_LINE_ARGS=%*
-goto execute
-
-:4NT_args
-@rem Get arguments from the 4NT Shell from JP Software
-set CMD_LINE_ARGS=%$
 
 :execute
 @rem Setup the command line
diff --git a/rxbluetooth/build.gradle b/rxbluetooth/build.gradle
index a3c64e5..2b78f08 100644
--- a/rxbluetooth/build.gradle
+++ b/rxbluetooth/build.gradle
@@ -3,7 +3,6 @@ apply plugin: 'com.novoda.bintray-release'
 
 android {
   compileSdkVersion COMPILE_SDK_VERSION
-  buildToolsVersion BUILD_TOOLS_VERSION
 
   defaultConfig {
     minSdkVersion MIN_SDK_VERSION
@@ -17,7 +16,7 @@ android {
 }
 
 dependencies {
-  implementation "com.android.support:support-annotations:$SUPPORT_LIBRARY_VERSION"
+  implementation "androidx.annotation:annotation:$ANDROIDX_ANNOTATION_VERSION"
 
   api "io.reactivex.rxjava2:rxjava:$RXJAVA_VERSION"
   api "io.reactivex.rxjava2:rxandroid:$RXANDROID_VERSION"
@@ -33,4 +32,4 @@ publish {
   website = POM_URL
 }
 
-apply from: 'https://raw.github.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle'
\ No newline at end of file
+apply from: 'https://raw.github.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle'
diff --git a/rxbluetooth/src/main/java/com/github/ivbaranov/rxbluetooth/RxBluetooth.java b/rxbluetooth/src/main/java/com/github/ivbaranov/rxbluetooth/RxBluetooth.java
index 52ab1d6..14faa67 100644
--- a/rxbluetooth/src/main/java/com/github/ivbaranov/rxbluetooth/RxBluetooth.java
+++ b/rxbluetooth/src/main/java/com/github/ivbaranov/rxbluetooth/RxBluetooth.java
@@ -29,8 +29,8 @@
 import android.location.LocationManager;
 import android.os.Build;
 import android.os.Parcelable;
-import android.support.annotation.Nullable;
-import android.support.annotation.RequiresApi;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 import android.text.TextUtils;
 import com.github.ivbaranov.rxbluetooth.events.AclEvent;
 import com.github.ivbaranov.rxbluetooth.events.BondStateEvent;