diff --git a/app/build.gradle b/app/build.gradle
index 6dff8e344617beaa62fe3835d5704c351ffee8aa..51c16eaa9b88aacc3fe8a1d88f4e38d4a8b9c6b5 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -6,8 +6,8 @@ apply plugin: 'com.android.application'
 def appName = 'Bitmask'
 
 android {
-  compileSdkVersion 27
-  buildToolsVersion '27.0.3'
+  compileSdkVersion 28
+  buildToolsVersion '28.0.3'
 
   compileOptions {
     targetCompatibility 1.8
@@ -169,9 +169,9 @@ dependencies {
   androidTestImplementation 'com.jayway.android.robotium:robotium-solo:5.6.3'
   testImplementation 'junit:junit:4.12'
   testImplementation 'org.json:json:20170516'
-  debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.4'
-  releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
-  betaImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
+  debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.2'
+  releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.2'
+  betaImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.2'
   annotationProcessor 'com.jakewharton:butterknife:6.1.0'
   annotationProcessor 'com.squareup.dagger:dagger-compiler:1.2.2'
   implementation 'com.jakewharton:butterknife:6.1.0'
@@ -182,15 +182,15 @@ dependencies {
   implementation 'com.intellij:annotations:12.0'
   implementation 'com.google.code.gson:gson:2.8.2'
   implementation 'com.squareup.okhttp3:okhttp:3.9.0'
-  implementation "com.android.support:support-core-utils:27.0.2"
-  implementation 'com.android.support:support-annotations:27.0.2'
-  implementation 'com.android.support:support-v4:27.0.2'
-  implementation 'com.android.support:appcompat-v7:27.0.2'
-  implementation 'com.android.support:design:27.0.2'
-  implementation 'com.android.support:support-fragment:27.0.2'
-  implementation 'com.android.support.constraint:constraint-layout:1.0.2'
-  implementation 'com.android.support:multidex:1.0.2'
-  implementation 'com.android.support:cardview-v7:27.0.2'
+  implementation "com.android.support:support-core-utils:28.0.0"
+  implementation 'com.android.support:support-annotations:28.0.0'
+  implementation 'com.android.support:support-v4:28.0.0'
+  implementation 'com.android.support:appcompat-v7:28.0.0'
+  implementation 'com.android.support:design:28.0.0'
+  implementation 'com.android.support:support-fragment:28.0.0'
+  implementation 'com.android.support.constraint:constraint-layout:1.1.3'
+  implementation 'com.android.support:multidex:1.0.3'
+  implementation 'com.android.support:cardview-v7:28.0.0'
 }
 
 // Ensure the no-op dependency is always used in JVM tests.
@@ -202,12 +202,23 @@ configurations.all { config ->
       }
     }
   }
-  resolutionStrategy.force "com.android.support:support-annotations:27.0.2"
-  resolutionStrategy.force "com.android.support:support-v4:27.0.2"
-  resolutionStrategy.force "com.android.support:support-core-utils:27.0.2"
-  resolutionStrategy.force "com.android.support:appcompat-v7:27.0.2"
-  resolutionStrategy.force "com.android.support:design:27.0.2"
-  resolutionStrategy.force "com.android.support:support-fragment:27.0.2"
+  resolutionStrategy.force "com.android.support:support-annotations:28.0.0"
+  resolutionStrategy.force "com.android.support:support-v4:28.0.0"
+  resolutionStrategy.force "com.android.support:support-core-utils:28.0.0"
+  resolutionStrategy.force "com.android.support:appcompat-v7:28.0.0"
+  resolutionStrategy.force "com.android.support:design:28.0.0"
+  resolutionStrategy.force "com.android.support:support-fragment:28.0.0"
+}
+
+subprojects {
+  afterEvaluate {project ->
+    if (project.hasProperty("android")) {
+      android {
+        compileSdkVersion 28
+        buildToolsVersion "28.0.3"
+      }
+    }
+  }
 }
 
 def processFileInplace(file, Closure processText) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/BitmaskApp.java b/app/src/main/java/se/leap/bitmaskclient/BitmaskApp.java
