diff --git a/src/android/app/src/main/jni/CMakeLists.txt b/src/android/app/src/main/jni/CMakeLists.txt
index 77b95130d..443b39d57 100644
--- a/src/android/app/src/main/jni/CMakeLists.txt
+++ b/src/android/app/src/main/jni/CMakeLists.txt
@@ -1,4 +1,6 @@
 add_library(citra-android SHARED
+    android_common/android_common.cpp
+    android_common/android_common.h
     applets/mii_selector.cpp
     applets/mii_selector.h
     applets/swkbd.cpp
diff --git a/src/android/app/src/main/jni/android_common/android_common.cpp b/src/android/app/src/main/jni/android_common/android_common.cpp
new file mode 100644
index 000000000..dedd33151
--- /dev/null
+++ b/src/android/app/src/main/jni/android_common/android_common.cpp
@@ -0,0 +1,32 @@
+// Copyright 2022 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "jni/android_common/android_common.h"
+
+#include <string>
+#include <string_view>
+
+#include <jni.h>
+
+#include "common/string_util.h"
+
+std::string GetJString(JNIEnv* env, jstring jstr) {
+    if (!jstr) {
+        return {};
+    }
+
+    const jchar* jchars = env->GetStringChars(jstr, nullptr);
+    const jsize length = env->GetStringLength(jstr);
+    const std::u16string_view string_view(reinterpret_cast<const char16_t*>(jchars), length);
+    const std::string converted_string = Common::UTF16ToUTF8(string_view);
+    env->ReleaseStringChars(jstr, jchars);
+
+    return converted_string;
+}
+
+jstring ToJString(JNIEnv* env, std::string_view str) {
+    const std::u16string converted_string = Common::UTF8ToUTF16(str);
+    return env->NewString(reinterpret_cast<const jchar*>(converted_string.data()),
+                          static_cast<jint>(converted_string.size()));
+}
diff --git a/src/android/app/src/main/jni/android_common/android_common.h b/src/android/app/src/main/jni/android_common/android_common.h
new file mode 100644
index 000000000..a09f7bc45
--- /dev/null
+++ b/src/android/app/src/main/jni/android_common/android_common.h
@@ -0,0 +1,12 @@
+// Copyright 2022 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <string>
+
+#include <jni.h>
+
+std::string GetJString(JNIEnv* env, jstring jstr);
+jstring ToJString(JNIEnv* env, std::string_view str);
diff --git a/src/android/app/src/main/jni/applets/mii_selector.cpp b/src/android/app/src/main/jni/applets/mii_selector.cpp
index 0e8e79238..2009a84ec 100644
--- a/src/android/app/src/main/jni/applets/mii_selector.cpp
+++ b/src/android/app/src/main/jni/applets/mii_selector.cpp
@@ -3,6 +3,7 @@
 // Refer to the license.txt file included.
 
 #include "common/string_util.h"
+#include "jni/android_common/android_common.h"
 #include "jni/applets/mii_selector.h"
 #include "jni/id_cache.h"
 
@@ -26,7 +27,7 @@ void AndroidMiiSelector::Setup(const Frontend::MiiSelectorConfig& config) {
                          static_cast<jboolean>(config.enable_cancel_button));
     env->SetObjectField(java_config,
                         env->GetFieldID(s_mii_selector_config_class, "title", "Ljava/lang/String;"),
-                        env->NewStringUTF(config.title.c_str()));
+                        ToJString(env, config.title));
     env->SetLongField(
         java_config,
         env->GetFieldID(s_mii_selector_config_class, "initially_selected_mii_index", "J"),
@@ -39,7 +40,7 @@ void AndroidMiiSelector::Setup(const Frontend::MiiSelectorConfig& config) {
         env->NewObjectArray(static_cast<jsize>(miis.size()), string_class, nullptr);
     for (std::size_t i = 0; i < miis.size(); ++i) {
         const auto name = Common::UTF16BufferToUTF8(miis[i].mii_name);
-        env->SetObjectArrayElement(array, static_cast<jsize>(i), env->NewStringUTF(name.c_str()));
+        env->SetObjectArrayElement(array, static_cast<jsize>(i), ToJString(env, name));
     }
     env->SetObjectField(
         java_config,
diff --git a/src/android/app/src/main/jni/applets/swkbd.cpp b/src/android/app/src/main/jni/applets/swkbd.cpp
index 062d307a6..e373c9e27 100644
--- a/src/android/app/src/main/jni/applets/swkbd.cpp
+++ b/src/android/app/src/main/jni/applets/swkbd.cpp
@@ -3,22 +3,14 @@
 // Refer to the license.txt file included.
 
 #include <map>
+
 #include <jni.h>
+
 #include "core/core.h"
+#include "jni/android_common/android_common.h"
 #include "jni/applets/swkbd.h"
 #include "jni/id_cache.h"
 
-static std::string GetJString(JNIEnv* env, jstring jstr) {
-    if (!jstr) {
-        return {};
-    }
-
-    const char* s = env->GetStringUTFChars(jstr, nullptr);
-    std::string result = s;
-    env->ReleaseStringUTFChars(jstr, s);
-    return result;
-}
-
 static jclass s_software_keyboard_class;
 static jclass s_keyboard_config_class;
 static jclass s_keyboard_data_class;
@@ -39,15 +31,15 @@ static jobject ToJavaKeyboardConfig(const Frontend::KeyboardConfig& config) {
                          static_cast<jboolean>(config.multiline_mode));
     env->SetObjectField(object,
                         env->GetFieldID(s_keyboard_config_class, "hint_text", "Ljava/lang/String;"),
-                        env->NewStringUTF(config.hint_text.c_str()));
+                        ToJString(env, config.hint_text));
 
     const jclass string_class = reinterpret_cast<jclass>(env->FindClass("java/lang/String"));
     const jobjectArray array =
         env->NewObjectArray(static_cast<jsize>(config.button_text.size()), string_class,
-                            env->NewStringUTF(config.button_text[0].c_str()));
+                            ToJString(env, config.button_text[0]));
     for (std::size_t i = 1; i < config.button_text.size(); ++i) {
         env->SetObjectArrayElement(array, static_cast<jsize>(i),
-                                   env->NewStringUTF(config.button_text[i].c_str()));
+                                   ToJString(env, config.button_text[i]));
     }
     env->SetObjectField(
         object, env->GetFieldID(s_keyboard_config_class, "button_text", "[Ljava/lang/String;"),
@@ -78,8 +70,7 @@ void AndroidKeyboard::Execute(const Frontend::KeyboardConfig& config) {
 
 void AndroidKeyboard::ShowError(const std::string& error) {
     JNIEnv* env = IDCache::GetEnvForThread();
-    env->CallStaticVoidMethod(s_software_keyboard_class, s_swkbd_show_error,
-                              env->NewStringUTF(error.c_str()));
+    env->CallStaticVoidMethod(s_software_keyboard_class, s_swkbd_show_error, ToJString(env, error));
 }
 
 void InitJNI(JNIEnv* env) {
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 6dffc1225..e876ecb3e 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -27,6 +27,7 @@
 #include "core/hle/service/nfc/nfc.h"
 #include "core/savestate.h"
 #include "core/settings.h"
+#include "jni/android_common/android_common.h"
 #include "jni/applets/mii_selector.h"
 #include "jni/applets/swkbd.h"
 #include "jni/camera/ndk_camera.h"
@@ -58,24 +59,13 @@ std::condition_variable running_cv;
 
 } // Anonymous namespace
 
-static std::string GetJString(JNIEnv* env, jstring jstr) {
-    if (!jstr) {
-        return {};
-    }
-
-    const char* s = env->GetStringUTFChars(jstr, nullptr);
-    std::string result = s;
-    env->ReleaseStringUTFChars(jstr, s);
-    return result;
-}
-
 static bool DisplayAlertMessage(const char* caption, const char* text, bool yes_no) {
     JNIEnv* env = IDCache::GetEnvForThread();
 
     // Execute the Java method.
     jboolean result = env->CallStaticBooleanMethod(
-        IDCache::GetNativeLibraryClass(), IDCache::GetDisplayAlertMsg(), env->NewStringUTF(caption),
-        env->NewStringUTF(text), yes_no ? JNI_TRUE : JNI_FALSE);
+        IDCache::GetNativeLibraryClass(), IDCache::GetDisplayAlertMsg(), ToJString(env, caption),
+        ToJString(env, text), yes_no ? JNI_TRUE : JNI_FALSE);
 
     return result != JNI_FALSE;
 }
@@ -84,8 +74,8 @@ static std::string DisplayAlertPrompt(const char* caption, const char* text, int
     JNIEnv* env = IDCache::GetEnvForThread();
 
     jstring value = reinterpret_cast<jstring>(env->CallStaticObjectMethod(
-        IDCache::GetNativeLibraryClass(), IDCache::GetDisplayAlertPrompt(),
-        env->NewStringUTF(caption), env->NewStringUTF(text), buttonConfig));
+        IDCache::GetNativeLibraryClass(), IDCache::GetDisplayAlertPrompt(), ToJString(env, caption),
+        ToJString(env, text), buttonConfig));
 
     return GetJString(env, value);
 }
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index 395cf1d38..47aaddddb 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -8,6 +8,8 @@
 #include <cstdlib>
 #include <locale>
 #include <sstream>
