You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取startActivityForResult启动的Activity实例并接收回调结果?

问题分析与解决方案

为什么直接new Activity实例会崩溃

Activity是Android系统管控的核心组件,绝对不能通过直接调用构造函数new来创建实例。Android系统需要为Activity初始化上下文、窗口、生命周期管理等核心依赖,这些步骤只有在通过Intent启动Activity时才会由系统自动完成。直接调用构造函数生成的Activity实例缺少这些必要初始化,必然触发崩溃。

正确获取Activity实例并启动带结果的Activity的步骤

1. 在Java层留存已初始化的Activity实例

首先要拿到一个被系统正确初始化的Activity实例,最简单的方式是在目标Activity中保留静态实例,并提供JNI可调用的入口:

package myPackage;

import android.content.Intent;
import android.os.Bundle;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;

public class MyActivity extends AppCompatActivity implements PaymentControllerListener {
    private static MyActivity sInstance;
    // Android 11+推荐用ActivityResultLauncher替代已废弃的startActivityForResult
    private ActivityResultLauncher<Intent> mResultLauncher;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        sInstance = this;
        
        // 注册Activity结果回调
        mResultLauncher = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            result -> {
                if (result.getResultCode() == RESULT_OK) {
                    Intent data = result.getData();
                    // 将结果传递给Native层
                    nativeOnActivityResult(result.getResultCode(), data);
                }
            }
        );
    }

    // 给JNI提供获取当前Activity实例的静态方法
    public static MyActivity getInstance() {
        return sInstance;
    }

    // 给JNI调用的启动目标Activity的方法
    public void launchTargetActivity() {
        Intent intent = new Intent(this, TargetActivity.class);
        mResultLauncher.launch(intent);
    }

    // 接收结果并传递给Native层的Native方法
    private native void nativeOnActivityResult(int resultCode, Intent data);

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 清空静态引用,防止内存泄漏
        sInstance = null;
    }

    // 实现PaymentControllerListener接口的方法...
}

2. 在NDK层获取实例并启动目标Activity

通过JNI调用Java层的静态方法拿到已初始化的Activity实例,再调用启动方法:

#include <jni.h>
#include <android/log.h>

#define LOG_TAG "NativeActivityDemo"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

// 全局引用保存Activity实例,避免被GC回收
jobject gGlobalActivity = nullptr;

extern "C" JNIEXPORT void JNICALL
Java_myPackage_MyActivity_nativeOnActivityResult(JNIEnv* env, jobject thiz, int resultCode, jobject data) {
    // 处理返回结果
    if (resultCode == -1) { // Android中RESULT_OK的常量值为-1
        jclass intentClass = env->FindClass("android/content/Intent");
        jmethodID getStringExtra = env->GetMethodID(intentClass, "getStringExtra", "(Ljava/lang/String;)Ljava/lang/String;");
        
        jstring resultKey = env->NewStringUTF("result_data");
        jstring resultStr = (jstring)env->CallObjectMethod(data, getStringExtra, resultKey);
        
        const char* result = env->GetStringUTFChars(resultStr, nullptr);
        LOGI("Received activity result: %s", result);
        
        // 释放局部引用
        env->ReleaseStringUTFChars(resultStr, result);
        env->DeleteLocalRef(resultKey);
        env->DeleteLocalRef(resultStr);
        env->DeleteLocalRef(intentClass);
    }
}

extern "C" JNIEXPORT void JNICALL
Java_myPackage_MyNativeHelper_launchTargetActivityFromNative(JNIEnv* env, jobject thiz) {
    // 获取MyActivity类引用
    jclass myActivityClass = env->FindClass("myPackage/MyActivity");
    if (myActivityClass == nullptr) {
        LOGI("Failed to find MyActivity class");
        return;
    }

    // 调用静态方法获取Activity实例
    jmethodID getInstanceMethod = env->GetStaticMethodID(myActivityClass, "getInstance", "()LmyPackage/MyActivity;");
    jobject activityObj = env->CallStaticObjectMethod(myActivityClass, getInstanceMethod);
    if (activityObj == nullptr) {
        LOGI("Failed to get MyActivity instance");
        env->DeleteLocalRef(myActivityClass);
        return;
    }

    // 创建全局引用,避免实例被GC回收
    if (gGlobalActivity == nullptr) {
        gGlobalActivity = env->NewGlobalRef(activityObj);
    }

    // 调用启动目标Activity的方法
    jmethodID launchMethod = env->GetMethodID(myActivityClass, "launchTargetActivity", "()V");
    env->CallVoidMethod(gGlobalActivity, launchMethod);

    // 释放局部引用
    env->DeleteLocalRef(activityObj);
    env->DeleteLocalRef(myActivityClass);
}

3. 关键注意事项

  • 防止内存泄漏:在Activity的onDestroy方法中清空静态实例引用,不需要全局引用时调用env->DeleteGlobalRef(gGlobalActivity)释放资源。
  • 版本兼容:如果项目仍在使用Android 10及以下,可继续使用startActivityForResult,但推荐迁移到ActivityResultContracts API(前者已被官方废弃)。
  • 线程安全:如果在非UI线程调用JNI方法,需确保Activity实例处于活跃状态,避免调用已销毁的Activity方法引发崩溃。

内容的提问来源于stack exchange,提问作者Zaitsev Ilya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 22:17:55