{"id":1014,"date":"2020-02-06T16:16:00","date_gmt":"2020-02-06T16:16:00","guid":{"rendered":"https:\/\/blog.infotheme.net\/?p=1014"},"modified":"2020-02-06T16:16:29","modified_gmt":"2020-02-06T16:16:29","slug":"integrate-otp-in-android-php","status":"publish","type":"post","link":"https:\/\/infotheme.net\/blog\/integrate-otp-in-android-php\/","title":{"rendered":"How to Integrate OTP in Android &#038; PHP &#8211; Auto SMS Verification"},"content":{"rendered":"\n<p>Integrating OTP is not harder as it was before. Now lot&#8217;s of tools available around web or app. Android Developers recently introduced <strong><a href=\"https:\/\/developers.google.com\/identity\/sms-retriever\/verify\" rel=\"nofollow noopener\" target=\"_blank\">SMS Retriever or Verification API<\/a><\/strong>, it was introduced to make more secure , because previously some important receiver did this job in android, but there was a problem, with that permission &#8220;SMS READ, SMS RETRIVE&#8221; some fraud apps were receiving some confidential data of users. So without wasting time on the entire story, we can proceed with the new method of Android OTP Verification:<\/p>\n\n\n\n<p><strong>So First of all you need these things to proceed with this process:<\/strong><\/p>\n\n\n\n<ol><li>Android Studio (<a href=\"https:\/\/developer.android.com\/studio\" rel=\"nofollow noopener\" target=\"_blank\">Latest Version<\/a>)<\/li><li>Xampp (<a href=\"https:\/\/www.apachefriends.org\/download.html\" rel=\"nofollow noopener\" target=\"_blank\">A Tool Which Allows to create Apache server environment<\/a>)<\/li><li>VSCode (<a href=\"https:\/\/code.visualstudio.com\/download\" rel=\"nofollow noopener\" target=\"_blank\">A Tool to create php code<\/a>)<\/li><li>SMS Service (<a href=\"http:\/\/www.twilio.com\/referral\/AYMSB6\" rel=\"nofollow noopener\" target=\"_blank\">Twillio Is Best SMS Service Ever<\/a>)<\/li><li>Firebase for Authentication (<a href=\"https:\/\/firebase.google.com\/\" rel=\"nofollow noopener\" target=\"_blank\">You can Use Firebase Authentication, Instead SMS Service<\/a>)<\/li><\/ol>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" width=\"1024\" height=\"536\" src=\"https:\/\/blog.infotheme.net\/wp-content\/uploads\/2020\/02\/OTP-Integration-with-Android-and-PHP-1024x536.png\" alt=\"OTP Integration with Android and PHP\" class=\"wp-image-1015\" srcset=\"https:\/\/infotheme.net\/blog\/wp-content\/uploads\/2020\/02\/OTP-Integration-with-Android-and-PHP-1024x536.png 1024w, https:\/\/infotheme.net\/blog\/wp-content\/uploads\/2020\/02\/OTP-Integration-with-Android-and-PHP-300x157.png 300w, https:\/\/infotheme.net\/blog\/wp-content\/uploads\/2020\/02\/OTP-Integration-with-Android-and-PHP-768x402.png 768w, https:\/\/infotheme.net\/blog\/wp-content\/uploads\/2020\/02\/OTP-Integration-with-Android-and-PHP.png 1200w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>OTP Integration with Android and PHP<\/figcaption><\/figure>\n\n\n\n<p><strong>Let&#8217;s have some understanding on this entire process of verification:<\/strong><\/p>\n\n\n\n<p>As I previously mentioned the cause why google changed the policy for READ_SMS permission. So in this entire process your app request OTP from your PHP code and then send data to SMS Service where SMS service triggers an SMS to user&#8217;s mobile. Once the SMS comes, SMS Retriever API Tells to app about that Text Message. Which makes it easier to detect otp and after receiving it APP call a Verification Request to your server That&#8217;s It.<\/p>\n\n\n\n<p><strong>So let&#8217;s start with steps to implement the entire Process:<\/strong><\/p>\n\n\n\n<p><strong>Step 1: <\/strong>You need to add SMS Retriever API in your build.grade file of app under dependencies{&#8230;.} block<\/p>\n\n\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n  \/\/Google&#039;s Android SMS Retriver API\n  implementation &#039;com.google.android.gms:play-services-auth:17.0.0&#039;\n  implementation &#039;com.google.android.gms:play-services-auth-api-phone:17.0.0&#039;\n  \/\/Add Right Before This\n  testImplementation &#039;junit:junit:4.12&#039;\n  androidTestImplementation &#039;com.android.support.test:runner:1.0.2&#039;\n  androidTestImplementation &#039;com.android.support.test.espresso:espresso-core:3.0.2&#039;\n<\/pre>\n\n\n<p><strong>Step 2:<\/strong> If you want to get users phone number, which is connected with it&#8217;s Google Play Account. You can easily grab it with  <strong>GoogleApiClient Builder<\/strong>. Let&#8217;s focus on code, but please keep in mind you need to do it onCreate(){} method. So that once user with choose you can easily put the mobile number into EditText of Phone Number or Phone Number Input. Initialize Api Client Builder<\/p>\n\n\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n\/\/ For Activity \nmGoogleApiClient = new GoogleApiClient.Builder(this)\n        .addConnectionCallbacks(this)\n        .enableAutoManage(this, this)\n        .addApi(Auth.CREDENTIALS_API)\n        .build();\n\/\/For Fragment\nmGoogleApiClient = new GoogleApiClient.Builder(getActivity())\n        .addConnectionCallbacks(this)\n        .enableAutoManage(this, this)\n        .addApi(Auth.CREDENTIALS_API)\n        .build(); \/\/ Replace this with getActivity() if needed it&#039;s just context here\n<\/pre>\n\n\n<p><strong>Step 3:<\/strong> Let&#8217;s call this hint request to get the number.<\/p>\n\n\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\npublic void getPhoneNumberHint() {\n    HintRequest hintRequest =\n        new HintRequest.Builder()\n            .setPhoneNumberIdentifierSupported(true)\n            .build();\n    PendingIntent mIntent = Auth.CredentialsApi.getHintPickerIntent(mGoogleApiClient, hintRequest);\n    try {\n      startIntentSenderForResult(mIntent.getIntentSender(), RESOLVE_HINT, null, 0, 0, 0);\n    } catch (IntentSender.SendIntentException e) {\n      e.printStackTrace();\n    }\n  }\n<\/pre>\n\n\n<p><strong>Step 4:<\/strong> Time to get the Hint Request&#8217;s Result from Activity (In Simple words time to get the result which is user&#8217;s mobile number)<\/p>\n\n\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n@Override\n  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {\n    super.onActivityResult(requestCode, resultCode, data);\n    \/\/Result if we want hint number\n    \/\/ Define it as an constant such as =&gt; private int RESOLVE_HINT = 101\n    if (requestCode == RESOLVE_HINT) {\n      if (resultCode == Activity.RESULT_OK) {\n        Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY);\n        MobileNumberInput.setText(credential.getId());\n      }\n    }\n<\/pre>\n\n\n<p><strong>Step 5: <\/strong>Start SMS Retriever \/ Listener Method, Where Retriever API will start listening for SMS and when it will receive SMS, will send to Broadcast receiver.<\/p>\n\n\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\npublic void StartSMSListener() {\n    SmsRetrieverClient mClient = SmsRetriever.getClient(this);\n    Task&lt;Void&gt; mTask = mClient.startSmsRetriever();\n    mTask.addOnSuccessListener(new OnSuccessListener&lt;Void&gt;() {\n      @Override public void onSuccess(Void aVoid) {\n        layoutInput.setVisibility(View.GONE);\n        layoutVerify.setVisibility(View.VISIBLE);\n        Toast.makeText(MainActivity.this, &quot;SMS Retriever starts&quot;, Toast.LENGTH_LONG).show();\n      }\n    });\n    mTask.addOnFailureListener(new OnFailureListener() {\n      @Override public void onFailure(@NonNull Exception e) {\n        Toast.makeText(MainActivity.this, &quot;Unable to Find!&quot;, Toast.LENGTH_LONG).show();\n      }\n    });\n  }\n\n<\/pre>\n\n\n<p><strong>Step 6: <\/strong>Now it&#8217;s time for a Broadcast receiver to receive SMS and send the result to Activity. Create a Java Class &#8220;SmsBroadcastReciever.java&#8221; under BroadcastReciever Directory or Package in your project.<\/p>\n\n\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\npackage com.infotheme.tutorial.smsverification.BroadcastReciever;\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.util.Log;\nimport com.google.android.gms.auth.api.phone.SmsRetriever;\nimport com.google.android.gms.common.api.CommonStatusCodes;\nimport com.google.android.gms.common.api.Status;\nimport com.infotheme.tutorial.smsverification.Interfaces.OtpReceivedInterface;\n\/**\n * Created on : Feb 06, 2020\n * Author     : InfoTheme Inc.\n *\/\npublic class SmsBroadcastReciever extends BroadcastReceiver {\n  private static final String TAG = &quot;SmsBroadcastReciever&quot;;\n  private static final String OTP_DELIMITER = &quot;#&gt;&quot;;\n  OtpReceivedInterface otpReceiveInterface = null;\n  \/\/ These interfaces will extract the data and status in your activity on request\n  public void setOnOtpListeners(OtpReceivedInterface otpReceiveInterface) {\n    this.otpReceiveInterface = otpReceiveInterface;\n  }\n  @Override public void onReceive(Context context, Intent intent) {\n    Log.d(TAG, &quot;onReceive: &quot;);\n    if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) {\n      Bundle extras = intent.getExtras();\n      Status mStatus = (Status) extras.get(SmsRetriever.EXTRA_STATUS);\n      switch (mStatus.getStatusCode()) {\n        case CommonStatusCodes.SUCCESS:\n          \/\/ Get SMS message contents&#039;\n          String message = (String) extras.get(SmsRetriever.EXTRA_SMS_MESSAGE);\n          Log.d(TAG, &quot;onReceive: failure &quot;+message);\n          if (otpReceiveInterface != null) {\n            String otp = getVerificationCode(message);\n            otpReceiveInterface.onOtpReceived(otp);\n          Log.e(TAG, &quot;OTP received: &quot; + otp);\n          }\n          break;\n        case CommonStatusCodes.TIMEOUT:\n          \/\/ SMS timed out (After 5 minutes)\n          Log.d(TAG, &quot;onReceive: failure&quot;);\n          if (otpReceiveInterface != null) {\n            otpReceiveInterface.onOtpTimeout();\n          }\n          break;\n      }\n    }\n  }\n\n\n   private String getVerificationCode(String message) {\n        String code = null;\n        int index = message.indexOf(OTP_DELIMITER);\n\n        if (index != -1) {\n            int start = index + 2;\n            int length = 4; \/\/OTP Length\n            code = message.substring(start, start + length);\n            return code;\n        }\n\n        return code;\n    }\n}\n<\/pre>\n\n\n<p><strong>Step 7<\/strong>: Now time to Create Otp Listener which we included previous file, Create Directory or package named &#8220;Interfaces&#8221;, create a java class &#8220;OtpReceivedInterface.java&#8221; and put below code:<\/p>\n\n\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\npublic interface OtpReceivedInterface {\n  void onOtpReceived(String otp);\n  void onOtpTimeout();\n}\n<\/pre>\n\n\n<p><strong>Step 8:<\/strong> Now it&#8217;s time to register your <strong>BroadcastReciever<\/strong> to your <strong>AndroidManifest<\/strong>, simply put below code under application block &lt;application &#8230;..> &lt;\/application><\/p>\n\n\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&lt;receiver\n        android:name=&quot;.BroadcastReciever.SmsBroadcastReciever&quot;\n        android:exported=&quot;true&quot;&gt;\n      &lt;intent-filter&gt;\n        &lt;action android:name=&quot;com.google.android.gms.auth.api.phone.SMS_RETRIEVE&quot; \/&gt;\n      &lt;\/intent-filter&gt;\n&lt;\/receiver&gt;\n<\/pre>\n\n\n<p><strong>Step 9: <\/strong>Here is code of Awesome Layout of Your otp_activity.xml<\/p>\n\n\n\n<p><strong>Step 10:<\/strong> Here is code of OTPActivity.java<\/p>\n\n\n\n<p><strong>Step 11: <\/strong> You will be needed Application Hash for verification using Android SMS Retriever Api, use this code but keep in mind debug key and release key will be different. Create A Class &#8221; AppSignatureHelper.java&#8221; Anywhere in your project and add this code.<\/p>\n\n\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\npublic class AppSignatureHelper extends ContextWrapper {\n  private static final String TAG = &quot;AppSignatureHelper&quot;;\n  private static final String HASH_TYPE = &quot;SHA-256&quot;;\n  public static final int NUM_HASHED_BYTES = 9;\n  public static final int NUM_BASE64_CHAR = 11;\n  public AppSignatureHelper(Context context) {\n    super(context);\n  }\n  \/**\n   * Get the app signatures for the your current package\n   *\/\n  public ArrayList&lt;String&gt; getAppSignatures() {\n    ArrayList&lt;String&gt; appCodes = new ArrayList&lt;&gt;();\n    try {\n      \/\/ Get all package signatures for the current package\n      String packageName = getPackageName();\n      PackageManager packageManager = getPackageManager();\n      Signature[] signatures = packageManager.getPackageInfo(packageName,\n          PackageManager.GET_SIGNATURES).signatures;\n      \/\/ For each signature create a compatible hash\n      for (Signature signature : signatures) {\n        String hash = hash(packageName, signature.toCharsString());\n        if (hash != null) {\n          appCodes.add(String.format(&quot;%s&quot;, hash));\n        }\n      }\n    } catch (PackageManager.NameNotFoundException e) {\n      Log.e(TAG, &quot;Unable to find package to obtain hash.&quot;, e);\n    }\n    return appCodes;\n  }\n  private static String hash(String packageName, String signature) {\n    String appInfo = packageName + &quot; &quot; + signature;\n    try {\n      MessageDigest messageDigest = MessageDigest.getInstance(HASH_TYPE);\n      messageDigest.update(appInfo.getBytes(StandardCharsets.UTF_8));\n      byte[] hashSignature = messageDigest.digest();\n      \/\/ truncated into NUM_HASHED_BYTES\n      hashSignature = Arrays.copyOfRange(hashSignature, 0, NUM_HASHED_BYTES);\n      \/\/ encode into Base64\n      String base64Hash = Base64.encodeToString(hashSignature, Base64.NO_PADDING | Base64.NO_WRAP);\n      base64Hash = base64Hash.substring(0, NUM_BASE64_CHAR);\n      Log.d(TAG, String.format(&quot;pkg: %s -- hash: %s&quot;, packageName, base64Hash));\n      return base64Hash;\n    } catch (NoSuchAlgorithmException e) {\n      Log.e(TAG, &quot;hash:NoSuchAlgorithm&quot;, e);\n    }\n    return null;\n  }\n}\n<\/pre>\n\n\n<p>I am still working on this entire post will be back to you in next few days. As soon i will get time, rest please leave some review on this article. I will be back soon with PHP code.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Integrating OTP is not harder as it was before. Now lot&#8217;s of tools available around web or app. Android Developers recently introduced SMS Retriever or [&hellip;] <span class=\"read-more-link\"><a class=\"read-more\" href=\"https:\/\/infotheme.net\/blog\/integrate-otp-in-android-php\/\">Read More<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":1015,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[157,135],"tags":[],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/infotheme.net\/blog\/wp-json\/wp\/v2\/posts\/1014"}],"collection":[{"href":"https:\/\/infotheme.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/infotheme.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/infotheme.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/infotheme.net\/blog\/wp-json\/wp\/v2\/comments?post=1014"}],"version-history":[{"count":1,"href":"https:\/\/infotheme.net\/blog\/wp-json\/wp\/v2\/posts\/1014\/revisions"}],"predecessor-version":[{"id":1016,"href":"https:\/\/infotheme.net\/blog\/wp-json\/wp\/v2\/posts\/1014\/revisions\/1016"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/infotheme.net\/blog\/wp-json\/wp\/v2\/media\/1015"}],"wp:attachment":[{"href":"https:\/\/infotheme.net\/blog\/wp-json\/wp\/v2\/media?parent=1014"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/infotheme.net\/blog\/wp-json\/wp\/v2\/categories?post=1014"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/infotheme.net\/blog\/wp-json\/wp\/v2\/tags?post=1014"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}