+#include <string>
+#include <string_view>
 #include "common/common_paths.h"
 #include "common/logging/log.h"
 #include "common/string_util.h"
@@ -135,14 +137,14 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
     return result;
 }
 
-std::string UTF16ToUTF8(const std::u16string& input) {
+std::string UTF16ToUTF8(std::u16string_view input) {
     std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
-    return convert.to_bytes(input);
+    return convert.to_bytes(input.data(), input.data() + input.size());
 }
 
-std::u16string UTF8ToUTF16(const std::string& input) {
+std::u16string UTF8ToUTF16(std::string_view input) {
     std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
-    return convert.from_bytes(input);
+    return convert.from_bytes(input.data(), input.data() + input.size());
 }
 
 #ifdef _WIN32
diff --git a/src/common/string_util.h b/src/common/string_util.h
index 2c454bb7b..d9edbf803 100644
--- a/src/common/string_util.h
+++ b/src/common/string_util.h
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <cstddef>
 #include <string>
+#include <string_view>
 #include <vector>
 #include "common/common_types.h"
 #include "common/swap.h"
@@ -37,8 +38,8 @@ void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _P
 [[nodiscard]] std::string ReplaceAll(std::string result, const std::string& src,
                                      const std::string& dest);
 
-[[nodiscard]] std::string UTF16ToUTF8(const std::u16string& input);
-[[nodiscard]] std::u16string UTF8ToUTF16(const std::string& input);
+[[nodiscard]] std::string UTF16ToUTF8(std::u16string_view input);
+[[nodiscard]] std::u16string UTF8ToUTF16(std::string_view input);
 
 #ifdef _WIN32
 [[nodiscard]] std::string UTF16ToUTF8(const std::wstring& input);