diff --git a/app/src/fatweb/AndroidManifest.xml b/app/src/fatweb/AndroidManifest.xml
index 5188b05b1fe358d7cacf1ba79080035045996998..28246e5f4d794dd5eb54c447647c5d45c740d3c9 100644
--- a/app/src/fatweb/AndroidManifest.xml
+++ b/app/src/fatweb/AndroidManifest.xml
@@ -39,10 +39,6 @@
                 <action android:name="android.intent.action.PACKAGE_INSTALL"/>
                 <data android:scheme="package"/>
             </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.PACKAGE_INSTALL"/>
-                <data android:scheme="package"/>
-            </intent-filter>
         </receiver>
 
         <provider android:name="androidx.core.content.FileProvider"
@@ -53,6 +49,9 @@
             <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_provider_paths" />
 
         </provider>
+        <activity
+            android:name=".appUpdate.InstallActivity"
+            android:theme="@style/invisibleTheme" />
     </application>
 
 
diff --git a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadBroadcastReceiver.java b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadBroadcastReceiver.java
index 6613d39427f78593cea835d7a93930b8d1dfb1d3..f410b9ffd58892fcedaf2b05ad200fd36de23026 100644
--- a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadBroadcastReceiver.java
+++ b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadBroadcastReceiver.java
@@ -19,7 +19,6 @@ package se.leap.bitmaskclient.appUpdate;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.net.Uri;
 import android.os.Bundle;
 import android.util.Log;
 import android.widget.Toast;
@@ -27,12 +26,12 @@ import android.widget.Toast;
 import java.io.File;
 
 import se.leap.bitmaskclient.Constants;
+import se.leap.bitmaskclient.R;
+import se.leap.bitmaskclient.utils.ConfigHelper;
 
 import static android.app.Activity.RESULT_CANCELED;
 import static se.leap.bitmaskclient.Constants.BROADCAST_DOWNLOAD_SERVICE_EVENT;
 import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE;
-import static se.leap.bitmaskclient.appUpdate.DownloadConnector.APP_TYPE;
-import static se.leap.bitmaskclient.appUpdate.DownloadService.DOWNLOAD_FAILED;
 import static se.leap.bitmaskclient.appUpdate.DownloadService.DOWNLOAD_PROGRESS;
 import static se.leap.bitmaskclient.appUpdate.DownloadService.NO_NEW_VERISON;
 import static se.leap.bitmaskclient.appUpdate.DownloadService.PROGRESS_VALUE;
@@ -40,8 +39,9 @@ import static se.leap.bitmaskclient.appUpdate.DownloadService.UPDATE_DOWNLOADED;
 import static se.leap.bitmaskclient.appUpdate.DownloadService.UPDATE_DOWNLOAD_FAILED;
 import static se.leap.bitmaskclient.appUpdate.DownloadService.UPDATE_FOUND;
 import static se.leap.bitmaskclient.appUpdate.DownloadService.UPDATE_NOT_FOUND;
+import static se.leap.bitmaskclient.appUpdate.DownloadService.VERIFICATION_ERROR;
 import static se.leap.bitmaskclient.appUpdate.DownloadServiceCommand.DOWNLOAD_UPDATE;
