Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native onActivityResult not work

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

}
like image 724
shawnXiao Avatar asked Mar 31 '16 13:03

shawnXiao


3 Answers

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

}
like image 165
oscarthecat Avatar answered Nov 07 '22 18:11

oscarthecat


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());
    }
}
like image 23
f4z3k4s Avatar answered Nov 07 '22 17:11

f4z3k4s


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)
  }
like image 1
Somnath Kadam Avatar answered Nov 07 '22 16:11

Somnath Kadam