React Native onActivityResult不起作用。

6

我有一个React Native的webview组件。这个webview应该支持文件输入类型,所以我这样做:

在WebView中上传文件

并且这个webview实现了ActivityEventListener并重写了onActivityResult方法。但是onActivityResult没有起作用。

代码如下:

class RNWebView extends WebView implements ActivityEventListener {
      protected class GeoWebChromeClient extends WebChromeClient {
          public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
           ...
            mActivity.startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE);
            return true;
          }
      }

    public RNWebView(ReactContext reactContext, Activity activity) {
        super(reactContext);
        // Add the listener for `onActivityResult`
        reactContext.addActivityEventListener(this);
        ...
     }

@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
    // Your logic here
    Log.d("Tanck", "requestCode:" + requestCode + "----" + "resultCode:" + resultCode);
}

}
3个回答

18

也许晚点但希望能有所帮助。

原生模块的onActivityResultReactContext调用,ReactContext又被ReactInstanceManagerImpl调用,在0.29中,ReactInstanceManagerImplReactActivity调用。在上面的示例中,MyWb扩展了Activity而不是ReactActivity,因此ReactInstanceManagerImpl从未被调用。

解决方法就在你的activity的onActivityResult中调用ReactInstanceManageronActivityResult,因为你已经有自己的ReactInstanceManager对象引用。

启动React Native的Activity应该有一个类似于这样的重写:

// Manually pass along the `onActivityResult` event to React Native event listeners.
// We are not extending from `ReactActivity` so we need to do this manually.
// 
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

  mReactInstanceManager.onActivityResult( this, requestCode, resultCode, data );

}

只是为了澄清,您需要在启动 React Native 的 Activity 上放置 onActivityResult 并调用 mReactInstanceManager.onActivityResult( ... )(或者任何您称呼它的名称)。或者,您可以从 ReactActivity 扩展该 Activity。 - Joshua Pinter

1
如果有人在使用Promise的React Native模块中使用Kotlin,请参考以下代码:
import android.app.Activity
import android.content.Intent
import android.util.Log
import com.facebook.react.bridge.*
import com.onboardinglib.HostActivity

class ConsistyOnboarding (reactContext: ReactApplicationContext) :
  ReactContextBaseJavaModule(reactContext) {

  private val CODE = 999
  private var promise: Promise? = null
  private val reContext: ReactApplicationContext? = reactContext

  fun dumpIntent(intent: Intent) {
    LogPrint("Bundle data", "Dumping intent start")

    val bundleData = intent.extras
    if (bundleData != null) {
      for (key in bundleData.keySet()) {
        LogPrint(
          "Bundle data-->",
          key + " : " + if (bundleData[key] != null) bundleData[key] else "NULL"
        )
      }
    }
  }

  override fun getName(): String {
    return "ConsistyOnboarding"
  }

  private val mActivityEventListener: ActivityEventListener =
    object : BaseActivityEventListener() {
      override fun onActivityResult(
        activity: Activity,
        requestCode: Int,
        resultCode: Int,
        data: Intent
      ) {
        LogPrint("mActivityEventListener", "Started")

        if (data == null) {
          resolve("01", "No action taken", "0")
          return
        }

        dumpIntent(data)

        if (resultCode == Activity.RESULT_OK) {
          try {
            val status = data.getBooleanExtra("status", false)
            val response = data.getIntExtra("response", 0)
            val message = data.getStringExtra("message")
            resolve(status.toString(), response.toString(), message.toString())
            return
          } catch (e: Exception) {
            e.printStackTrace()
            resolve("01", "Exception occurred in on-boarding " + e.message, "0")
          }
        }
        resolve("01", "No action taken", "0")
      }
    }


  init {
    reContext?.addActivityEventListener(mActivityEventListener)
  }


  @ReactMethod
  fun Onboarding(
    partnerId: String, partnerKey: String  prm: Promise
  ) {

    promise = prm
    val currentActivity = currentActivity
    val intent = Intent(currentActivity, HostActivity::class.java)

    intent.putExtra("pId", partnerId) 
    intent.putExtra("ApiKey", partnerKey) 
    
    try {
      currentActivity?.startActivityForResult(intent, CODE)
    } catch (e: Exception) {
      e.printStackTrace()
      resolve("01", "No action taken", "0")
    }
  }

  private fun resolve(
    statusCode: String,
    response: String,
    message: String
  ) {
    if (promise == null) {
      return
    }

    val map = Arguments.createMap()

    map.putString("statusCode", statusCode)
    map.putString("response", response)
    map.putString("message", message)

    promise!!.resolve(map)
    promise = null
  }

  private fun LogPrint(key: String?, value: String?) {
    if (key == null || value == null) {
      return
    }
    Log.i(key, value)
  }
}

主要部分需要添加事件监听器。
init {
    reContext?.addActivityEventListener(mActivityEventListener)
  }

1
为了使解决方案完整:
在您的MainActivity(或在初始化RN并使用mReactInstanceManager的Activity中,如果它是本地应用程序的一部分)中:
...
private ReactInstanceManager mReactInstanceManager;
...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    mReactInstanceManager.onActivityResult(requestCode, resultCode, data);
}

在你的模块中:
public class MyModule extends ReactContextBaseJavaModule implements ActivityEventListener {
    static final int REQUEST_VIDEO_CAPTURE = 1;

    final ReactApplicationContext reactContext;
    Promise promise;

    public GeneralIntentModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
        this.reactContext.addActivityEventListener(this);
    }

    @Override
    public String getName() {
        return "MyModule ";
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        this.promise.resolve(data.getDataString());
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接