0
votes

I have used below plugin cordova-plugin-sms

Methods :-

watchSMS() {   
  if(window.SMS) window.SMS.startWatch(function(){  
    console.log('Succeed to start watching SMS');   
    document.addEventListener('onSMSArrive', this.smsArived);
  }, function(){   
    console.log('failed to start watching SMS');  
  });  
}

stopWatchSMS() {   
  if(window.SMS) window.SMS.stopWatch(function(){ 
     console.log('Succeed to stop watching SMS'); 
  }, function(){  
     console.log('failed to stop watching SMS');    
  }); 
}

smsArived = (result: any) => { 
    console.log("SMS DATA 2" + smsData);
    this.stopWatchSMS();   
}

using the above code for reading otp from SMS for ionic 3 getting below error can any one help

file:///android_asset/www/cordova.js: Line 312 : Error in Success callbackId: SMS329868448 : TypeError: Cannot read property 'smsArived' of null I/chromium: [INFO:CONSOLE(312)] "Error in Success callbackId: SMS329868448 : TypeError: Cannot read property 'smsArived' of null",, source: file:///android_asset/www/cordova.js

1

1 Answers

2
votes

You are trying to implement this using pure javascript which leads to unwanted effects when working with Ionic/Angular/Typescript. this in your success callback function of startWatch does not reference the class scope so the smsArived method is not found.

So how to do this the Angular/Ionic way?

First of all do not access global objects directly (window, document) this is bad for performance and maintainability. To use a cordova plugin which is not included in ionic-natvie you have to tell typescript that the plugin handle (SMS) exists:

declare var SMS; // put this at the same level as your imports

Then you have to modify your watchSMS function as follows:

watchSMS() {   
  SMS.startWatch(
    success => {

    },
    error => {

    }
  );
}

By using arrow functions for your callbacks this has the correct scope. So now we need to work around your direct call to document.addEventListener: In Angular4 this is done by injecting the Renderer2 class:

import { Renderer2 } from '@angular/core'; // the import
constructor(private renderer: Renderer2) {} // inject it in your constructor

Now you can add the event listener in the success callback and call your smsArived method with the events data when an event is captured:

let removeSmsListener = this.renderer.listen('document', 'onSMSArrive', (event) => {
   this.smsArived(event);
});

Notice that again you have to use an arrow function to keep the context of this. To clean up behind you, you can call removeSmsListener() because the listen method of the renderer returns a function.

It should be easy now to apply these changes to the other functions.