diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java
index 027d476095..91b29e4410 100644
--- a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java
@@ -169,6 +169,12 @@ public final class NativeLibrary
 	 */
 	public static native void CreateUserFolders();
 
+	/**
+	 * Sets the current working user directory
+	 * If not set, it auto-detects a location
+	 */
+	public static native void SetUserDirectory(String directory);
+
 	/**
 	 * Begins emulation.
 	 * 
diff --git a/Source/Core/Common/FileUtil.cpp b/Source/Core/Common/FileUtil.cpp
index a20543e3ec..e4fc2bb5c7 100644
--- a/Source/Core/Common/FileUtil.cpp
+++ b/Source/Core/Common/FileUtil.cpp
@@ -21,7 +21,6 @@
 #include <direct.h>    // getcwd
 #include <io.h>
 #include <shellapi.h>
-#include <shlobj.h>    // for SHGetFolderPath
 #include <windows.h>
 #else
 #include <dirent.h>
@@ -743,66 +742,6 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new
 	// Set up all paths and files on the first run
 	if (paths[D_USER_IDX].empty())
 	{
-#ifdef _WIN32
-		// Detect where the User directory is. There are five different cases (on top of the
-		// command line flag, which overrides all this):
-		// 1. GetExeDirectory()\portable.txt exists
-		//    -> Use GetExeDirectory()\User
-		// 2. HKCU\Software\Dolphin Emulator\LocalUserConfig exists and is true
-		//    -> Use GetExeDirectory()\User
-		// 3. HKCU\Software\Dolphin Emulator\UserConfigPath exists
-		//    -> Use this as the user directory path
-		// 4. My Documents exists
-		//    -> Use My Documents\Dolphin Emulator as the User directory path
-		// 5. Default
-		//    -> Use GetExeDirectory()\User
-
-		// Check our registry keys
-		HKEY hkey;
-		DWORD local = 0;
-		TCHAR configPath[MAX_PATH] = {0};
-		if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Software\\Dolphin Emulator"), 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS)
-		{
-			DWORD size = 4;
-			if (RegQueryValueEx(hkey, TEXT("LocalUserConfig"), nullptr, nullptr, reinterpret_cast<LPBYTE>(&local), &size) != ERROR_SUCCESS)
-				local = 0;
-
-			size = MAX_PATH;
-			if (RegQueryValueEx(hkey, TEXT("UserConfigPath"), nullptr, nullptr, (LPBYTE)configPath, &size) != ERROR_SUCCESS)
-				configPath[0] = 0;
-			RegCloseKey(hkey);
-		}
-
-		local = local || File::Exists(GetExeDirectory() + DIR_SEP "portable.txt");
-
-		// Get Program Files path in case we need it.
-		TCHAR my_documents[MAX_PATH];
-		bool my_documents_found = SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_MYDOCUMENTS, nullptr, SHGFP_TYPE_CURRENT, my_documents));
-
-		if (local) // Case 1-2
-			paths[D_USER_IDX] = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP;
-		else if (configPath[0]) // Case 3
-			paths[D_USER_IDX] = TStrToUTF8(configPath);
-		else if (my_documents_found) // Case 4
-			paths[D_USER_IDX] = TStrToUTF8(my_documents) + DIR_SEP "Dolphin Emulator" DIR_SEP;
-		else // Case 5
-			paths[D_USER_IDX] = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP;
-
-		// Prettify the path: it will be displayed in some places, we don't want a mix of \ and /.
-		paths[D_USER_IDX] = ReplaceAll(paths[D_USER_IDX], "\\", DIR_SEP);
-
-		// Make sure it ends in DIR_SEP.
-		if (*paths[D_USER_IDX].rbegin() != DIR_SEP_CHR)
-			paths[D_USER_IDX] += DIR_SEP;
-#else
-		if (File::Exists(ROOT_DIR DIR_SEP USERDATA_DIR))
-			paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP;
-		else
-			paths[D_USER_IDX] = std::string(getenv("HOME") ?
-				getenv("HOME") : getenv("PWD") ?
-				getenv("PWD") : "") + DIR_SEP DOLPHIN_DATA_DIR DIR_SEP;
-#endif
-
 		paths[D_GCUSER_IDX]         = paths[D_USER_IDX] + GC_USER_DIR DIR_SEP;
 		paths[D_WIIROOT_IDX]        = paths[D_USER_IDX] + WII_USER_DIR;
 		paths[D_WIIUSER_IDX]        = paths[D_WIIROOT_IDX] + DIR_SEP;
diff --git a/Source/Core/DolphinQt/Main.cpp b/Source/Core/DolphinQt/Main.cpp
index dd622a5290..65baf122da 100644
--- a/Source/Core/DolphinQt/Main.cpp
+++ b/Source/Core/DolphinQt/Main.cpp
@@ -42,6 +42,7 @@ int main(int argc, char* argv[])
 	app.setAttribute(Qt::AA_UseHighDpiPixmaps);
 	// TODO: Add command line options
 
+	UICommon::SetUserDirectory(""); // Auto-detect user folder
 	UICommon::CreateDirectories();
 	UICommon::Init();
 
diff --git a/Source/Core/DolphinWX/Main.cpp b/Source/Core/DolphinWX/Main.cpp
index e0a36c023b..ecc7ca6e57 100644
--- a/Source/Core/DolphinWX/Main.cpp
+++ b/Source/Core/DolphinWX/Main.cpp
@@ -229,12 +229,7 @@ bool DolphinApp::OnInit()
 	selectAudioEmulation = parser.Found("audio_emulation", &audioEmulationName);
 	selectPerfDir = parser.Found("perf_dir", &perfDir);
 	playMovie = parser.Found("movie", &movieFile);
-
-	if (parser.Found("user", &userPath))
-	{
-		File::CreateFullPath(WxStrToStr(userPath) + DIR_SEP);
-		File::GetUserPath(D_USER_IDX, userPath.ToStdString() + DIR_SEP);
-	}
+	parser.Found("user", &userPath);
 #endif // wxUSE_CMDLINE_PARSER
 
 	// Register message box and translation handlers
@@ -249,6 +244,7 @@ bool DolphinApp::OnInit()
 	wxHandleFatalExceptions(true);
 #endif
 
+	UICommon::SetUserDirectory(userPath.ToStdString());
 	UICommon::CreateDirectories();
 	UICommon::Init();
 
@@ -421,7 +417,6 @@ void DolphinApp::OnFatalException()
 	WiimoteReal::Shutdown();
 }
 
-
 // ------------
 // Talk to GUI
 
diff --git a/Source/Core/DolphinWX/MainAndroid.cpp b/Source/Core/DolphinWX/MainAndroid.cpp
index 527e76f17a..78960533cd 100644
--- a/Source/Core/DolphinWX/MainAndroid.cpp
+++ b/Source/Core/DolphinWX/MainAndroid.cpp
@@ -49,6 +49,7 @@
 
 ANativeWindow* surf;
 std::string g_filename;
+std::string g_set_userpath = "";
 
 #define DOLPHIN_TAG "Dolphinemu"
 
@@ -231,6 +232,7 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetFilename(
 JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveState(JNIEnv *env, jobject obj, jint slot);
 JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadState(JNIEnv *env, jobject obj, jint slot);
 JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_CreateUserFolders(JNIEnv *env, jobject obj);
+JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetUserDirectory(JNIEnv *env, jobject obj, jstring jDirectory);
 JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv *env, jobject obj, jobject _surf);
 
 JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_UnPauseEmulation(JNIEnv *env, jobject obj)
@@ -361,6 +363,13 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_CreateUserFo
 	File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + JAP_DIR DIR_SEP);
 }
 
+JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetUserDirectory(JNIEnv *env, jobject obj, jstring jDirectory)
+{
+	std::string directory = GetJString(env, jDirectory);
+	g_set_userpath = directory;
+	UICommon::SetUserDirectory(directory);
+}
+
 JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv *env, jobject obj, jobject _surf)
 {
 	surf = ANativeWindow_fromSurface(env, _surf);
@@ -371,6 +380,7 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv *
 
 	RegisterMsgAlertHandler(&MsgAlert);
 
+	UICommon::SetUserDirectory(g_set_userpath);
 	UICommon::Init();
 
 	// No use running the loop when booting fails
diff --git a/Source/Core/DolphinWX/MainNoGUI.cpp b/Source/Core/DolphinWX/MainNoGUI.cpp
index 8d6d0282a6..bd82c8b4f5 100644
--- a/Source/Core/DolphinWX/MainNoGUI.cpp
+++ b/Source/Core/DolphinWX/MainNoGUI.cpp
@@ -324,6 +324,7 @@ int main(int argc, char* argv[])
 		return 1;
 	}
 
+	UICommon::SetUserDirectory(""); // Auto-detect user folder
 	UICommon::Init();
 
 	platform->Init();
diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp
index 735487306a..2c4b9b4a87 100644
--- a/Source/Core/UICommon/UICommon.cpp
+++ b/Source/Core/UICommon/UICommon.cpp
@@ -2,6 +2,10 @@
 // Licensed under GPLv2
 // Refer to the license.txt file included.
 
+#ifdef _WIN32
+#include <shlobj.h>    // for SHGetFolderPath
+#endif
+
 #include "Common/CommonPaths.h"
 #include "Common/FileUtil.h"
 #include "Common/Logging/LogManager.h"
@@ -70,4 +74,77 @@ void CreateDirectories()
 	File::CreateFullPath(File::GetUserPath(D_THEMES_IDX));
 }
 
+void SetUserDirectory(const std::string& custom_path)
+{
+	if (custom_path.size() != 0)
+	{
+		File::CreateFullPath(custom_path + DIR_SEP);
+		File::GetUserPath(D_USER_IDX, custom_path + DIR_SEP);
+		return;
+	}
+
+	std::string user_path = "";
+#ifdef _WIN32
+	// Detect where the User directory is. There are five different cases (on top of the
+	// command line flag, which overrides all this):
+	// 1. GetExeDirectory()\portable.txt exists
+	//    -> Use GetExeDirectory()\User
+	// 2. HKCU\Software\Dolphin Emulator\LocalUserConfig exists and is true
+	//    -> Use GetExeDirectory()\User
+	// 3. HKCU\Software\Dolphin Emulator\UserConfigPath exists
+	//    -> Use this as the user directory path
+	// 4. My Documents exists
+	//    -> Use My Documents\Dolphin Emulator as the User directory path
+	// 5. Default
+	//    -> Use GetExeDirectory()\User
+
+	// Check our registry keys
+	HKEY hkey;
+	DWORD local = 0;
+	TCHAR configPath[MAX_PATH] = {0};
+	if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Software\\Dolphin Emulator"), 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS)
+	{
+		DWORD size = 4;
+		if (RegQueryValueEx(hkey, TEXT("LocalUserConfig"), nullptr, nullptr, reinterpret_cast<LPBYTE>(&local), &size) != ERROR_SUCCESS)
+			local = 0;
+
+		size = MAX_PATH;
+		if (RegQueryValueEx(hkey, TEXT("UserConfigPath"), nullptr, nullptr, (LPBYTE)configPath, &size) != ERROR_SUCCESS)
+			configPath[0] = 0;
+		RegCloseKey(hkey);
+	}
+
+	local = local || File::Exists(File::GetExeDirectory() + DIR_SEP "portable.txt");
+
+	// Get Program Files path in case we need it.
+	TCHAR my_documents[MAX_PATH];
+	bool my_documents_found = SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_MYDOCUMENTS, nullptr, SHGFP_TYPE_CURRENT, my_documents));
+
+	if (local) // Case 1-2
+		user_path = File::GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP;
+	else if (configPath[0]) // Case 3
+		user_path = TStrToUTF8(configPath);
+	else if (my_documents_found) // Case 4
+		user_path = TStrToUTF8(my_documents) + DIR_SEP "Dolphin Emulator" DIR_SEP;
+	else // Case 5
+		user_path = File::GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP;
+
+	// Prettify the path: it will be displayed in some places, we don't want a mix of \ and /.
+	user_path = ReplaceAll(user_path, "\\", DIR_SEP);
+
+	// Make sure it ends in DIR_SEP.
+	if (*user_path.rbegin() != DIR_SEP_CHR)
+		user_path += DIR_SEP;
+#else
+	if (File::Exists(ROOT_DIR DIR_SEP USERDATA_DIR))
+		user_path = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP;
+	else
+		user_path = std::string(getenv("HOME") ?
+			getenv("HOME") : getenv("PWD") ?
+			getenv("PWD") : "") + DIR_SEP DOLPHIN_DATA_DIR DIR_SEP;
+#endif
+
+	File::GetUserPath(D_USER_IDX, user_path);
+}
+
 } // namespace UICommon
diff --git a/Source/Core/UICommon/UICommon.h b/Source/Core/UICommon/UICommon.h
index d177727986..6a5e05fbaf 100644
--- a/Source/Core/UICommon/UICommon.h
+++ b/Source/Core/UICommon/UICommon.h
@@ -11,5 +11,6 @@ void Init();
 void Shutdown();
 
 void CreateDirectories();
+void SetUserDirectory(const std::string& custom_path);
 
 } // namespace UICommon