Capture OTP while Sign in/Sign up

How to capture otp from android mobile during registration/login in a app

1 Like

Hi @nazneen,

Check out this post and video for a walkthrough on how to capture One Time Password (OTP):

@Chris_Trevarthen Could you please help me with the same OTP reading when I try to sign in using android mobile app ?

Hi @janani0515,

I haven’t worked with OTP testing, but if you are able to share screenshots or videos of the process, I might be able to help figure out how to inspect some elements.

– Chris

Hi @Chris_Trevarthen,

As soon as I enter my login credentials, the OTP will get displayed as a notification. It will also be in my ‘Text Messages’ folder.
I need to read this otp from either notification or sms folder and enter it to login my application. There are several ways to do it for a web application but for a mobile app there are no procedures.

Please help me.
Refer attached images.

Hi @janani0515,

Thanks for the screenshot, that helps me understand a bit better what you’re trying to do. I don’t think you’ll be able to access the notification popup message with Katalon Studio/Appium, but I think you might be able to switch to the Notifications application and read the latest notification to get the OTP code.

  1. Use Katalon Studio to Spy Mobile using an apk file that you have on your machine
  2. Trigger the OTP notification on your emulator or device
  3. In the emulator or device, switch to the Android Notifications app
  4. Capture the object for the corresponding notification message in the Notifications app - this is probably the latest one - name this something like “First Notification Item”
  5. Capture the text object for the notification that contains the OTP - name this something like “OTP Text”
  6. Save the text object in the Test Object repository
  7. Stop the spying process
  8. Open your test case
  9. Switch to the “Script” view of the test case
  10. After the spot in your test case that you trigger the OTP request and the notification appears, add a line for:
    Mobile.openNotifications()
    This should open the Android Notifications app programmatically
  11. Add code to tap the latest notification object, which should be something like:
    TestObject notification = findTestObject('Object Repository/First Notification Item')
    Mobile.tap(notification, 10)
    
    Where “First Notification Item” is what you named the captured first notification element when you were spying
  12. Add code to get the text of the OTP:
    TestObject otp = findTextObject('Object Repository/OTP Text')
    String otpText = Mobile.getText(otp, 10)
    
  13. You can then switch back to the main app using
    Mobile.closeNotifications()
  14. Use the OTP text you captured above and set it in to the password field in your app using Mobile.sendKeys() or Mobile.setText().

It’s a bit of a round-about process, but I think the concept should work for what you want to do.

Hope this helps,

Chris

1 Like

@Chris_Trevarthen
Thanks for the detailed explanation. But still I get struck in between the process.Whenever I start recording my actions, the notification pops up, but I am unable to capture the notification screen.The whole layout of my screen gets captured and I cannot capture the OTP notification section alone.

Kindly help me out with how can I switch to Android notifications app as the back button will not help moving back to my mobile screen.

@Chris_Trevarthen
Hi Chris! Any updates on the above issue?

Thanks in Advance.

Hi @janani0515,

I’m not sure if you’ll be able to capture the notification as it pops up, but if you add the line Mobile.openNotifications() to your test, it should pull down the Notifications drawer.

From there, you’ll need to find the notification object that you want to grab the OTP from (this is probably the latest/top notification). To do this, I manually created a test object in the Object Repository with the name “notification”. It has an xpath value of:

//*[@class = 'android.widget.FrameLayout' and @resource-id = 'android:id/status_bar_latest_event_content'][1]/*[@class='android.widget.LinearLayout' and @resource-id='android:id/notification_main_column']/*[@class='android.widget.TextView' and @resource-id='android:id/text']

That xpath gets the first notification object, then the LinearLayout within that, and finally the TextView within that.

In my test, I can then find that Test Object and inspect its contents.

All put together, it’s like this:

// Do the work to trigger a OTP

Mobile.openNotifications()
TestObject notification = findTestObject('Object Repository/notification')
String otp = Mobile.getText(notification, 10)
Mobile.closeNotifications()

// Use the otp String in the appropriate place

Hope this helps,

Chris

2 Likes

@Chris_Trevarthen
Hi Chris,Thanks for the detailed insight.I did the above by creating an object with Xpath value, but when Katalon executes the following step,

String otp = Mobile.getText(notification, 10)

it keeps loading and would not give me any status so I am unable to find out what is the error.

