diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.java
index 26ff14914..7fdd692c2 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.java
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.java
@@ -6,18 +6,22 @@ import android.os.Bundle;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
+import android.widget.Toast;
 
 import androidx.annotation.NonNull;
 import androidx.appcompat.app.AppCompatActivity;
 import androidx.appcompat.widget.Toolbar;
 
+import org.yuzu.yuzu_emu.NativeLibrary;
 import org.yuzu.yuzu_emu.R;
 import org.yuzu.yuzu_emu.activities.EmulationActivity;
 import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity;
 import org.yuzu.yuzu_emu.model.GameProvider;
 import org.yuzu.yuzu_emu.ui.platform.PlatformGamesFragment;
 import org.yuzu.yuzu_emu.utils.AddDirectoryHelper;
+import org.yuzu.yuzu_emu.utils.DirectoryInitialization;
 import org.yuzu.yuzu_emu.utils.FileBrowserHelper;
+import org.yuzu.yuzu_emu.utils.FileUtil;
 import org.yuzu.yuzu_emu.utils.PicassoUtils;
 import org.yuzu.yuzu_emu.utils.StartupHandler;
 import org.yuzu.yuzu_emu.utils.ThemeUtil;
@@ -116,8 +120,13 @@ public final class MainActivity extends AppCompatActivity implements MainView {
         switch (request) {
             case MainPresenter.REQUEST_ADD_DIRECTORY:
                 FileBrowserHelper.openDirectoryPicker(this,
-                                                  MainPresenter.REQUEST_ADD_DIRECTORY,
-                                                  R.string.select_game_folder);
+                        MainPresenter.REQUEST_ADD_DIRECTORY,
+                        R.string.select_game_folder);
+                break;
+            case MainPresenter.REQUEST_INSTALL_KEYS:
+                FileBrowserHelper.openFilePicker(this,
+                        MainPresenter.REQUEST_INSTALL_KEYS,
+                        R.string.install_keys);
                 break;
         }
     }
