6

I have a webview component of React Native. The webview should support input type is file, so I do it as:

File Upload in WebView

and the webview implements ActivityEventListener and override onActivityResult.But the onActivityResult not working.

The Code is

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);
}

}
Community
  • 1
  • 1
shawnXiao
  • 850
  • 3
  • 9
  • 16

3 Answers3

18

Maybe late hope it helps.

native module's onActivityResult is called by ReactContext which is called by ReactInstanceManagerImpl which in 0.29 is called by ReactActivity. In the example above MyWb extends Activity not ReactActivity, so ReactInstanceManagerImpl is never called.

The solution is just in your activity's onActivityResult call ReactInstanceManager's onActivityResult since you already have your own ReactInstanceManager object reference.

The Activity you are launching React Native from should have an override like this:

// 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 );

}
Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245
oscarthecat
  • 1,811
  • 1
  • 18
  • 28
  • Just to clarify, you need to put `onActivityResult` on the Activity that you are launching React Native from and call `mReactInstanceManager.onActivityResult( ... )` (or whatever you called it). Or, you can extend that Activity from `ReactActivity`. – Joshua Pinter Jul 03 '18 at 05:31
1

To make the solution complete:

in your MainActivity (or in the Activity, where RN is initialized and mReactInstanceManager is used if it is a part of a native app):

...
private ReactInstanceManager mReactInstanceManager;
...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

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

in your Module:

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());
    }
}
f4z3k4s
  • 966
  • 7
  • 13
1

If any one using kotlin with react-native module with Promise, plesae refer below code,

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)
  }
}

Main part is need to add event Listener,

init {
    reContext?.addActivityEventListener(mActivityEventListener)
  }
Somnath Kadam
  • 6,051
  • 6
  • 21
  • 37