5

I am trying to create android native module for react native and I am using Activity Results API to start another activity. But registerForActivityResult is not found, even I have these two dependencies listed in the Gradle:

implementation "androidx.activity:activity:1.2.0"
implementation "androidx.fragment:fragment:1.3.0"

This is what I am trying to achieve:

ActivityResultLauncher<String> mGetContent = registerForActivityResult(new GetContent(),
    new ActivityResultCallback<Uri>() {
        @Override
        public void onActivityResult(Uri uri) {
            // Handle the returned Uri
        }
    }
);
0

2 Answers 2

2

I know I'm a bit late to the party. But I had the same issue, and I thought I should share how I solved this hoping it would help others.

First I created a new interface (in it's own file) to have a contract between the MainActivity and the React Native module:

public interface OnActivityResultImplementation<S, T> {
    S execute(T a);
}

In my MainActivity I have this:

public class MainActivity extends ReactActivity {
protected OnActivityResultImplementation onActivityResultImplementation = null;
protected ActivityResultLauncher<Intent> mStartForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
        result -> {
            onActivityResultImplementation.execute(result);
        });
   ...
}

And then in the React Native Module I set it up the like this:

public class RCTPushProvisioningModule extends ReactContextBaseJavaModule {

@ReactMethod
public void callNativeApiMethod(final Promise promise) {
    MainActivity activity = (MainActivity) this.getReactApplicationContext().getCurrentActivity();
    activity.onActivityResultImplementation = result -> {
        ActivityResult activityResult = (ActivityResult) result;
        switch (activityResult.getResultCode()) {
            case Activity.RESULT_OK:
                promise.resolve(OK);
                break;
            case Activity.RESULT_CANCELED:
                promise.resolve(CANCELED);
                break;
            default:
                promise.reject(ERROR_CODE, "FAILED");
                break;
        }
        return null;
    };

    // Use the ActivityResultLauncher<Intent> from MainActivity to wire the whole thing up.
    fictiveNativeApi.callMethodThatRequiresActivityResultLauncher(activity.mStartForResult);
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

How to do this for the new architecture using TurboModules. Can you help here stackoverflow.com/questions/75576907/…
0

Here's my attempt for migrating a known module called react-native-image-picker into using Results API.

As you can see we register onHostResume

    @Override
    public void onHostResume() {
        Activity currentActivity = getCurrentActivity();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
                currentActivity instanceof FragmentActivity fragmentActivity) {
            initializeLaunchers(fragmentActivity);
        }
    }

then

private void initializeLaunchers(FragmentActivity activity) {
        if (activity == null) return;

        // Only register if we haven't already for this activity
        if (currentFragmentActivity != activity || cameraLauncher == null) {
            try {
                // Check if we can register (activity must be at least CREATED)
                if (activity.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.CREATED)) {
                    currentFragmentActivity = activity;

                    cameraLauncher = activity.registerForActivityResult(
                            new ActivityResultContracts.StartActivityForResult(),
                            result -> {
                                int requestCode = REQUEST_LAUNCH_IMAGE_CAPTURE;
                                if (this.options != null && this.options.mediaType.equals(mediaTypeVideo)) {
                                    requestCode = REQUEST_LAUNCH_VIDEO_CAPTURE;
                                }
                                onActivityResult(activity, requestCode, result.getResultCode(), result.getData());
                            }
                    );

                    libraryLauncher = activity.registerForActivityResult(
                            new ActivityResultContracts.StartActivityForResult(),
                            result -> {
                                onActivityResult(activity, REQUEST_LAUNCH_LIBRARY, result.getResultCode(), result.getData());
                            }
                    );

                }
            } catch (IllegalStateException e) {
                // Failed to register - activity in wrong state
            }
        }
    }

and finally we just use like so:

cameraLauncher.launch(cameraIntent);

Check the full code here.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.