Also you have used resource id value in the xpath:
[@class = ‘android.widget.FrameLayout’ and @resource-id = ‘android:id/status_bar_latest_event_content’][1]/[@class=‘android.widget.LinearLayout’ and @resource-id=‘android:id/notification_main_column’]/*[@class=‘android.widget.TextView’ and @resource-id=‘android:id/text’]

In my object property, only the class Textview has resource id whereas the other two classes FrameLayout and LinearLayout does not have any resource id.

Is resource id must when creating xpath or can any other alternative id be added?

Could you please share your thoughts?

Hi @janani0515,

The resource-id isn’t strictly necessary, but it helps to narrow down exactly which element that Appium should look for. Since there are so many LinearLayout or TextView objects on a given screen, it’s unlikely that just putting the classes will return the element you want.

To try to find a good xpath for you to use, let’s go through some steps/questions:

  1. Are you able to use Mobile.showNotifications() in your test to open the Android Notifications widget?
  2. Can you start the Spy Mobile feature of Katalon with your app and then slide open the Android Notifications widget manually (not the notification as it comes in, but the list of all notifications you’ve received on the device)? If so, can you send a screenshot of what the notifications look like? I’d imagine it looks something like this:

  1. Using Spy Mobile, can you find the OTP text in the Android Notification widget and click the checkbox next to the TextView element (I assume it’s a TextView). This should be similar to the screenshot I took above of some notification text.
  2. Once the checkbox is selected, you should see all of the properties of that text element. Can you copy and share with me the full xpath value of the element?

Thanks,

Chris

@Chris_Trevarthen

Thank alot for the explanation. I have attached screenshot for your reference. The following are the captured elements.

1.Frame Layout

2.Linear Layout

3.Text View

The Xpaths of the captured elements are as follows:

1.Frame Layout:
//hierarchy/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.ScrollView[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]

2.Linear Layout:
//hierarchy/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.ScrollView[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]

3.TextView:
//hierarchy/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.ScrollView[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[2]/android.widget.TextView[1]

Manual Object Creation:
I have manually created an object and set xpath value as per the guidance.

My code snippet:

When I run my test case, the line , TestObject notification = findTestObject(‘OTP/Capture’) , does not get executed and the line gets skipped.

Kindly guide me on what goes wrong!

Thanks in advance.

1 Like

@Chris_Trevarthen
I have attached the Log Viewer of the executed test case. The newly created object does not get identified to capture otp.

Kindly help out!

Thanks in advance.
N.Aishwarya Janani

Hi @janani0515,

I think we can change your xpath to make it look at the text itself instead of trying to find by the full path. So if you change the xpath for your OTP/Capture element to:

//*[@class = 'android.widget.TextView' and contains(@text, 'gin OTP')]

Where gin OTP is that part of the notification that you can see in your screenshots.

Can you try that and see if you are able to get the text out of the notification?

– Chris

1 Like

@Chris_Trevarthen

Thank You. I tried but still no luck. One doubt that arises is every time my otp gets generated , the number of the OTP changes. If I do not mention that number, will the Katalon identify it?

Sample xpath of the otp that was captured earlier,

//*[@class = ‘android.widget.TextView’ and @instance = ‘1’ and (text() = ‘…gin OTP : 818099’ or . = '…gin OTP : 818099 ') and @resource-id = ‘android:id/text’]

Xpath of my manually created object while running test case as I may not know what otp number would come when I login the application :
//*[@class = ‘android.widget.TextView’ and (text() = '…gin OTP : ') and @resource-id = ‘android:id/text’]

Output:

Hi @janani0515

Since your OTP will change, I recommend trying the contains() function of path, so based on your manually created object, it could be:

//*[@class = ‘android.widget.TextView’ and contains(@text, '…gin OTP : ') and @resource-id = ‘android:id/text’]

Once you get the text of the object, you can use some string functions to pull out the OTP:

String notificationText = Mobile.getText(notification, 10)
String otp = notificationText.reverse().take(6).reverse()

Hope this helps,

Chris

Hi @Chris_Trevarthen,

Finally my manually created object has been detected successfully but when I try to set the text to the required field, it throws error saying ‘object is null’.

Hi,
You miss the folder name
findTestObject('Login/android.widget.Button1 - Sign In')

Hi @HeleneB
Thanks for that! Even then I am unable to set text since it keeps loading

Did you try with a timeout ?
Mobile.setText(findTestObject('Login/android.widget.Button1 - Sign In'), code, 10)