index 6484d0eefdec378f3d448c66d19edda16b38546f..fd9aa02969843a8f282f8d2748ae2ed1f55277ad 100644
--- a/app/src/main/java/se/leap/bitmaskclient/BitmaskApp.java
+++ b/app/src/main/java/se/leap/bitmaskclient/BitmaskApp.java
@@ -19,7 +19,6 @@ public class BitmaskApp extends MultiDexApplication {
     private final static String TAG = BitmaskApp.class.getSimpleName();
     private RefWatcher refWatcher;
     private ProviderObservable providerObservable;
-    private SharedPreferences preferences;
 
 
     @Override
@@ -33,7 +32,7 @@ public class BitmaskApp extends MultiDexApplication {
         refWatcher = LeakCanary.install(this);
         // Normal app init code...*/
         PRNGFixes.apply();
-        preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
+        SharedPreferences preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
         providerObservable = ProviderObservable.getInstance();
         providerObservable.updateProvider(getSavedProviderFromSharedPreferences(preferences));
         EipSetupObserver.init(this, preferences);
diff --git a/app/src/main/java/se/leap/bitmaskclient/Constants.java b/app/src/main/java/se/leap/bitmaskclient/Constants.java
index b05fedf9fe3941c4b557603f55d9ddc01792e777..f9ee8fcf3c87be5ab6eddc6e143944130b0b4d34 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Constants.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Constants.java
@@ -33,6 +33,8 @@ public interface Constants {
     String DEFAULT_BITMASK = "normal";
     String CUSTOM_BITMASK = "custom";
 
+    String ASK_TO_CANCEL_VPN = "ask_to_cancel_vpn";
+
 
     //////////////////////////////////////////////
     // EIP CONSTANTS
diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
index 3095943512c42ae9804c34ed724b29dba7489346..a535b0cb698ffc54251db898e749af82f3c8ca0c 100644
--- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
@@ -19,7 +19,6 @@ package se.leap.bitmaskclient;
 import android.app.Activity;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.content.SharedPreferences;
@@ -67,6 +66,7 @@ import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
 import static se.leap.bitmaskclient.Constants.REQUEST_CODE_CONFIGURE_LEAP;
 import static se.leap.bitmaskclient.Constants.REQUEST_CODE_LOG_IN;
 import static se.leap.bitmaskclient.Constants.REQUEST_CODE_SWITCH_PROVIDER;
+import static se.leap.bitmaskclient.Constants.ASK_TO_CANCEL_VPN;
 import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES;
 import static se.leap.bitmaskclient.EipSetupObserver.connectionRetry;
 import static se.leap.bitmaskclient.EipSetupObserver.gatewayOrder;
@@ -81,7 +81,6 @@ public class EipFragment extends Fragment implements Observer {
 
     public final static String TAG = EipFragment.class.getSimpleName();
 
-    public static final String ASK_TO_CANCEL_VPN = "ask_to_cancel_vpn";
 
     private SharedPreferences preferences;
     private Provider provider;
@@ -106,8 +105,8 @@ public class EipFragment extends Fragment implements Observer {
     private EipStatus eipStatus;
 
     //---saved Instance -------
-    private final static String KEY_SHOW_PENDING_START_CANCELLATION = "KEY_SHOW_PENDING_START_CANCELLATION";
-    private final static String KEY_SHOW_ASK_TO_STOP_EIP = "KEY_SHOW_ASK_TO_STOP_EIP";
+    private final String KEY_SHOW_PENDING_START_CANCELLATION = "KEY_SHOW_PENDING_START_CANCELLATION";
+    private final String KEY_SHOW_ASK_TO_STOP_EIP = "KEY_SHOW_ASK_TO_STOP_EIP";
     private boolean showPendingStartCancellation = false;
     private boolean showAskToStopEip = false;
     //------------------------
@@ -324,22 +323,9 @@ public class EipFragment extends Fragment implements Observer {
         showPendingStartCancellation = true;
         alertDialog = alertBuilder.setTitle(activity.getString(R.string.eip_cancel_connect_title))
                 .setMessage(activity.getString(R.string.eip_cancel_connect_text))
-                .setPositiveButton((android.R.string.yes), new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                        stopEipIfPossible();
-                    }
-                })
-                .setNegativeButton(activity.getString(android.R.string.no), new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                    }
-                }).setOnDismissListener(new DialogInterface.OnDismissListener() {
-            @Override
-            public void onDismiss(DialogInterface dialog) {
-                showPendingStartCancellation = false;
-            }
-        }).show();
+                .setPositiveButton((android.R.string.yes), (dialog, which) -> stopEipIfPossible())
+                .setNegativeButton(activity.getString(android.R.string.no), (dialog, which) -> {
+                }).setOnDismissListener(dialog -> showPendingStartCancellation = false).show();
 
     }
 
@@ -353,22 +339,9 @@ public class EipFragment extends Fragment implements Observer {
         showAskToStopEip = true;
         alertDialog = alertBuilder.setTitle(activity.getString(R.string.eip_cancel_connect_title))
                 .setMessage(activity.getString(R.string.eip_warning_browser_inconsistency))
-                .setPositiveButton((android.R.string.yes), new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                        stopEipIfPossible();
-                    }
-                })
-                .setNegativeButton(activity.getString(android.R.string.no), new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                    }
-                }).setOnDismissListener(new DialogInterface.OnDismissListener() {
-            @Override
-            public void onDismiss(DialogInterface dialog) {
-                showAskToStopEip = false;
-            }
-        }).show();
+                .setPositiveButton((android.R.string.yes), (dialog, which) -> stopEipIfPossible())
+                .setNegativeButton(activity.getString(android.R.string.no), (dialog, which) -> {
+                }).setOnDismissListener(dialog -> showAskToStopEip = false).show();
     }
 
     @Override
