Implement client restarting on Android

Restarting the client previously did not work, as the `shell_execute` function on Android uses `fork` which is not supported.

Now, the client is restarted by using an Android intent to restart the main activity. This is triggered by sending a user-defined message from the native code to the SDL main activity thread.
This commit is contained in:
Robert Müller 2024-07-16 12:34:19 +02:00
parent 804e87a979
commit d4f47c2a55
4 changed files with 46 additions and 0 deletions

View file

@ -3,10 +3,13 @@ package org.ddnet.client;
import android.app.NativeActivity;
import org.libsdl.app.SDLActivity;
import android.os.Bundle;
import android.content.Intent;
import android.content.pm.ActivityInfo;
public class NativeMain extends SDLActivity {
private static final int COMMAND_RESTART_APP = SDLActivity.COMMAND_USER + 1;
@Override
protected String[] getLibraries() {
return new String[] {
@ -19,4 +22,24 @@ public class NativeMain extends SDLActivity {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
super.onCreate(SavedInstanceState);
}
@Override
protected boolean onUnhandledMessage(int command, Object param) {
if(command == COMMAND_RESTART_APP) {
restartApp();
return true;
}
return false;
}
private void restartApp() {
Intent restartIntent =
Intent.makeRestartActivityTask(
getPackageManager().getLaunchIntentForPackage(
getPackageName()
).getComponent()
);
restartIntent.setPackage(getPackageName());
startActivity(restartIntent);
}
}

View file

@ -225,3 +225,12 @@ const char *InitAndroid()
return nullptr;
}
// See NativeMain.java
constexpr uint32_t COMMAND_USER = 0x8000;
constexpr uint32_t COMMAND_RESTART_APP = COMMAND_USER + 1;
void RestartAndroidApp()
{
SDL_AndroidSendMessage(COMMAND_RESTART_APP, 0);
}

View file

@ -20,4 +20,12 @@
*/
const char *InitAndroid();
/**
* Sends an intent to the Android system to restart the app.
*
* This will restart the main activity in a new task. The current process
* must immediately terminate after this function is called.
*/
void RestartAndroidApp();
#endif // ANDROID_ANDROID_MAIN_H

View file

@ -4594,11 +4594,13 @@ int main(int argc, const char **argv)
pClient->Run();
const bool Restarting = pClient->State() == CClient::STATE_RESTARTING;
#if !defined(CONF_PLATFORM_ANDROID)
char aRestartBinaryPath[IO_MAX_PATH_LENGTH];
if(Restarting)
{
pStorage->GetBinaryPath(PLAT_CLIENT_EXEC, aRestartBinaryPath, sizeof(aRestartBinaryPath));
}
#endif
std::vector<SWarning> vQuittingWarnings = pClient->QuittingWarnings();
@ -4611,7 +4613,11 @@ int main(int argc, const char **argv)
if(Restarting)
{
#if defined(CONF_PLATFORM_ANDROID)
RestartAndroidApp();
#else
shell_execute(aRestartBinaryPath, EShellExecuteWindowState::FOREGROUND);
#endif
}
PerformFinalCleanup();