Launch Week Day 5: Introducing Reachability for PHP.Learn More
Socket
Book a DemoSign in
Socket

cordova-plugin-sms-retriever

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cordova-plugin-sms-retriever - npm Package Compare versions

Comparing version
2.0.1
to
3.0.0
+72
src/android/AppSignatureHashHelper.java
package com.andreszs.smsretriever;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.util.Base64;
import android.util.Log;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
public class AppSignatureHashHelper extends ContextWrapper {
public static final String LOG_TAG = AppSignatureHashHelper.class.getSimpleName();
private static final String HASH_TYPE = "SHA-256";
private static final int NUM_HASHED_BYTES = 9;
private static final int NUM_BASE64_CHAR = 11;
public AppSignatureHashHelper(Context context) {
super(context);
}
/**
* Get all the app signatures for the current package
* https://github.com/googlesamples/android-credentials/blob/master/sms-verification/android/app/src/main/java/com/google/samples/smartlock/sms_verify/AppSignatureHelper.java
*/
public ArrayList<String> getAppSignatures() {
ArrayList<String> appCodes = new ArrayList<String>();
try {
// Get all package signatures for the current package
String packageName = getPackageName();
PackageManager packageManager = getPackageManager();
Signature[] signatures = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES).signatures;
// For each signature create a compatible hash
for (Signature signature : signatures) {
String hash = hash(packageName, signature.toCharsString());
if (hash != null) {
appCodes.add(String.format("%s", hash));
}
}
} catch (PackageManager.NameNotFoundException e) {
Log.e(LOG_TAG, e.getMessage());
}
return appCodes;
}
private static String hash(String packageName, String signature) {
String appInfo = packageName + " " + signature;
try {
MessageDigest messageDigest = MessageDigest.getInstance(HASH_TYPE);
messageDigest.update(appInfo.getBytes(StandardCharsets.UTF_8));
byte[] hashSignature = messageDigest.digest();
// truncated into NUM_HASHED_BYTES
hashSignature = Arrays.copyOfRange(hashSignature, 0, NUM_HASHED_BYTES);
// encode into Base64
String base64Hash = Base64.encodeToString(hashSignature, Base64.NO_PADDING | Base64.NO_WRAP);
base64Hash = base64Hash.substring(0, NUM_BASE64_CHAR);
return base64Hash;
} catch (NoSuchAlgorithmException e) {
Log.e(LOG_TAG, e.getMessage());
}
return null;
}
}
package com.andreszs.smsretriever;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import com.google.android.gms.auth.api.phone.SmsRetriever;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.common.api.Status;
/**
* BroadcastReceiver to wait for SMS messages. This can be registered either in the AndroidManifest or at runtime. Should filter Intents on SmsRetriever.SMS_RETRIEVED_ACTION.
*/
public class SMSBroadcastReceiver extends BroadcastReceiver {
private OTPReceiveListener otpListener;
public void setOTPListener(OTPReceiveListener otpListener) {
this.otpListener = otpListener;
}
@Override
public void onReceive(Context context, Intent intent) {
if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) {
Bundle extras = intent.getExtras();
Status status = (Status) extras.get(SmsRetriever.EXTRA_STATUS);
if (status == null) {
return;
}
switch (status.getStatusCode()) {
case CommonStatusCodes.SUCCESS:
String message = (String) extras.get(SmsRetriever.EXTRA_SMS_MESSAGE);
if (otpListener != null) {
otpListener.onSmsReceived(message);
}
break;
case CommonStatusCodes.TIMEOUT:
// Waiting for SMS timed out (5 minutes)
if (otpListener != null) {
otpListener.onSmsReceiveTimeOut();
}
break;
case CommonStatusCodes.API_NOT_CONNECTED:
if (otpListener != null) {
otpListener.onSmsReceivedError("API NOT CONNECTED");
}
break;
case CommonStatusCodes.NETWORK_ERROR:
if (otpListener != null) {
otpListener.onSmsReceivedError("NETWORK ERROR");
}
break;
case CommonStatusCodes.ERROR:
if (otpListener != null) {
otpListener.onSmsReceivedError("SOME THING WENT WRONG");
}
break;
}
}
}
/**
*
*/
public interface OTPReceiveListener {
void onSmsReceived(String smsMessage);
void onSmsReceiveTimeOut();
void onSmsReceivedError(String error);
}
}
+1
-1
{
"name": "cordova-plugin-sms-retriever",
"version": "2.0.1",
"version": "3.0.0",
"description": "Cordova plugin to retrieve SMS in Android using the SMS Retriever API.",

@@ -5,0 +5,0 @@ "cordova": {

@@ -6,3 +6,3 @@ <?xml version="1.0" encoding="utf-8"?>

id="cordova-plugin-sms-retriever"
version="2.0.1">
version="3.0.0">

@@ -26,13 +26,23 @@ <name>SMS Retriever</name>

<platform name="android">
<preference name="PLAY_SERVICES_AUTH_VERSION" default="20.5.0"/>
<preference name="PLAY_SERVICES_AUTH_API_PHONE_VERSION" default="18.0.1"/>
<framework src="com.google.android.gms:play-services-auth:$PLAY_SERVICES_AUTH_VERSION"/>
<framework src="com.google.android.gms:play-services-auth-api-phone:$PLAY_SERVICES_AUTH_API_PHONE_VERSION"/>
<preference name="PLAY_SERVICES_VERSION" default="15.0.0"/>
<framework src="com.google.android.gms:play-services-auth:$PLAY_SERVICES_VERSION"/>
<framework src="com.google.android.gms:play-services-auth-api-phone:$PLAY_SERVICES_VERSION"/>
<config-file target="res/xml/config.xml" parent="/*">
<feature name="SMSRetriever">
<param name="android-package" value="com.andreszs.smsretriever.SMSRetriever"/>
<param name="android-package" value="com.andreszs.smsretriever.SMSRetriever"/>
</feature>
</config-file>
<config-file target="AndroidManifest.xml" parent="application">
<receiver android:exported="true"
android:name="com.andreszs.smsretriever.SMSBroadcastReceiver"
android:permission="com.google.android.gms.auth.api.phone.permission.SEND">
<intent-filter>
<action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED" />
</intent-filter>
</receiver>
</config-file>
<config-file target="AndroidManifest.xml" parent="/*">

@@ -43,4 +53,6 @@ <uses-feature android:name="android.hardware.telephony" android:required="false" />

<source-file src="src/android/SMSRetriever.java" target-dir="src/com/andreszs/smsretriever" />
<source-file src="src/android/SMSBroadcastReceiver.java" target-dir="src/com/andreszs/smsretriever" />
<source-file src="src/android/AppSignatureHashHelper.java" target-dir="src/com/andreszs/smsretriever" />
</platform>
</plugin>

@@ -1,2 +0,2 @@

![License](https://img.shields.io/badge/license-MIT-orange.svg) ![Platform](https://img.shields.io/badge/platform-android-green.svg) [![Donate](https://img.shields.io/badge/donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=G33QACCVKYD7U)
![npm](https://img.shields.io/npm/dt/cordova-plugin-sms-retriever) ![npm](https://img.shields.io/npm/v/cordova-plugin-sms-retriever) ![GitHub package.json version](https://img.shields.io/github/package-json/v/andreszs/cordova-plugin-sms-retriever?color=FF6D00&label=master&logo=github) ![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/andreszs/cordova-plugin-sms-retriever) ![GitHub top language](https://img.shields.io/github/languages/top/andreszs/cordova-plugin-sms-retriever) ![GitHub](https://img.shields.io/github/license/andreszs/cordova-plugin-sms-retriever) ![GitHub last commit](https://img.shields.io/github/last-commit/andreszs/cordova-plugin-sms-retriever)

@@ -21,7 +21,46 @@ # cordova-plugin-sms-retriever

## Ionic
### Dev version:
```bash
npm i awesome-cordova-plugins-sms-retriever-api
```
### Prod version: https://github.com/danielsogl/awesome-cordova-plugins/pull/4528
```bash
npm i @awesome-cordova-plugins/sms-retriever-api
```
## Ionic Demo
https://github.com/MaximBelov/cordova-plugin-sms-retriever-lab
# Methods
## getPhoneNumber
Opens a dialog to select your mobile numbers saved in phone and [returns selected phone number](https://developers.google.com/identity/sms-retriever/request#1_obtain_the_users_phone_number).
```javascript
var onSuccess = function (strSuccess) {
console.log(strSuccess);
};
var onFail = function (strError) {
console.log(strError);
};
cordova.plugins.SMSRetriever.getPhoneNumber(onSuccess, onFail);
```
## startWatch
Start listening for a single incoming [verification SMS](https://developers.google.com/identity/sms-retriever/verify#1_construct_a_verification_message "verification SMS") for 5 minutes.
```javascript
cordova.plugins.SMSRetriever.startWatch(successCallback, errorCallback);
```
:warning: Method moved from **window** to **cordova.plugins** object in version 2.0.0

@@ -52,2 +91,21 @@

## stopWatch
Stops listening for a single incoming verification SMS
### Return values
- **SMS_RETRIEVER_DONE**
### Example
```javascript
var onSuccess = function (strSuccess) {
console.log(strSuccess);
};
var onFail = function (strError) {
console.log(strError);
};
cordova.plugins.SMSRetriever.stopWatch(onSuccess, onFail);
```
## getHashString

@@ -57,4 +115,10 @@

```javascript
cordova.plugins.SMSRetriever.getHashString(successCallback, errorCallback);
```
:warning: Method moved from **window** to **cordova.plugins** object in version 2.0.0
### Remarks

@@ -119,3 +183,3 @@

- Starting from **plugin 2.0.0**, the <#> prefix is no longer required by the plugin.
- Starting from an unknown **Play Services** version, the <#> is no longer required.
- Starting from an unknown **Play Services** version, the <#> is no longer required in the received SMS.

@@ -130,5 +194,6 @@ Otherwise, the contents of the verification message can be whatever you choose. It is helpful to create a message from which you can easily extract the one-time code later on. For example, a valid verification message might look like the following:

You can download the [SMS Retriever plugin demo app](https://www.andreszsogon.com/cordova-sms-retriever-plugin-demo-app/) from the Play Store; its source code is provided in the **demo** folder.
- [Compiled APK and reference](https://www.andreszsogon.com/cordova-sms-retriever-plugin-demo-app/) including testing procedure instructions
- [Source code for www folder](https://github.com/andreszs/cordova-plugin-demos)
[![](https://github.com/andreszs/cordova-plugin-demos/blob/main/com.andreszs.smsretriever.demo/screenshots/sms_retriever_demo_3.png?raw=true)](https://www.andreszsogon.com/cordova-sms-retriever-plugin-demo-app/) [![](https://github.com/andreszs/cordova-plugin-demos/blob/main/com.andreszs.smsretriever.demo/screenshots/sms_retriever_demo_4.png?raw=true)](https://www.andreszsogon.com/cordova-sms-retriever-plugin-demo-app/)
<img src="https://github.com/andreszs/cordova-plugin-demos/blob/main/com.andreszs.smsretriever.demo/screenshots/sms_retriever_demo_2.png?raw=true" width="240" /> <img src="https://github.com/andreszs/cordova-plugin-demos/blob/main/com.andreszs.smsretriever.demo/screenshots/sms_retriever_demo_3.png?raw=true" width="240" /> <img src="https://github.com/andreszs/cordova-plugin-demos/blob/main/com.andreszs.smsretriever.demo/screenshots/sms_retriever_demo_4.png?raw=true" width="240" />

@@ -163,2 +228,7 @@ # FAQ

### 3.0.0
- Added method stopWatch
- Added method getPhoneNumber
### 2.0.1

@@ -165,0 +235,0 @@

package com.andreszs.smsretriever;
import android.Manifest;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.IntentSender;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import org.apache.cordova.CallbackContext;

@@ -23,6 +26,10 @@ import org.apache.cordova.CordovaInterface;

import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.credentials.Credential;
import com.google.android.gms.auth.api.credentials.CredentialPickerConfig;
import com.google.android.gms.auth.api.credentials.HintRequest;
import com.google.android.gms.auth.api.phone.SmsRetriever;
import com.google.android.gms.auth.api.phone.SmsRetrieverClient;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.tasks.OnFailureListener;

@@ -32,236 +39,240 @@ import com.google.android.gms.tasks.OnSuccessListener;

/* AppSignatureHelper */
import android.content.ContextWrapper;
import android.content.pm.Signature;
import android.util.Base64;
import android.util.Log;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
public class SMSRetriever extends CordovaPlugin {
public class SMSRetriever extends CordovaPlugin implements SMSBroadcastReceiver.OTPReceiveListener {
private static String LOG_TAG;
private static boolean STARTED = false;
private CallbackContext callbackContext;
private SmsRetrieverClient smsRetrieverClient;
private static String LOG_TAG;
private static final int RESOLVE_HINT = 234433;
private static GoogleApiClient apiClient;
private static final String ACTION_START_WATCH = "startWatch";
private static final String ACTION_GET_SIGNATURE = "getHashString";
private Context applicationContext;
private CallbackContext startWatchCallbackContext;
private CallbackContext getPhoneNumberCallbackContext;
private SMSBroadcastReceiver smsBroadcastReceiver;
/* AppSignatureHelper */
private static final String HASH_TYPE = "SHA-256";
public static final int NUM_HASHED_BYTES = 9;
public static final int NUM_BASE64_CHAR = 11;
private static final String ACTION_START_WATCH = "startWatch";
private static final String ACTION_GET_SIGNATURE = "getHashString";
private static final String ACTION_STOP_WATCH = "stopWatch";
private static final String ACTION_GET_PHONE_NUMBER = "getPhoneNumber";
public SMSRetriever() {
this.LOG_TAG = SMSRetriever.class.getSimpleName();
Log.i(LOG_TAG, "Constructed");
}
public SMSRetriever() {
LOG_TAG = SMSRetriever.class.getSimpleName();
Log.i(LOG_TAG, "Constructed");
}
@Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
@Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
applicationContext = cordova.getActivity().getApplicationContext();
}
// Get an instance of SmsRetrieverClient, used to start listening for a matching SMS message.
smsRetrieverClient = SmsRetriever.getClient(cordova.getActivity().getApplicationContext());
}
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
PluginResult result = null;
this.callbackContext = callbackContext;
Log.i(LOG_TAG, String.format("Executing the %s action started", action));
Log.i(LOG_TAG, String.format("Executing the %s action started", action));
if (action.equals(ACTION_START_WATCH)) {
this.startWatch(callbackContext);
} else if (action.equals(ACTION_GET_SIGNATURE)) {
this.getHashString(callbackContext);
} else {
Log.w(LOG_TAG, String.format("Invalid action passed: %s", action));
result = new PluginResult(PluginResult.Status.INVALID_ACTION);
callbackContext.sendPluginResult(result);
}
return true;
}
switch (action) {
case ACTION_START_WATCH:
this.startWatch(callbackContext);
break;
case ACTION_STOP_WATCH:
this.stopWatch(callbackContext);
break;
case ACTION_GET_SIGNATURE:
this.getHashString(callbackContext);
break;
case ACTION_GET_PHONE_NUMBER:
this.getPhoneNumber(callbackContext);
break;
default:
Log.w(LOG_TAG, String.format("Invalid action passed: %s", action));
PluginResult result = new PluginResult(PluginResult.Status.INVALID_ACTION);
callbackContext.sendPluginResult(result);
break;
}
return true;
}
public void onDestroy() {
if (SmsBrReceiver != null) {
try {
cordova.getActivity().getApplicationContext().unregisterReceiver(SmsBrReceiver);
SmsBrReceiver = null;
Log.i(LOG_TAG, "SMS Retriever unregistered successfully");
} catch (Exception e) {
Log.e(LOG_TAG, e.getMessage());
}
}
}
public void onDestroy() {
this.unregisterListeners();
}
private void startWatch(final CallbackContext callbackContext) {
Log.i(LOG_TAG, ACTION_START_WATCH);
public void onSmsReceived(String smsMessage) {
Log.w(LOG_TAG, "SMS_RECEIVED");
Log.w(LOG_TAG, smsMessage);
try {
JSONObject item = new JSONObject();
item.put("sms", smsMessage);
PluginResult result = new PluginResult(PluginResult.Status.OK, item);
startWatchCallbackContext.sendPluginResult(result);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
startWatchCallbackContext.error(e.getMessage());
}
this.unregisterListeners();
}
// Starts SmsRetriever, which waits for ONE matching SMS message until timeout
// (5 minutes). The matching SMS message will be sent via a Broadcast Intent with
// action SmsRetriever#SMS_RETRIEVED_ACTION.
try {
if(this.STARTED){
PluginResult result = new PluginResult(PluginResult.Status.OK, "SMS_RETRIEVER_ALREADY_STARTED");
result.setKeepCallback(true);
callbackContext.sendPluginResult(result);
}else{
Task<Void> task = smsRetrieverClient.startSmsRetriever();
public void onSmsReceiveTimeOut() {
Log.w(LOG_TAG, "TIMEOUT");
PluginResult resultTimeout = new PluginResult(PluginResult.Status.ERROR, "TIMEOUT");
startWatchCallbackContext.sendPluginResult(resultTimeout);
this.unregisterListeners();
}
// Listen for success/failure of the start Task.
task.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
// Successfully started retriever, expect broadcast intent
Log.i(LOG_TAG, "smsRetrieverClient started successfully");
STARTED = true;
public void onSmsReceivedError(String error) {
PluginResult result = new PluginResult(PluginResult.Status.ERROR, error);
startWatchCallbackContext.sendPluginResult(result);
this.unregisterListeners();
}
// Use a BroadcastReceiver to receive the verification message.
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(SmsRetriever.SMS_RETRIEVED_ACTION);
private void startWatch(final CallbackContext callbackContext) {
if (startWatchCallbackContext != null) {
PluginResult result = new PluginResult(PluginResult.Status.OK, "SMS_RETRIEVER_ALREADY_STARTED");
callbackContext.sendPluginResult(result);
return;
}
// Starts SmsRetriever, which waits for ONE matching SMS message until timeout
// (5 minutes). The matching SMS message will be sent via a Broadcast Intent with
// action SmsRetriever#SMS_RETRIEVED_ACTION.
startWatchCallbackContext = callbackContext;
try {
smsBroadcastReceiver = new SMSBroadcastReceiver();
smsBroadcastReceiver.setOTPListener(this);
try {
cordova.getActivity().getApplicationContext().registerReceiver(SmsBrReceiver, intentFilter);
PluginResult result = new PluginResult(PluginResult.Status.OK, "SMS_RETRIEVER_STARTED");
result.setKeepCallback(true);
callbackContext.sendPluginResult(result);
} catch (Exception e) {
Log.e(LOG_TAG, e.getMessage());
PluginResult result = new PluginResult(PluginResult.Status.ERROR, e.getMessage());
callbackContext.sendPluginResult(result);
}
}
});
task.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// Failed to start retriever, inspect Exception for more details
Log.e(LOG_TAG, e.getMessage());
// Get an instance of SmsRetrieverClient, used to start listening for a matching SMS message.
SmsRetrieverClient smsRetrieverClient = SmsRetriever.getClient(applicationContext);
Task<Void> task = smsRetrieverClient.startSmsRetriever();
PluginResult result = new PluginResult(PluginResult.Status.ERROR, e.getMessage());
callbackContext.sendPluginResult(result);
}
});
}
// Listen for success/failure of the start Task.
task.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
// Successfully started retriever, expect broadcast intent
Log.i(LOG_TAG, "smsRetrieverClient started successfully");
} catch (Exception e) {
Log.e(LOG_TAG, e.getMessage());
PluginResult result = new PluginResult(PluginResult.Status.ERROR, e.getMessage());
callbackContext.sendPluginResult(result);
}
}
// Use a BroadcastReceiver to receive the verification message.
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(SmsRetriever.SMS_RETRIEVED_ACTION);
/**
* Google Play services uses the hash string to determine which verification messages to send to your app. The hash string is made of your app's package name and your app's public key certificate. https://developers.google.com/identity/sms-retriever/verify#computing_your_apps_hash_string
*/
private void getHashString(final CallbackContext callbackContext) {
try {
applicationContext.registerReceiver(smsBroadcastReceiver, intentFilter);
PluginResult result = new PluginResult(PluginResult.Status.OK, "SMS_RETRIEVER_STARTED");
result.setKeepCallback(true);
startWatchCallbackContext.sendPluginResult(result);
} catch (Exception e) {
Log.e(LOG_TAG, e.getMessage());
PluginResult result = new PluginResult(PluginResult.Status.ERROR, e.getMessage());
startWatchCallbackContext.sendPluginResult(result);
}
}
});
task.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// Failed to start retriever, inspect Exception for more details
Log.e(LOG_TAG, e.getMessage());
PluginResult result = new PluginResult(PluginResult.Status.ERROR, e.getMessage());
startWatchCallbackContext.sendPluginResult(result);
}
});
} catch (Exception e) {
Log.e(LOG_TAG, e.getMessage());
PluginResult result = new PluginResult(PluginResult.Status.ERROR, e.getMessage());
startWatchCallbackContext.sendPluginResult(result);
}
}
ArrayList<String> appCodes = this.getAppSignatures();
private void stopWatch(final CallbackContext callbackContext) {
callbackContext.success();
if (startWatchCallbackContext != null) {
startWatchCallbackContext.success("SMS_RETRIEVER_DONE");
}
this.unregisterListeners();
}
if (appCodes.size() == 0 || appCodes.get(0) == null) {
String err = "Unable to find package to obtain hash";
PluginResult result = new PluginResult(PluginResult.Status.ERROR, err);
callbackContext.sendPluginResult(result);
} else {
String hash = appCodes.get(0);
PluginResult result = new PluginResult(PluginResult.Status.OK, hash);
callbackContext.sendPluginResult(result);
}
}
private void unregisterListeners() {
if (smsBroadcastReceiver != null) {
try {
applicationContext.unregisterReceiver(smsBroadcastReceiver);
smsBroadcastReceiver = null;
Log.i(LOG_TAG, "SMS Retriever unregistered successfully");
} catch (Exception e) {
Log.e(LOG_TAG, e.getMessage());
}
}
/**
* BroadcastReceiver to wait for SMS messages. This can be registered either in the AndroidManifest or at runtime. Should filter Intents on SmsRetriever.SMS_RETRIEVED_ACTION.
*/
private BroadcastReceiver SmsBrReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) {
Bundle extras = intent.getExtras();
Status status = (Status) extras.get(SmsRetriever.EXTRA_STATUS);
JSONObject item = new JSONObject();
if (startWatchCallbackContext != null) {
startWatchCallbackContext = null;
}
}
switch (status.getStatusCode()) {
case CommonStatusCodes.SUCCESS:
// Get SMS message contents
String smsMessage = (String) extras.get(SmsRetriever.EXTRA_SMS_MESSAGE);
Log.i(LOG_TAG, smsMessage);
STARTED = false;
private void getPhoneNumber(final CallbackContext callbackContext) {
this.getPhoneNumberCallbackContext = callbackContext;
try {
FragmentActivity activity = cordova.getActivity();
if (apiClient == null) {
apiClient = new GoogleApiClient.Builder(activity).addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(@Nullable Bundle bundle) {
Log.d(LOG_TAG, "onConnected: ");
}
try {
item.put("sms", smsMessage);
PluginResult result = new PluginResult(PluginResult.Status.OK, item);
callbackContext.sendPluginResult(result);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
callbackContext.error(e.getMessage());
}
@Override
public void onConnectionSuspended(int i) {
Log.d(LOG_TAG, "onConnectionSuspended: ");
}
}).enableAutoManage(activity, new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
}).addApi(Auth.CREDENTIALS_API).build();
}
break;
HintRequest hintRequest = new HintRequest.Builder().setHintPickerConfig(new CredentialPickerConfig.Builder().setShowCancelButton(true).build()).setPhoneNumberIdentifierSupported(true).build();
case CommonStatusCodes.TIMEOUT:
// Waiting for SMS timed out (5 minutes)
Log.w(LOG_TAG, "TIMEOUT");
STARTED = false;
PluginResult resultTimeout = new PluginResult(PluginResult.Status.ERROR, "TIMEOUT");
callbackContext.sendPluginResult(resultTimeout);
cordova.setActivityResultCallback(this);
PendingIntent hintPickerIntent = Auth.CredentialsApi.getHintPickerIntent(apiClient, hintRequest);
activity.startIntentSenderForResult(hintPickerIntent.getIntentSender(), RESOLVE_HINT, null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
break;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
String phoneNumber = null;
try {
if (requestCode == RESOLVE_HINT) {
if (resultCode == Activity.RESULT_OK) {
Credential credential = intent.getParcelableExtra(Credential.EXTRA_KEY);
phoneNumber = credential.getId();
}
}
}
}
};
if (phoneNumber != null) {
getPhoneNumberCallbackContext.success(phoneNumber);
} else {
getPhoneNumberCallbackContext.error("Phone number not selected.");
}
} catch (Exception ex) {
ex.printStackTrace();
getPhoneNumberCallbackContext.error(ex.getMessage());
}
}
/**
* Get all the app signatures for the current package https://github.com/googlesamples/android-credentials/blob/master/sms-verification/android/app/src/main/java/com/google/samples/smartlock/sms_verify/AppSignatureHelper.java
*
* @return
*/
private ArrayList<String> getAppSignatures() {
ArrayList<String> appCodes = new ArrayList<String>();
try {
// Get all package signatures for the current package
String packageName = cordova.getActivity().getApplicationContext().getPackageName();
PackageManager packageManager = cordova.getActivity().getApplicationContext().getPackageManager();
Signature[] signatures = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES).signatures;
// For each signature create a compatible hash
for (Signature signature : signatures) {
String hash = hash(packageName, signature.toCharsString());
if (hash != null) {
appCodes.add(String.format("%s", hash));
}
}
} catch (PackageManager.NameNotFoundException e) {
Log.e(LOG_TAG, e.getMessage());
}
return appCodes;
}
private static String hash(String packageName, String signature) {
String appInfo = packageName + " " + signature;
try {
MessageDigest messageDigest = MessageDigest.getInstance(HASH_TYPE);
messageDigest.update(appInfo.getBytes(StandardCharsets.UTF_8));
byte[] hashSignature = messageDigest.digest();
// truncated into NUM_HASHED_BYTES
hashSignature = Arrays.copyOfRange(hashSignature, 0, NUM_HASHED_BYTES);
// encode into Base64
String base64Hash = Base64.encodeToString(hashSignature, Base64.NO_PADDING | Base64.NO_WRAP);
base64Hash = base64Hash.substring(0, NUM_BASE64_CHAR);
return base64Hash;
} catch (NoSuchAlgorithmException e) {
Log.e(LOG_TAG, e.getMessage());
}
return null;
}
/**
* Google Play services uses the hash string to determine which verification messages to send to your app. The hash string is made of your app's package name and your app's public key certificate. https://developers.google.com/identity/sms-retriever/verify#computing_your_apps_hash_string
*/
private void getHashString(final CallbackContext callbackContext) {
ArrayList<String> appCodes = new AppSignatureHashHelper(applicationContext).getAppSignatures();
if (appCodes.size() == 0 || appCodes.get(0) == null) {
String err = "Unable to find package to obtain hash";
PluginResult result = new PluginResult(PluginResult.Status.ERROR, err);
callbackContext.sendPluginResult(result);
} else {
String hash = appCodes.get(0);
PluginResult result = new PluginResult(PluginResult.Status.OK, hash);
callbackContext.sendPluginResult(result);
}
}
}

@@ -17,7 +17,13 @@ var exec = require('cordova/exec');

},
stopWatch: function (successCallback, failureCallback) {
exec(successCallback, failureCallback, 'SMSRetriever', 'stopWatch', []);
},
getHashString: function (successCallback, failureCallback) {
exec(successCallback, failureCallback, 'SMSRetriever', 'getHashString', []);
}
},
getPhoneNumber: function (successCallback, failureCallback) {
exec(successCallback, failureCallback, 'SMSRetriever', 'getPhoneNumber', []);
},
};
module.exports = smsRetriever;