@@ -377,12 +350,7 @@ public class EipFragment extends Fragment implements Observer {
             eipStatus = (EipStatus) observable;
             Activity activity = getActivity();
             if (activity != null) {
-                activity.runOnUiThread(new Runnable() {
-                    @Override
-                    public void run() {
-                        handleNewState();
-                    }
-                });
+                activity.runOnUiThread(() -> handleNewState());
             } else {
                 Log.e("EipFragment", "activity is null");
             }
diff --git a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java
index 30aa5baa185dc90bcce750b88b987a998d992ed2..fd0c27d6ed656137056aeb4c80129f1877f28b40 100644
--- a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java
@@ -38,6 +38,7 @@ import se.leap.bitmaskclient.drawer.NavigationDrawerFragment;
 import se.leap.bitmaskclient.eip.EipCommand;
 import se.leap.bitmaskclient.fragments.LogFragment;
 
+import static se.leap.bitmaskclient.Constants.ASK_TO_CANCEL_VPN;
 import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE;
 import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY;
 import static se.leap.bitmaskclient.Constants.EIP_ACTION_START;
@@ -47,7 +48,6 @@ import static se.leap.bitmaskclient.Constants.REQUEST_CODE_CONFIGURE_LEAP;
 import static se.leap.bitmaskclient.Constants.REQUEST_CODE_LOG_IN;
 import static se.leap.bitmaskclient.Constants.REQUEST_CODE_SWITCH_PROVIDER;
 import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES;
-import static se.leap.bitmaskclient.EipFragment.ASK_TO_CANCEL_VPN;
 import static se.leap.bitmaskclient.ProviderAPI.ERRORS;
 import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE;
 import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE;
diff --git a/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java b/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java
index 503ba536d4b6b5e482925a83632fe313ddce357e..566b34536903fdd85bade5ff3fead724c7de2c17 100644
--- a/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java
@@ -44,7 +44,7 @@ import static android.text.TextUtils.isEmpty;
 import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_NONETWORK;
 import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT;
 import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP_BLOCKING_VPN;
-import static se.leap.bitmaskclient.EipFragment.ASK_TO_CANCEL_VPN;
+import static se.leap.bitmaskclient.Constants.ASK_TO_CANCEL_VPN;
 import static se.leap.bitmaskclient.MainActivity.ACTION_SHOW_VPN_FRAGMENT;
 
 /**
diff --git a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
index 769bd887341c185125421030336be9a89ca59a15..ba0cfffc06e6fe090f28421e85ccdb2a5b98da3e 100644
--- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
@@ -382,31 +382,18 @@ public class NavigationDrawerFragment extends Fragment {
             alertDialog = alertBuilder
                     .setTitle(activity.getString(R.string.save_battery))
                     .setMessage(activity.getString(R.string.save_battery_message))
-                    .setPositiveButton((android.R.string.yes), new DialogInterface.OnClickListener() {
-                        @Override
-                        public void onClick(DialogInterface dialog, int which) {
-                            DrawerSettingsItem item = settingsListAdapter.getDrawerItem(BATTERY_SAVER);
-                            item.setChecked(true);
-                            settingsListAdapter.notifyDataSetChanged();
-                            saveBattery(getContext(), item.isChecked());
-                        }
+                    .setPositiveButton((android.R.string.yes), (dialog, which) -> {
+                        DrawerSettingsItem item = settingsListAdapter.getDrawerItem(BATTERY_SAVER);
+                        item.setChecked(true);
+                        settingsListAdapter.notifyDataSetChanged();
+                        saveBattery(getContext(), item.isChecked());
                     })
-                    .setNegativeButton(activity.getString(android.R.string.no), new DialogInterface.OnClickListener() {
-                        @Override
-                        public void onClick(DialogInterface dialog, int which) {
-                            disableSwitch(BATTERY_SAVER);
-                        }
-                    }).setOnDismissListener(new DialogInterface.OnDismissListener() {
+                    .setNegativeButton(activity.getString(android.R.string.no), (dialog, which) -> disableSwitch(BATTERY_SAVER)).setOnDismissListener(new DialogInterface.OnDismissListener() {
                         @Override
                         public void onDismiss(DialogInterface dialog) {
                             showEnableExperimentalFeature = false;
                         }
-                    }).setOnCancelListener(new DialogInterface.OnCancelListener() {
-                        @Override
-                        public void onCancel(DialogInterface dialog) {
-                            disableSwitch(BATTERY_SAVER);
-                        }
-                    }).show();
+                    }).setOnCancelListener(dialog -> disableSwitch(BATTERY_SAVER)).show();
         } catch (IllegalStateException e) {
             e.printStackTrace();
         }
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
new file mode 100644
index 0000000000000000000000000000000000000000..eb9626bcb2a91a65cac8c7d42533d91ce67c1b25
--- /dev/null
+++ b/app/src/main/res/values/attrs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <declare-styleable name="foo">
+        <attr name="textColorError" format="color" />
+    </declare-styleable>
+</resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 70bc3e16913012a9a0dfeb964bbb91b58a8b7c69..f3c55f41d5248707bac2ace2ab16b6a8382de3f5 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -21,4 +21,8 @@
         <item name="android:windowBackground">@drawable/splash_page</item>
     </style>
 
+    <style name="foo">
+        <item name="textColorError">@color/colorPrimary</item>
+    </style>
+
 </resources>
diff --git a/docker/android-sdk/Dockerfile b/docker/android-sdk/Dockerfile
index f57280c60cb924a78dfeb9c691bb00cbd8d28bf1..4c0c1782c7944109a52dd1ded6d7daa01bb10d9c 100644
--- a/docker/android-sdk/Dockerfile
+++ b/docker/android-sdk/Dockerfile
@@ -1,7 +1,7 @@
 FROM 0xacab.org:4567/leap/docker/debian:stretch_amd64
 
 MAINTAINER LEAP Encryption Access Project <info@leap.se>
-LABEL Description="Android SDK baseimage based on debian:stretch" Vendor="LEAP" Version="26.0.0"
+LABEL Description="Android SDK baseimage based on debian:stretch" Vendor="LEAP" Version="27.0.0"
 
 # ------------------------------------------------------
 # --- Install System Dependencies
@@ -59,11 +59,13 @@ RUN echo y | sdkmanager "platform-tools" # echo y to accept google licenses
 RUN sdkmanager "extras;android;m2repository"
 
 # Install Build Tools (Please keep in descending order)
+RUN sdkmanager "build-tools;28.0.3"
 RUN sdkmanager "build-tools;27.0.3"
 RUN sdkmanager "build-tools;25.0.2"
 RUN sdkmanager "build-tools;23.0.3"
 
 # Install Target SDK Packages (Please keep in descending order)
+RUN sdkmanager "platforms;android-28"
 RUN sdkmanager "platforms;android-27"
 RUN sdkmanager "platforms;android-25"
 RUN sdkmanager "platforms;android-23"