-import static se.leap.bitmaskclient.appUpdate.FileProviderUtil.getUriFor;
+import static se.leap.bitmaskclient.appUpdate.UpdateDownloadManager.getUpdateFile;
 
 public class DownloadBroadcastReceiver extends BroadcastReceiver {
 
@@ -75,25 +75,21 @@ public class DownloadBroadcastReceiver extends BroadcastReceiver {
                     case UPDATE_NOT_FOUND:
                         if (resultData.getBoolean(NO_NEW_VERISON, false)) {
                             //TODO: Save in preferences date, retry in a week
-                        } else if (resultData.getBoolean(DOWNLOAD_FAILED, false)) {
-                            Toast.makeText(context.getApplicationContext(), "Update check failed.", Toast.LENGTH_LONG).show();
                         }
                         break;
                     case UPDATE_DOWNLOADED:
-                        notificationManager.cancelNotifications();
-                        Intent installIntent = new Intent(Intent.ACTION_VIEW);
-                        File update = UpdateDownloadManager.getUpdateFile(context);
-                        if (update.exists()) {
-                            installIntent.setDataAndType(getUriFor(context, update), APP_TYPE);
-                        }
-                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                        intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
-                        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-                        context.startActivity(installIntent);
+                        notificationManager.buildDownloadSuccessfulNotification();
                         break;
                     case UPDATE_DOWNLOAD_FAILED:
-                        notificationManager.cancelNotifications();
-                        Toast.makeText(context.getApplicationContext(), "Update download failed.", Toast.LENGTH_LONG).show();
+                        if (resultData.getBoolean(VERIFICATION_ERROR, false)) {
+                            Toast.makeText(context.getApplicationContext(), context.getString(R.string.version_update_error_pgp_verification), Toast.LENGTH_LONG).show();
+                        } else {
+                            Toast.makeText(context.getApplicationContext(), context.getString(R.string.version_update_error), Toast.LENGTH_LONG).show();
+                        }
+                        File file = getUpdateFile(context);
+                        if (file.exists()) {
+                            file.delete();
+                        }
                         break;
                     case DOWNLOAD_PROGRESS:
                         int progress = resultData.getInt(PROGRESS_VALUE, 0);
diff --git a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadConnector.java b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadConnector.java
index 9427083da75026d38d74c46f235c3f540e4a9059..d4c5de7fe77a414dabb1e73116acc96ca217042c 100644
--- a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadConnector.java
+++ b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadConnector.java
@@ -45,8 +45,8 @@ import okio.Okio;
 public class DownloadConnector {
 
     private static final String TAG = DownloadConnector.class.getSimpleName();
-    final static String APP_TYPE = "application/vnd.android.package-archive";
-    final static String TEXT_FILE_TYPE = "application/text";
+    public final static String APP_TYPE = "application/vnd.android.package-archive";
+    public final static String TEXT_FILE_TYPE = "application/text";
 
     public interface DownloadProgress {
         void onUpdate(int progress);
@@ -78,8 +78,8 @@ public class DownloadConnector {
     }
 
     static File requestFileFromServer(@NonNull String url, @NonNull OkHttpClient okHttpClient, File destFile, DownloadProgress callback) {
-        BufferedSink sink = null;
-        BufferedSource source = null;
+        BufferedSink sink;
+        BufferedSource source;
         try {
             Request.Builder requestBuilder = new Request.Builder()
                     .url(url)
diff --git a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadNotificationManager.java b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadNotificationManager.java
index 4f7f2883942aa05fec1985fc74539ce13b2de1b0..aaf487aae10745f339ab424d5f8d70c7359b3182 100644
--- a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadNotificationManager.java
+++ b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadNotificationManager.java
@@ -42,18 +42,14 @@ public class DownloadNotificationManager {
     }
 
     public void buildDownloadFoundNotification() {
-        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+        NotificationManager notificationManager = initNotificationManager();
         if (notificationManager == null) {
             return;
         }
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-           createNotificationChannel(notificationManager);
-        }
-        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this.context, DownloadService.NOTIFICATION_CHANNEL_NEWSTATUS_ID);
-        notificationBuilder.setAutoCancel(true)
-                .setDefaults(Notification.DEFAULT_ALL)
+        NotificationCompat.Builder notificationBuilder = initNotificationBuilderDefaults();
+        notificationBuilder
+                .setSmallIcon(R.drawable.ic_about_36)
                 .setWhen(System.currentTimeMillis())
-                .setSmallIcon(R.mipmap.ic_launcher)
                 .setTicker(context.getString(R.string.version_update_title, context.getString(R.string.app_name)))
                 .setContentTitle(context.getString(R.string.version_update_title, context.getString(R.string.app_name)))
                 .setContentText(context.getString(R.string.version_update_found))
@@ -61,6 +57,51 @@ public class DownloadNotificationManager {
         notificationManager.notify(DOWNLOAD_NOTIFICATION_ID, notificationBuilder.build());
     }
 
+    public void buildDownloadSuccessfulNotification() {
+        NotificationManager notificationManager = initNotificationManager();
+        if (notificationManager == null) {
+            return;
+        }
+        NotificationCompat.Builder notificationBuilder = initNotificationBuilderDefaults();
+        notificationBuilder
+                .setSmallIcon(android.R.drawable.stat_sys_download_done)
+                .setWhen(System.currentTimeMillis())
+                .setTicker(context.getString(R.string.version_update_title, context.getString(R.string.app_name)))
+                .setContentTitle(context.getString(R.string.version_update_download_title, context.getString(R.string.app_name)))
+                .setContentText(context.getString(R.string.version_update_download_description))
+                .setContentIntent(getInstallIntent());
+        notificationManager.notify(DOWNLOAD_NOTIFICATION_ID, notificationBuilder.build());
+    }
+
+    public void buildDownloadUpdateProgress(int progress) {
+        NotificationManager notificationManager = initNotificationManager();
+        if (notificationManager == null) {
+            return;
+        }
+
+        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this.context, DownloadService.NOTIFICATION_CHANNEL_NEWSTATUS_ID);
+        notificationBuilder
+                .setDefaults(Notification.DEFAULT_ALL)
+                .setAutoCancel(false)
+                .setOngoing(true)
+                .setSmallIcon(android.R.drawable.stat_sys_download)
+                .setContentTitle(context.getString(R.string.version_update_apk_description, context.getString(R.string.app_name)))
+                .setProgress(100, progress, false)
+                .setContentIntent(getDownloadIntent());
+        notificationManager.notify(DOWNLOAD_NOTIFICATION_ID, notificationBuilder.build());
+    }
+
+    private NotificationManager initNotificationManager() {
+        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+        if (notificationManager == null) {
+            return null;
+        }
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            createNotificationChannel(notificationManager);
+        }
+        return notificationManager;
+    }
+
     @TargetApi(26)
     private void createNotificationChannel(NotificationManager notificationManager) {
         CharSequence name = "Bitmask Updates";
@@ -75,7 +116,13 @@ public class DownloadNotificationManager {
         notificationManager.createNotificationChannel(channel);
     }
 
-
+    private NotificationCompat.Builder initNotificationBuilderDefaults() {
+        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this.context, DownloadService.NOTIFICATION_CHANNEL_NEWSTATUS_ID);
+        notificationBuilder.
+                setDefaults(Notification.DEFAULT_ALL).
+                setAutoCancel(true);
+        return notificationBuilder;
+    }
 
     private PendingIntent getDownloadIntent() {
         Intent downloadIntent = new Intent(context, DownloadBroadcastReceiver.class);
@@ -83,24 +130,9 @@ public class DownloadNotificationManager {
         return PendingIntent.getBroadcast(context, 0, downloadIntent, PendingIntent.FLAG_CANCEL_CURRENT);
     }
 
-    public void buildDownloadUpdateProgress(int progress) {
-        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-        if (notificationManager == null) {
-            return;
-        }
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-            createNotificationChannel(notificationManager);
-        }
-        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this.context, DownloadService.NOTIFICATION_CHANNEL_NEWSTATUS_ID);
-        notificationBuilder.setAutoCancel(true)
-                .setDefaults(Notification.DEFAULT_ALL)
-                .setAutoCancel(false)
-                .setOngoing(true)
-                .setSmallIcon(R.mipmap.ic_launcher)
-                .setContentTitle(context.getString(R.string.version_update_apk_description, context.getString(R.string.app_name)))
-                .setProgress(100, progress, false)
-                .setContentIntent(getDownloadIntent());
-        notificationManager.notify(DOWNLOAD_NOTIFICATION_ID, notificationBuilder.build());
+    private PendingIntent getInstallIntent() {
+        Intent installIntent = new Intent(context, InstallActivity.class);
+        return PendingIntent.getActivity(context, 0, installIntent, PendingIntent.FLAG_CANCEL_CURRENT);
     }
 
     public void cancelNotifications() {
diff --git a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/InstallActivity.java b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/InstallActivity.java
index e373a888b8868e1b7ca031a4a39548a20351ae73..f2f8223808430243938a50ffe0e7c326a0517a24 100644
--- a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/InstallActivity.java
+++ b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/InstallActivity.java
@@ -1,4 +1,96 @@
+/**
+ * Copyright (c) 2020 LEAP Encryption Access Project and contributers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
 package se.leap.bitmaskclient.appUpdate;
 
-public class InstallActivity {
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.widget.Toast;
+
+import androidx.annotation.Nullable;
+
+import java.io.File;
+
+import de.blinkt.openvpn.core.VpnStatus;
+import se.leap.bitmaskclient.R;
+import se.leap.bitmaskclient.utils.PreferenceHelper;
+
+import static se.leap.bitmaskclient.Constants.REQUEST_CODE_INSTALL_UPDATE;
+import static se.leap.bitmaskclient.Constants.REQUEST_CODE_REQUEST_UPDATE;
+import static se.leap.bitmaskclient.appUpdate.DownloadConnector.APP_TYPE;
+import static se.leap.bitmaskclient.appUpdate.FileProviderUtil.getUriFor;
+
+public class InstallActivity extends Activity {
+
+    private static final String TAG = InstallActivity.class.getSimpleName();
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        requestPermissionAndInstall();
+    }
+
+
+    private void requestPermissionAndInstall() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !this.getPackageManager().canRequestPackageInstalls()) {
+            startActivityForResult(new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:"+getPackageName())),
+                    REQUEST_CODE_REQUEST_UPDATE);
+        } else {
+            installUpdate();
+        }
+    }
+
+    protected void installUpdate() {
+        PreferenceHelper.restartOnUpdate(this.getApplicationContext(), true);
+
+        Intent installIntent = new Intent(Intent.ACTION_VIEW);
+        File update = UpdateDownloadManager.getUpdateFile(this.getApplicationContext());
+        if (update.exists()) {
+            installIntent.setDataAndType(getUriFor(this.getApplicationContext(), update), APP_TYPE);
+            installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            this.startActivityForResult(installIntent, REQUEST_CODE_INSTALL_UPDATE);
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        if (requestCode == REQUEST_CODE_REQUEST_UPDATE) {
+            if (resultCode == RESULT_OK) {
+                installUpdate();
+            } else {
+                Toast.makeText(this, getString(R.string.version_update_error_permissions), Toast.LENGTH_LONG).show();
+                finish();
+            }
+        } else if (requestCode == REQUEST_CODE_INSTALL_UPDATE) {
+            switch (resultCode) {
+                case RESULT_OK:
+                    Toast.makeText(this, "Update successful.", Toast.LENGTH_LONG).show();
+                    break;
+                case RESULT_CANCELED:
+                case RESULT_FIRST_USER:
+                    Toast.makeText(this, getString(R.string.version_update_error), Toast.LENGTH_LONG).show();
+                    break;
+            }
+            finish();
+        }
+    }
 }
diff --git a/app/src/main/java/se/leap/bitmaskclient/Constants.java b/app/src/main/java/se/leap/bitmaskclient/Constants.java
index dfd947596df4b27db1cfedc08861de301791ef33..f62af6389423bd52310c9e24836d027658c0a961 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Constants.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Constants.java
@@ -36,9 +36,7 @@ public interface Constants {
     String ALLOW_TETHERING_USB = "tethering_usb";
     String SHOW_EXPERIMENTAL = "show_experimental";
     String USE_IPv6_FIREWALL = "use_ipv6_firewall";
-    String APK_DOWNLOAD_ID = "apk_download_id";
-    String VERSION_FILE_DOWNLOAD_ID = "version_file_downlaod_id";
-    String SIGNATURE_DOWNLOAD_ID = "signature_file_download_id";
+    String RESTART_ON_UPDATE = "restart_on_update";
 
 
      //////////////////////////////////////////////
@@ -50,6 +48,8 @@ public interface Constants {
     int REQUEST_CODE_SWITCH_PROVIDER = 1;
     int REQUEST_CODE_LOG_IN = 2;
     int REQUEST_CODE_ADD_PROVIDER = 3;
+    int REQUEST_CODE_INSTALL_UPDATE = 4;
+    int REQUEST_CODE_REQUEST_UPDATE = 5;
 
 
     //////////////////////////////////////////////
diff --git a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java
index 9937eeebca730c8196d00bbd03c14e8e43fae7cb..9d49d5dab015472a1c929ab2e10e07c5ed9658c7 100644
--- a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java
@@ -183,9 +183,14 @@ public class StartActivity extends Activity{
                 if (getIntent() != null && getIntent().getBooleanExtra(EIP_RESTART_ON_BOOT, false)) {
                     EipCommand.startVPN(this.getApplicationContext(), true);
                     finish();
-                    return;
+                } else if (PreferenceHelper.getRestartOnUpdate(this.getApplicationContext())) {
+                    PreferenceHelper.restartOnUpdate(this.getApplicationContext(), false);
+                    EipCommand.startVPN(this.getApplicationContext(), false);
+                    showMainActivity();
+                    finish();
+                } else {
+                    showMainActivity();
                 }
-                showMainActivity();
             }
         } else {
             configureLeapProvider();
diff --git a/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java
index cb2aeb26204eac7354f0011a9f9ed89db8791c36..5ca2ec75d502161d3e4508bb46b6e517fae5c18f 100644
--- a/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java
@@ -27,6 +27,7 @@ import static se.leap.bitmaskclient.Constants.PROVIDER_CONFIGURED;
 import static se.leap.bitmaskclient.Constants.PROVIDER_EIP_DEFINITION;
 import static se.leap.bitmaskclient.Constants.PROVIDER_PRIVATE_KEY;
 import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE;
+import static se.leap.bitmaskclient.Constants.RESTART_ON_UPDATE;
 import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES;
 import static se.leap.bitmaskclient.Constants.SHOW_EXPERIMENTAL;
 import static se.leap.bitmaskclient.Constants.USE_IPv6_FIREWALL;
@@ -121,6 +122,14 @@ public class PreferenceHelper {
                 apply();
     }
 
+    public static void restartOnUpdate(Context context, boolean isEnabled) {
+        putBoolean(context, RESTART_ON_UPDATE, isEnabled);
+    }
+
+    public static boolean getRestartOnUpdate(Context context) {
+        return getBoolean(context, RESTART_ON_UPDATE, false);
+    }
+
     public static boolean getUsePluggableTransports(Context context) {
         return getBoolean(context, USE_PLUGGABLE_TRANSPORTS, false);
     }
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5ba51afec3d2b184422d9bca33a5bf1927b248e0..d047da2192b18bb8ab3231d73487ea61644c90c5 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -149,4 +149,7 @@
   <string name="version_update_storage_permission_denied">Storage permission request was denied.</string>
   <string name="version_update_download_title">A new %s version has been downloaded.</string>
   <string name="version_update_download_description">Tap here to install the update.</string>
+  <string name="version_update_error_pgp_verification">PGP verification error. Ignoring download.</string>
+  <string name="version_update_error">Update failed.</string>
+  <string name="version_update_error_permissions">No permissions to install app.</string>
 </resources>