@@ -132,7 +141,6 @@ public final class MainActivity extends AppCompatActivity implements MainView {
         super.onActivityResult(requestCode, resultCode, result);
         switch (requestCode) {
             case MainPresenter.REQUEST_ADD_DIRECTORY:
-                // If the user picked a file, as opposed to just backing out.
                 if (resultCode == MainActivity.RESULT_OK) {
                     int takeFlags = (Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                     getContentResolver().takePersistableUriPermission(Uri.parse(result.getDataString()), takeFlags);
@@ -144,6 +152,22 @@ public final class MainActivity extends AppCompatActivity implements MainView {
                     mPresenter.onDirectorySelected(FileBrowserHelper.getSelectedDirectory(result));
                 }
                 break;
+
+            case MainPresenter.REQUEST_INSTALL_KEYS:
+                if (resultCode == MainActivity.RESULT_OK) {
+                    int takeFlags = (Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+                    getContentResolver().takePersistableUriPermission(Uri.parse(result.getDataString()), takeFlags);
+                    String dstPath = DirectoryInitialization.getUserDirectory() + "/keys/";
+                    if (FileUtil.copyUriToInternalStorage(this, result.getData(), dstPath, "prod.keys")) {
+                        if (NativeLibrary.ReloadKeys()) {
+                            Toast.makeText(this, R.string.install_keys_success, Toast.LENGTH_SHORT).show();
+                        } else {
+                            Toast.makeText(this, R.string.install_keys_failure, Toast.LENGTH_SHORT).show();
+                            launchFileListActivity(MainPresenter.REQUEST_INSTALL_KEYS);
+                        }
+                    }
+                }
+                break;
         }
     }
 
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainPresenter.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainPresenter.java
index 01f577600..82667a98f 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainPresenter.java
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainPresenter.java
@@ -11,6 +11,7 @@ import org.yuzu.yuzu_emu.utils.AddDirectoryHelper;
 
 public final class MainPresenter {
     public static final int REQUEST_ADD_DIRECTORY = 1;
+    public static final int REQUEST_INSTALL_KEYS = 2;
     private final MainView mView;
     private String mDirToAdd;
     private long mLastClickTime = 0;
@@ -46,6 +47,10 @@ public final class MainPresenter {
             case R.id.button_add_directory:
                 launchFileListActivity(REQUEST_ADD_DIRECTORY);
                 return true;
+
+            case R.id.button_install_keys:
+                launchFileListActivity(REQUEST_INSTALL_KEYS);
+                return true;
         }
 
         return false;
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileBrowserHelper.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileBrowserHelper.java
index 6175f39c4..4dab914c7 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileBrowserHelper.java
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileBrowserHelper.java
@@ -10,6 +10,15 @@ public final class FileBrowserHelper {
         activity.startActivityForResult(i, requestCode);
     }
 
+    public static void openFilePicker(FragmentActivity activity, int requestCode, int title) {
+        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+        intent.addCategory(Intent.CATEGORY_OPENABLE);
+        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
+        intent.putExtra(Intent.EXTRA_TITLE, title);
+        intent.setType("*/*");
+        activity.startActivityForResult(intent, requestCode);
+    }
+
     public static String getSelectedDirectory(Intent result) {
         return result.getDataString();
     }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.java
index 624fd4a88..8665704cc 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.java
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.java
@@ -12,8 +12,9 @@ import androidx.documentfile.provider.DocumentFile;
 
 import org.yuzu.yuzu_emu.model.MinimalDocumentFile;
 
+import java.io.FileOutputStream;
+import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
 import java.net.URLDecoder;
 import java.util.ArrayList;
 import java.util.List;
@@ -243,6 +244,40 @@ public class FileUtil {
         return size;
     }
 
+    public static boolean copyUriToInternalStorage(Context context, Uri sourceUri, String destinationParentPath, String destinationFilename) {
+        InputStream input = null;
+        FileOutputStream output = null;
+        try {
+            input = context.getContentResolver().openInputStream(sourceUri);
+            output = new FileOutputStream(destinationParentPath + "/" + destinationFilename);
+            byte[] buffer = new byte[1024];
+            int len;
+            while ((len = input.read(buffer)) != -1) {
+                output.write(buffer, 0, len);
+            }
+            output.flush();
+            return true;
+        } catch (Exception e) {
+            Log.error("[FileUtil]: Cannot copy file, error: " + e.getMessage());
+        } finally {
+            if (input != null) {
+                try {
+                    input.close();
+                } catch (IOException e) {
+                    Log.error("[FileUtil]: Cannot close input file, error: " + e.getMessage());
+                }
+            }
+            if (output != null) {
+                try {
+                    output.close();
+                } catch (IOException e) {
+                    Log.error("[FileUtil]: Cannot close output file, error: " + e.getMessage());
+                }
+            }
+        }
+        return false;
+    }
+
     public static boolean isRootTreeUri(Uri uri) {
         final List<String> paths = uri.getPathSegments();
         return paths.size() == 2 && PATH_TREE.equals(paths.get(0));
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/StartupHandler.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/StartupHandler.java
index 6d3e58e18..749a06b32 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/StartupHandler.java
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/StartupHandler.java
@@ -2,6 +2,10 @@ package org.yuzu.yuzu_emu.utils;
 
 import android.content.SharedPreferences;
 import android.preference.PreferenceManager;
+import android.text.Html;
+import android.text.method.LinkMovementMethod;
+import android.widget.TextView;
+
 import androidx.appcompat.app.AlertDialog;
 
 import org.yuzu.yuzu_emu.R;
@@ -13,7 +17,7 @@ public final class StartupHandler {
     private static SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.getAppContext());
 
     private static void handleStartupPromptDismiss(MainActivity parent) {
-        parent.launchFileListActivity(MainPresenter.REQUEST_ADD_DIRECTORY);
+        parent.launchFileListActivity(MainPresenter.REQUEST_INSTALL_KEYS);
     }
 
     private static void markFirstBoot() {
@@ -26,14 +30,16 @@ public final class StartupHandler {
         if (mPreferences.getBoolean("FirstApplicationLaunch", true)) {
             markFirstBoot();
 
-            // Prompt user with standard first boot disclaimer
-            new AlertDialog.Builder(parent)
-                    .setTitle(R.string.app_name)
-                    .setIcon(R.mipmap.ic_launcher)
-                    .setMessage(parent.getResources().getString(R.string.app_disclaimer))
-                    .setPositiveButton(android.R.string.ok, null)
-                    .setOnDismissListener(dialogInterface -> handleStartupPromptDismiss(parent))
-                    .show();
+            AlertDialog.Builder builder = new AlertDialog.Builder(parent);
+            builder.setMessage(Html.fromHtml(parent.getResources().getString(R.string.app_disclaimer)));
+            builder.setTitle(R.string.app_name);
+            builder.setIcon(R.mipmap.ic_launcher);
+            builder.setPositiveButton(android.R.string.ok, null);
+            builder.setOnDismissListener(dialogInterface -> handleStartupPromptDismiss(parent));
+
+            AlertDialog alert = builder.create();
+            alert.show();
+            ((TextView) alert.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
         }
     }
 }
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 358316c48..6d1e75c40 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -271,7 +271,7 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_SetAppDirectory(JNIEnv* env,
 jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_ReloadKeys(JNIEnv* env,
                                                           [[maybe_unused]] jclass clazz) {
     Core::Crypto::KeyManager::Instance().ReloadKeys();
-    return static_cast<jboolean>(Core::Crypto::KeyManager::Instance().IsKeysLoaded());
+    return static_cast<jboolean>(Core::Crypto::KeyManager::Instance().AreKeysLoaded());
 }
 
 void Java_org_yuzu_yuzu_1emu_NativeLibrary_UnPauseEmulation([[maybe_unused]] JNIEnv* env,
diff --git a/src/android/app/src/main/res/drawable-hdpi/ic_cia_install.png b/src/android/app/src/main/res/drawable-hdpi/ic_install.png
similarity index 100%
rename from src/android/app/src/main/res/drawable-hdpi/ic_cia_install.png
rename to src/android/app/src/main/res/drawable-hdpi/ic_install.png
diff --git a/src/android/app/src/main/res/drawable-mdpi/ic_cia_install.png b/src/android/app/src/main/res/drawable-mdpi/ic_install.png
similarity index 100%
rename from src/android/app/src/main/res/drawable-mdpi/ic_cia_install.png
rename to src/android/app/src/main/res/drawable-mdpi/ic_install.png
diff --git a/src/android/app/src/main/res/drawable-night-hdpi/ic_cia_install.png b/src/android/app/src/main/res/drawable-night-hdpi/ic_install.png
similarity index 100%
rename from src/android/app/src/main/res/drawable-night-hdpi/ic_cia_install.png
rename to src/android/app/src/main/res/drawable-night-hdpi/ic_install.png
diff --git a/src/android/app/src/main/res/drawable-night-mdpi/ic_cia_install.png b/src/android/app/src/main/res/drawable-night-mdpi/ic_install.png
similarity index 100%
rename from src/android/app/src/main/res/drawable-night-mdpi/ic_cia_install.png
rename to src/android/app/src/main/res/drawable-night-mdpi/ic_install.png
diff --git a/src/android/app/src/main/res/drawable-night-xhdpi/ic_cia_install.png b/src/android/app/src/main/res/drawable-night-xhdpi/ic_install.png
similarity index 100%
rename from src/android/app/src/main/res/drawable-night-xhdpi/ic_cia_install.png
rename to src/android/app/src/main/res/drawable-night-xhdpi/ic_install.png
diff --git a/src/android/app/src/main/res/drawable-night-xxhdpi/ic_cia_install.png b/src/android/app/src/main/res/drawable-night-xxhdpi/ic_install.png
similarity index 100%
rename from src/android/app/src/main/res/drawable-night-xxhdpi/ic_cia_install.png
rename to src/android/app/src/main/res/drawable-night-xxhdpi/ic_install.png
diff --git a/src/android/app/src/main/res/drawable-night-xxxhdpi/ic_cia_install.png b/src/android/app/src/main/res/drawable-night-xxxhdpi/ic_install.png
similarity index 100%
rename from src/android/app/src/main/res/drawable-night-xxxhdpi/ic_cia_install.png
rename to src/android/app/src/main/res/drawable-night-xxxhdpi/ic_install.png
diff --git a/src/android/app/src/main/res/drawable-xhdpi/ic_cia_install.png b/src/android/app/src/main/res/drawable-xhdpi/ic_install.png
similarity index 100%
rename from src/android/app/src/main/res/drawable-xhdpi/ic_cia_install.png
rename to src/android/app/src/main/res/drawable-xhdpi/ic_install.png
diff --git a/src/android/app/src/main/res/drawable-xxhdpi/ic_cia_install.png b/src/android/app/src/main/res/drawable-xxhdpi/ic_install.png
similarity index 100%
rename from src/android/app/src/main/res/drawable-xxhdpi/ic_cia_install.png
rename to src/android/app/src/main/res/drawable-xxhdpi/ic_install.png
diff --git a/src/android/app/src/main/res/drawable-xxxhdpi/ic_cia_install.png b/src/android/app/src/main/res/drawable-xxxhdpi/ic_install.png
similarity index 100%
rename from src/android/app/src/main/res/drawable-xxxhdpi/ic_cia_install.png
rename to src/android/app/src/main/res/drawable-xxxhdpi/ic_install.png
diff --git a/src/android/app/src/main/res/menu/menu_game_grid.xml b/src/android/app/src/main/res/menu/menu_game_grid.xml
index cd515afbf..3eb8cf817 100644
--- a/src/android/app/src/main/res/menu/menu_game_grid.xml
+++ b/src/android/app/src/main/res/menu/menu_game_grid.xml
@@ -14,9 +14,9 @@
                 android:title="@string/select_game_folder"
                 app:showAsAction="ifRoom" />
             <item
-                android:id="@+id/button_install_cia"
-                android:icon="@drawable/ic_cia_install"
-                android:title="@string/install_cia_title"
+                android:id="@+id/button_install_keys"
+                android:icon="@drawable/ic_install"
+                android:title="@string/install_keys"
                 app:showAsAction="ifRoom" />
         </menu>
     </item>
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index 893f6aa1a..1c6858a60 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -3,7 +3,7 @@
 
     <!-- General application strings -->
     <string name="app_name" translatable="false">yuzu</string>
-    <string name="app_disclaimer">This software will run games for the Nintendo Switch game console. No game titles are included.\n\nBefore you run, please place your rightfully owned Switch game files onto your device storage.</string>
+    <string name="app_disclaimer">This software will run games for the Nintendo Switch game console. No game titles or keys are included.&lt;br /&gt;&lt;br /&gt;Before you begin, please locate your <![CDATA[<b> prod.keys </b>]]> file on your device storage.&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href="https://yuzu-emu.org/wiki/dumping-decryption-keys-from-a-switch-console/">Learn more</a>]]></string>
     <string name="app_notification_channel_name" translatable="false">yuzu</string>
     <string name="app_notification_channel_id" translatable="false">yuzu</string>
     <string name="app_notification_channel_description">yuzu Switch emulator notifications</string>
@@ -49,7 +49,9 @@
 
     <!-- Add Directory Screen-->
     <string name="select_game_folder">Select game folder</string>
-    <string name="install_cia_title">Install CIA</string>
+    <string name="install_keys">Install keys</string>
+    <string name="install_keys_success">Keys successfully installed</string>
+    <string name="install_keys_failure">Keys file (prod.keys) is invalid</string>
 
     <!-- Preferences Screen -->
     <string name="preferences_settings">Settings</string>
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index 0bd5859d0..4ff2c50e5 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -706,7 +706,7 @@ void KeyManager::LoadFromFile(const std::filesystem::path& file_path, bool is_ti
     }
 }
 
-bool KeyManager::IsKeysLoaded() const {
+bool KeyManager::AreKeysLoaded() const {
     return !s128_keys.empty() && !s256_keys.empty();
 }
 
diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h
index fb991ae54..8c864503b 100644
--- a/src/core/crypto/key_manager.h
+++ b/src/core/crypto/key_manager.h
@@ -268,7 +268,7 @@ public:
     bool AddTicketPersonalized(Ticket raw);
 
     void ReloadKeys();
-    bool IsKeysLoaded() const;
+    bool AreKeysLoaded() const;
 
 private:
     KeyManager();