Efficient Debugging: Start UE Android App with command line parameters

高效调试:命令行参数启动UE Android App

In the process of using UE development, specifying command line parameters is a frequently used feature that facilitates control over certain processes and toggles. UE also extensively uses Commandline to control the behavior of the engine. The official documentation: Command-Line Arguments, allows different modules to read or check parameters from the Commandline, implementing custom command line parameter functionalities.

However, for the mobile Android platform, it is not very convenient to specify startup parameters; editing the ue4commandline.txt file is quite cumbersome.

Based on this pain point, I developed a UE Android plugin during the New Year holiday that allows Android applications to start and specify command line parameters as conveniently as on PC, without needing to modify the engine. Once the plugin is activated, you can package the APK for use. The project is open-sourced on GitHub: hxhb/AppCmderUE.

This article analyzes how UE reads Commandline on the Android side and introduces the implementation principles and usage methods of the AppCmderUE plugin.

On desktop platforms like Windows and Mac, you only need to specify the application path and parameters in a script environment like CMD or bash:

1
2
UE4Editor.exe D:\UnrealProject\BlankGame.uproject -game
BlankGame.exe -log

They will all be passed to the default program entry main function:

1
int main(int argc, char** argv);

Then, it sets the command line for the engine using FCommandLine::Set for runtime use.

As previously mentioned, using Unreal Insights also requires specifying -tracehost and -trace=cpu for controlling the types of profiling data collected and the machine IP to which it is transmitted.

However, there is no convenient method to specify startup parameters for mobile applications developed with UE. UE provides a default mechanism to edit a ue4commandline.txt file, filling in the command line parameters. When the engine starts, it will load this file and append it to the FCommandline of the engine.

I have introduced this method in my previous wiki: Mobile Startup Parameters.

This method is not elegant and has several issues:

  1. The ue4commandline.txt file does not exist by default and must be created manually;
  2. Each modification of the parameters requires accessing the file on the device, modifying it, and saving it;
  3. If you do not want to use startup parameters, you must delete it manually;
  4. On Android 11, tighter permission controls prevent access to the data directory on PC;

Since these pain points were discovered, I attempted to create a new project to address them. To avoid reinventing the wheel and to see what workflows could be leveraged in the engine, I found through code review that besides ue4commandline.txt, there are two other ways to add command line parameters in UE.

AndroidConfigRuleSystem

  1. Through AndroidConfigRuleSystem, Android Configuration Rules System, it is read in GameActivity.java.template#L1579 and passed to the engine’s C++ side via JNI (Java_com_epicgames_ue4_GameActivity_nativeSetConfigRulesVariables), ultimately being retrieved in InitCommandLine and appended to the engine’s command line parameters.
1
2
3
4
5
6
Launch/Private/Android/LaunchAndroid.cpp
if (FString* ConfigRulesCmdLineAppend = FAndroidMisc::GetConfigRulesVariable(TEXT("cmdline")))
{
FCommandLine::Append(**ConfigRulesCmdLineAppend);
FPlatformMisc::LowLevelOutputDebugStringf(TEXT("ConfigRules appended: %s"), **ConfigRulesCmdLineAppend);
}

However, it is not possible to dynamically set it within the engine; it can only be set at the packaging stage and read at runtime.

adb shell setprop

  1. The setprop command can be used to set a property named debug.ue4.commandline via adb, filling the parameter in, which will be appended to the startup parameters. Support for this was only added in the UE4.26 engine, so it cannot be used in UE4.25 and earlier.
1
2
3
4
5
6
7
8
9
10
// Name of the UE4 commandline append setprop
static constexpr char UE4CommandLineSetprop[] = "debug.ue4.commandline";

char CommandLineSetpropAppend[CMD_LINE_MAX];
if (__system_property_get(UE4CommandLineSetprop, CommandLineSetpropAppend) > 0)
{
FCommandLine::Append(UTF8_TO_TCHAR(" "));
FCommandLine::Append(UTF8_TO_TCHAR(CommandLineSetpropAppend));
FPlatformMisc::LowLevelOutputDebugStringf(TEXT("UE4 setprop appended: %s"), UTF8_TO_TCHAR(CommandLineSetpropAppend));
}

Usage example:

1
2
adb shell setprop debug.ue4.commandline '-test123'
adb shell am start com.tencent.tmgp.fmgame/com.epicgames.ue4.GameActivity

If the LaunchImage at startup is enabled:

1
2
bool bShowLaunchImage = false;
Ini.GetBool("/Script/AndroidRuntimeSettings.AndroidRuntimeSettings", "bShowLaunchImage", out bShowLaunchImage);

the launched Activity will change from com.epicgames.ue4.GameActivity to com.epicgames.ue4.SplashActivity.

However, this approach also has drawbacks:

  1. Requires executing two commands.
  2. After setprop, this property persists until the next reboot.
  3. Engines prior to 4.25 cannot use it.

AppCmderUE

