How to automatically read SMS in Ionic 5 apps
In this post, we will learn how to read SMS in an Ionic app automatically. Reading SMS is a popular feature found in the majority of popular apps today. Mostly, this is used for automatic approval of OTP in authentication or online payment processes.
Traditionally SMS were read by SMS after asking for?READ_SMS?permission, but that has changed since the introduction of Retriever API from Google. More on that in further sections (Step 2).
What is Ionic?5?
You probably already know about Ionic, but I’m putting it here just for the sake of beginners.?Ionic?is a complete open-source SDK for hybrid mobile app development. Ionic provides tools and services for developing hybrid mobile apps using Web technologies like CSS, HTML5, and Sass.
So, in other words — If you create Native apps in Android — you code in Java. If you create Native apps in iOS — you code in Obj-C or Swift. Both of these are powerful but complex languages. With Ionic and Cordova/Capacitor you can write a single piece of code for your app that can run on both iOS and Android (and windows!), that too with the simplicity of HTML, CSS, and JS.
Why receive SMS automatically?
Apps can communicate in a number of ways. Most apps receive information from servers using push notifications. Push notification information can be easily processed by the apps automatically. (You can read my detailed blog on?how to include push notifications in an Ionic 5 app)
But on occasions, you get information via a third party service which can be delivered effectively only using SMS. For example, when making a credit card payment, you receive an SMS containing the OTP (one-time password) for the transaction. Modern apps automatically read the SMS and capture the OTP, and complete the transaction process. This brings in a huge UX boost, where the user doesn’t have to interact with the app for a long time to make the payment.
Another example is the?Login / authentication process. Apps which are mobile number centric, mostly allow users to register with their phone number. To validate if the user has the phone number he/she claims the app server sends an OTP, and the app can verify the OTP automatically to register the user, something like this?:
Structure
We are going to build a small Ionic 5 app with the SMS reading feature. Following are the steps we’ll take
Let’s dive right in
Step 1 — Create a sample Ionic 5?app
I have covered this topic in detail in?this blog.
In short, the steps you need to take here are
You can create a?blank?starter for the sake of this tutorial. On running?ionic start appName blank?, node modules will be installed. Once the installation is done, run your app on browser using
$ ionic serve
Here is how the app will look like.
The UI is pretty simple for a registration screen. Here’s the flow
I leave the UI (HTML + CSS) on you, you can make it anyway you like.
Step 2 — App Hash and Retriever API
Before setting up the plugin, let’s learn a little about App Hash and SMS retriever API.
Early android apps used a?READ_SMS?permission which allowed the app to read ALL SMS from your device. In 2020, Google released the SMS Retriever API that allows you to fetch the SMS without any permission from the app. That means you don’t have to give the app “Read SMS” permission, thereby avoiding any privacy issues. In fact,?READ_SMS?permission can now get your app rejected from app store, as this comes under?Dangerous permission?category. Hence the old plugins which used?READ_SMS?permission are now effectively deprecated.
The?SMS Retriever API helps in reading SMS without permission. It reads SMS based on?App Hash — An 11 digit unique hash string used for auto verifying SMS. Google Play Services utilizes the hash string to figure out which messages to send to your application.?
This unique hash can be different for different environments. For example, if an app is signed by a debug keystore for development the hash will be different from production build or if the app is signed by Google Play.
Reading SMS with App?Hash
To read SMS using retriever API, we should know the SMS syntax which the API can read correctly. A valid verification message might look like the following:
Your OTP is: 672838 /kkeid8sksd3
The last 11 digits alphanumeric character is the unique hash generated for the app. That 11 digits unique character is the main key which google play services reads for the SMS using the SMS Retriever API. So basically, you’ll need the App Hash on the server side, to be sent along with the SMS.
Generating App?Hash
Google has given exact instruction for generating Key hash on?this link. I will discuss this in short here.
For debug or production keystore, you can just use this command
$ keytool -exportcert -alias <<KEYSTORE_ALIAS>> -keystore <<KEYSTORE_PATH>>| xxd -p | tr -d "[:space:]" | echo -n <<APP_PACKAGE_NAME>>`cat` | sha256sum | tr -d "[:space:]-" | xxd -r -p | base64 | cut -c1-11
// output - uv+otVdzZzc <-- App Hash
Where, app_package_name is the bundle_ID, which looks like?com.enappd.readsms?.?If you use app signing by Google Play, follow?this link?for additional information.
领英推荐
Note — Do not make your app hash public
Now, we are ready to setup the plugins and implement SMS read feature in our app.
Step 3— Implement the Cordova plugin to read?SMS
For reading SMS via the Ionic 5 app, there are few plugins available.
We will implement the Ionic recommended plugin, but other plugins can work in your app as well.
To install the plugin, run
$ ionic cordova plugin add cordova-plugin-sms-retriever-manager
$ npm install @ionic-native/sms-retriever
Import the plugin in?app.module.ts?and add to providers array
import { SmsRetriever } from '@ionic-native/sms-retriever/ngx';
@NgModule({
... ,
providers: [
SmsRetriever,
{ provide: RouteReuseStrategy,
useClass: IonicRouteStrategy
}
],
...
})
export class AppModule { }
Page flow
As the app starts, it redirects to?Login?page. Once the OTP is approved, you redirect to?Home?page. The?app-routing.module.ts?routes?object looks like below
const routes: Routes = [
{
path: 'home',
loadChildren:
() => import('./home/home.module').then(m => m.HomePageModule)
},
{
path: 'login',
loadChildren:
() => import('./login/login.module').then(m => m.LoginPageModule)
},
{
path: '',
redirectTo: 'login',
pathMatch: 'full'
}
];
OTP Flow
Import the plugin in your?login.page.ts?using
import { SmsRetriever } from '@ionic-native/sms-retriever';
Now, there are two methods available with the plugin
this.smsRetriever.getAppHash()
.then((res: any) => console.log(res))
.catch((error: any) => console.error(error))
This function gives the same App Hash as we generated in previous section.?
this.smsRetriever.startWatching()
.then((res: any) => console.log(res))
.catch((error: any) => console.error(error));
Overall, our?login.page.ts?looks like this
import { Component } from '@angular/core'
import { ToastController } from '@ionic/angular';
import { SmsRetriever } from '@ionic-native/sms-retriever/ngx';
import { Router } from '@angular/router';
@Component({
selector: 'app-login',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss'],
})
export class LoginPage {
OTP: string = '';
showOTPInput: boolean = false;
OTPmessage: string = 'An OTP is sent to your number. You should receive it in 15 s'
constructor
(
private router: Router,
private toastCtrl: ToastController,
private smsRetriever: SmsRetriever
) {
this.smsRetriever.getAppHash()
.then((res: any) => console.log(res))
.catch((error: any) => console.error(error));
}
async presentToast(message, position, duration) {
const toast = await this.toastCtrl.create({
message: message,
position: position,
duration: duration
});
toast.present();
}
next() {
this.showOTPInput = true;
this.start();
}
start() {
this.smsRetriever.startWatching()
.then((res: any) => {
console.log(res);
this.processSMS(res);
})
.catch((error: any) => console.error(error));
}
processSMS(data) {
// Design your SMS with App hash so the retriever API can read the SMS without READ_SMS permission
// Attach the App hash to SMS from your server, Last 11 characters should be the App Hash
// After that, format the SMS so you can recognize the OTP correctly
// Here I put the first 6 character as OTP
const message = data.Message;
if (message != -1) {
this.OTP = message.slice(0, 6);
console.log(this.OTP);
this.OTPmessage = 'OTP received. Proceed to register';
this.presentToast(
'SMS received with correct app hash',
'bottom',
1500
);
}
}
register() {
if (this.OTP != '') {
this.presentToast(
'You are successfully registered',
'bottom',
1500
);
this.router.navigate(['/home'])
}
else {
this.presentToast('Your OTP is not valid', 'bottom', 1500);
}
}
};
Step 4— Build an app on android?device
If you have carried out the above steps correctly, the Android build should be a breeze. Run the following command to create an Android platform
$ ionic cordova platform add android
Once platform is added, run the app on device (Make sure you have a device attached to the system). You’ll need an actual SIM connection to receive SMS
$ ionic cordova run android
Once your app is up and running on the device, we’ll send SMS from another device simulating a server behavior, or use any other application to send SMS to your phone.
Step 5— Test automatic SMS reading to approve a sample registration
In case you missed it in Step 1, here are the steps again.
Conclusion
In this blog, you learned how to implement automatic SMS reading in an Ionic 5 app using SMS retrieve API. This API is safe in usage as it only reads the SMS meant for your particular app, using the App Hash.?
Automatic SMS reading is useful in modules like automatic OTP reading for authentication or automatic OTP reading for online transactions.
That’s all for this blog. This was quite a read, but a very interesting feature for your next Pro app.
Stay tuned for more Ionic blogs?!
Software Engineer at Wafi Solutions
1 个月start() { this.smsRetriever.startWatching() .then((res: any) => { console.log(res); this.processSMS(res); }) .catch((error: any) => console.error(error)); } In production, I got timeout error after 5 mins,