React Native Module - Unable to Retrieve Phone Number

37 views Asked by At

I have implemented a React Native module (PhoneNumberHintModule) to retrieve phone numbers using the Smart Lock for Passwords API. The native module appears to be correctly implemented, and I have added the necessary event listener in my React Native code. However, I am facing an issue where the phone number is not being retrieved successfully.

Here is my PhoneNumberHintModule native module code:

public class PhoneNumberHintModule extends ReactContextBaseJavaModule {

    private static ReactApplicationContext reactContext;
    private static final int CREDENTIAL_PICKER_REQUEST = 1;
    private static Promise mPromise;
    private static final String EVENT_PHONE_NUMBER_SELECTED = "phoneNumberSelected";

    private final BaseActivityEventListener activityEventListener = new BaseActivityEventListener() {
        @Override
        public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
            PhoneNumberHintModule.this.onActivityResult(requestCode, resultCode, data);
        }
    };

    public PhoneNumberHintModule(ReactApplicationContext context) {
        super(context);
        reactContext = context;
        if (reactContext != null) {
            reactContext.addActivityEventListener(activityEventListener);
        }
    }

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

    @ReactMethod
    public void getPhoneNumberHint(final Promise promise) {
        mPromise = promise;
        final Activity currentActivity = getCurrentActivity();

        if (currentActivity == null) {
            promise.reject("ACTIVITY_NOT_AVAILABLE", "Activity is not available");
            return;
        }

        Context context = getReactApplicationContext();
        HintRequest hintRequest = new HintRequest.Builder()
                .setPhoneNumberIdentifierSupported(true)
                .build();

        IntentSender intent = Credentials.getClient(context).getHintPickerIntent(hintRequest).getIntentSender();

        try {
            currentActivity.startIntentSenderForResult(
                    intent,
                    CREDENTIAL_PICKER_REQUEST,
                    null,
                    0,
                    0,
                    0,
                    new Bundle()
            );
        } catch (IntentSender.SendIntentException e) {
            e.printStackTrace();
            sendErrorToReactNative("SEND_INTENT_ERROR", e.getMessage());
        }
    }

    private void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == CREDENTIAL_PICKER_REQUEST) {
            if (resultCode == Activity.RESULT_OK) {
                handleCredentialResult(data);
            } else {
                sendErrorToReactNative("RESULT_NOT_OK", "Result code is not OK");
            }
        }
    }

    private void handleCredentialResult(Intent data) {
        if (data != null) {
            Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY);
            if (credential != null) {
                String phoneNumber = credential.getId();
                if (phoneNumber != null) {
                    emitPhoneNumberSelectedEvent(phoneNumber);
                    if (mPromise != null) {
                        mPromise.resolve(phoneNumber);
                    }
                } else {
                    sendErrorToReactNative("PHONE_NUMBER_NULL", "Phone number is null");
                }
            } else {
                sendErrorToReactNative("CREDENTIAL_NULL", "Credential is null");
            }
        } else {
            sendErrorToReactNative("DATA_NULL", "Intent data is null");
        }
    }

    private void emitPhoneNumberSelectedEvent(String phoneNumber) {
        if (reactContext != null) {
            reactContext
                    .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                    .emit(EVENT_PHONE_NUMBER_SELECTED, phoneNumber);
        }
    }

    private void sendErrorToReactNative(String code, String message) {
        if (mPromise != null) {
            mPromise.reject(code, message);
        }
    }
}

And here is my React Native code:

useEffect(() => {
    const subscription = phoneNumberHintModuleEventEmitter.addListener(
      'phoneNumberSelected',
      phoneNumber => {
        console.log('Received phone number:', phoneNumber);
      },
    );

    return () => {
      subscription.remove();
    };
  }, []);

  const handleOpenHint = async () => {
    try {
      const phoneNumber = await PhoneNumberHintModule.getPhoneNumberHint();
      console.log('Selected phone number:', phoneNumber);
    } catch (error) {
      console.error('Error fetching phone number hint:', error);
    }
  };

I have added the event listener in my React Native code to listen for the 'phoneNumberSelected' event, but the callback is not being triggered.

I suspect the issue might be related to the native module or the way I am handling the event in React Native. Can someone please review my code and provide insights into why the phone number might not be retrieved successfully?

Thank you in advance for your assistance!

0

There are 0 answers