From a9f68c976b436f201ac8fed6e26e761b5f8b4756 Mon Sep 17 00:00:00 2001 From: Julian Winkler Date: Fri, 25 Jul 2025 16:41:59 +0200 Subject: [PATCH] startActivity(): implement Intent.FLAG_ACTIVITY_CLEAR_TOP --- src/api-impl-jni/app/android_app_Activity.c | 32 +++++++++++++++++++ .../generated_headers/android_app_Activity.h | 8 +++++ src/api-impl-jni/handle_cache.c | 1 + src/api-impl-jni/handle_cache.h | 1 + src/api-impl/android/app/Activity.java | 1 + src/api-impl/android/content/Context.java | 8 +++-- src/api-impl/android/content/Intent.java | 1 + 7 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/api-impl-jni/app/android_app_Activity.c b/src/api-impl-jni/app/android_app_Activity.c index 768e7e3f..3bb27a1a 100644 --- a/src/api-impl-jni/app/android_app_Activity.c +++ b/src/api-impl-jni/app/android_app_Activity.c @@ -151,6 +151,9 @@ static jobject activity_not_created = NULL; void activity_start(JNIEnv *env, jobject activity_object) { + if (activity_current) + activity_unfocus(env, activity_current); + activity_current = NULL; /* -- run the activity's onCreate -- */ (*env)->CallVoidMethod(env, activity_object, handle_cache.activity.onCreate, NULL); if((*env)->ExceptionCheck(env)) @@ -198,6 +201,35 @@ JNIEXPORT void JNICALL Java_android_app_Activity_nativeStartActivity(JNIEnv *env activity_start(env, activity); } +JNIEXPORT void JNICALL Java_android_app_Activity_nativeResumeActivity(JNIEnv *env, jclass class, jclass activity_class, jobject intent) +{ + GList *l; + GList *activities_to_close = NULL; + for (l = activity_backlog; l != NULL; l = l->next) { + if ((*env)->IsSameObject(env, activity_class, _CLASS(l->data))) { + if (l != activity_backlog) { + activities_to_close = activity_backlog; + activity_backlog = l; + l->prev->next = NULL; + l->prev = NULL; + } + + /* -- run the activity's onNewIntent -- */ + (*env)->CallVoidMethod(env, l->data, handle_cache.activity.onNewIntent, intent); + if((*env)->ExceptionCheck(env)) + (*env)->ExceptionDescribe(env); + break; + } + } + activity_update_current(env); + + for (l = activities_to_close; l != NULL; l = l->next) { + activity_close(env, l->data); + _UNREF(l->data); + } + g_list_free(activities_to_close); +} + JNIEXPORT void JNICALL Java_android_app_Activity_nativeOpenURI(JNIEnv *env, jclass class, jstring uriString) { static XdpPortal *portal = NULL; diff --git a/src/api-impl-jni/generated_headers/android_app_Activity.h b/src/api-impl-jni/generated_headers/android_app_Activity.h index b2619a12..b99f8c61 100644 --- a/src/api-impl-jni/generated_headers/android_app_Activity.h +++ b/src/api-impl-jni/generated_headers/android_app_Activity.h @@ -29,6 +29,14 @@ JNIEXPORT void JNICALL Java_android_app_Activity_nativeFinish JNIEXPORT void JNICALL Java_android_app_Activity_nativeStartActivity (JNIEnv *, jclass, jobject); +/* + * Class: android_app_Activity + * Method: nativeResumeActivity + * Signature: (Ljava/lang/Class;Landroid/content/Intent;)V + */ +JNIEXPORT void JNICALL Java_android_app_Activity_nativeResumeActivity + (JNIEnv *, jclass, jclass, jobject); + /* * Class: android_app_Activity * Method: nativeOpenURI diff --git a/src/api-impl-jni/handle_cache.c b/src/api-impl-jni/handle_cache.c index 073bc436..ead408ec 100644 --- a/src/api-impl-jni/handle_cache.c +++ b/src/api-impl-jni/handle_cache.c @@ -17,6 +17,7 @@ void set_up_handle_cache(JNIEnv *env) handle_cache.activity.onStop = _METHOD(handle_cache.activity.class, "onStop", "()V"); handle_cache.activity.onPause = _METHOD(handle_cache.activity.class, "onPause", "()V"); handle_cache.activity.onBackPressed = _METHOD(handle_cache.activity.class, "onBackPressed", "()V"); + handle_cache.activity.onNewIntent = _METHOD(handle_cache.activity.class, "onNewIntent", "(Landroid/content/Intent;)V"); handle_cache.attribute_set.class = _REF((*env)->FindClass(env, "android/util/AttributeSet")); if((*env)->ExceptionCheck(env)) diff --git a/src/api-impl-jni/handle_cache.h b/src/api-impl-jni/handle_cache.h index 462e3fb4..1001b926 100644 --- a/src/api-impl-jni/handle_cache.h +++ b/src/api-impl-jni/handle_cache.h @@ -13,6 +13,7 @@ struct handle_cache { jmethodID onStop; jmethodID onPause; jmethodID onBackPressed; + jmethodID onNewIntent; } activity; struct { jclass class; diff --git a/src/api-impl/android/app/Activity.java b/src/api-impl/android/app/Activity.java index ca1afaae..62f739f5 100644 --- a/src/api-impl/android/app/Activity.java +++ b/src/api-impl/android/app/Activity.java @@ -586,6 +586,7 @@ public class Activity extends ContextThemeWrapper implements Window.Callback, La private native void nativeFinish(long native_window); public static native void nativeStartActivity(Activity activity); + public static native void nativeResumeActivity(Class activityClass, Intent intent); public static native void nativeOpenURI(String uri); public native void nativeFileChooser(int action, String type, String title, int requestCode); public void reportFullyDrawn() {} diff --git a/src/api-impl/android/content/Context.java b/src/api-impl/android/content/Context.java index de50070d..d0796eb0 100644 --- a/src/api-impl/android/content/Context.java +++ b/src/api-impl/android/content/Context.java @@ -622,8 +622,12 @@ public class Context extends Object { @Override public void run() { try { - Activity activity = Activity.internalCreateActivity(className_, this_application.native_window, intent_); - Activity.nativeStartActivity(activity); + if ((intent_.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0 && intent_.getComponent() != null) { + Activity.nativeResumeActivity(Class.forName(intent_.getComponent().getClassName()).asSubclass(Activity.class), intent_); + } else { + Activity activity = Activity.internalCreateActivity(className_, this_application.native_window, intent_); + Activity.nativeStartActivity(activity); + } } catch (Exception e) { e.printStackTrace(); } diff --git a/src/api-impl/android/content/Intent.java b/src/api-impl/android/content/Intent.java index 309f3af1..6e50fc3b 100644 --- a/src/api-impl/android/content/Intent.java +++ b/src/api-impl/android/content/Intent.java @@ -17,6 +17,7 @@ import java.util.Set; public class Intent implements Parcelable { public static final String ACTION_MAIN = "android.intent.action.MAIN"; public static final int FLAG_ACTIVITY_NEW_TASK = 0x10000000; + public static final int FLAG_ACTIVITY_CLEAR_TOP = 0x04000000; private ComponentName component; private Bundle extras = new Bundle();