I have implemented a solution based on UPL and JNI that combines the advantages of both methods. Just place the plugin in the project, enable it, and package it without any further configuration.

Let’s look at the final effect; the startup command:

1
append_cmd.bat com.imzlp.gworld "-test123" "-test456" "-test789"

UE Log:

1
Final commandline: ../../../Blank426/Blank426.uproject -test123 -test456 -test789

Implementation principles:

  1. The Java side receives parameters via Intent with -e.
  2. In OnCreate, it uses JNI to interact with the engine layer and adds Intent parameters to the AndroidConfigRuleSystem.
  3. Utilizing UE’s own support for the AndroidConfigRuleSystem, the engine can automatically append them to FCommandLine.

The code is not extensive, but by leveraging the Java-side GameActivity and the engine’s UPL, JNI, and other execution workflows, all functionalities can be realized without modifying the engine.

append_cmd.bat is a script I wrapped around the adb command for ease of use:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@echo off
setlocal enabledelayedexpansion
set PROGRAM_NAME = %0
set PACKAGE_NAME=%1
set CMD_LINE_ARGS=" "

FOR %%I IN (%*) do (
@REM echo %%I
if NOT "%PROGRAM_NAME%" == "%%I" (
if NOT "%PACKAGE_NAME%" == "%%I" (
if !CMD_LINE_ARGS! == " " (
set CMD_LINE_ARGS=%%I
@REM echo %CMD_LINE_ARGS%
) else (
set CMD_LINE_ARGS=!CMD_LINE_ARGS!/.,;/%%I
@REM echo %CMD_LINE_ARGS%
)
)
)
)
@REM echo adb shell am start -a android.intent.action.MAIN -n %PACKAGE_NAME%/com.epicgames.ue4.GameActivity --es cmdline %CMD_LINE_ARGS%
adb shell am start -a android.intent.action.MAIN -n %PACKAGE_NAME%/com.epicgames.ue4.GameActivity --es cmdline %CMD_LINE_ARGS%

This command requires passing two parameters:

  1. The package name of the UE packaged APK, such as com.imzlp.gworld;
  2. A list of parameters, separated by spaces. Each parameter needs to be wrapped in double quotes (""). When the script forwards to adb, append_cmd.bat will modify the parameters to be separated by /.,;/ to avoid interference with the included symbols.

For example:

1
append_cmd.bat com.imzlp.gworld "-tracehost=127.0.0.1" "-trace=cpu"

The actual adb command will be:

1
adb shell am start -a android.intent.action.MAIN -n com.imzlp.gworld/com.epicgames.ue4.GameActivity --es cmdline "-tracehost=127.0.0.1"/.,;/"-trace=cpu"

On the engine side, it will automatically parse and append them to FCommandLine in the original format. After executing the above command, profiling data can be directly seen on the PC:

Additionally, on the Android 11 system, because system permissions have tightened, a non-rooted system cannot directly access files in UE’s sandbox path (Android/data/com.xxx.xxxx). If game data paths are in the sandbox directory, it is not convenient to retrieve log files from the device. With the AppCmderUE plugin, you can easily specify UE’s log to another path without modifications to the project.

1
append_cmd.bat com.imzlp.GWorld "-abslog=/storage/emulated/0/GWorld.log"

Thus, executing the append_cmd.bat script will automatically launch the app on the phone and append the parameters, achieving similar functionality to PC.

This approach applies only to Android; a similar solution for iOS can be explored further given time.

ADB over Wi-Fi

In addition to using a USB connection to Android devices, adb also supports Wi-Fi mode. Based on this article’s hxhb/AppCmderUE project and ADB over Wi-Fi, remote profiling becomes very convenient.

  1. Connect the device via USB.
  2. Let the device’s adbd daemon listen on port 5555, waiting for PC connections.
1
adb tcpip 5555
  1. Check the device IP to get the wlan0 IP address.
1
adb shell ifconfig

  1. Disconnect the USB connection to the device.

  2. Connect to the device remotely via adb.

1
2
adb connect DEVICE_IP:5555
# adb connect 192.168.31.172:5555
  1. By using adb devices, you can see the connected remote device.

Once the remote adb environment is set up, you can use append_cmd.bat to remotely start and profile the UE project:

1
append_cmd.bat com.imzlp.gworld "-tracehost=192.168.31.175" "-trace=cpu"

The profiling data can also be captured on the PC using Unreal Insights:

Conclusion

Based on the hxhb/AppCmderUE project, it becomes extremely convenient to pass startup parameters to apps developed with UE, greatly enhancing efficiency in development debugging and performance analysis.

The article is finished. If you have any questions, please comment and communicate.

Scan the QR code on WeChat and follow me.

Title:Efficient Debugging: Start UE Android App with command line parameters
Author:LIPENGZHA
Publish Date:2022/01/01 19:58
World Count:5.8k Words
Link:https://en.imzlp.com/posts/29169/
License: CC BY-NC-SA 4.0
Reprinting of the full article is prohibited.
Your donation will encourage me to keep creating!