在 Xamarin 窗体中自动读取短信激活码,而不是由用户手动键入



我用Xamarin Forms写了一个项目。当每个用户注册后,我向他/她发送一个激活码进行确认,用户必须插入它才能进入应用程序。但是我正在寻找一个插件或一种用户不需要插入激活码的方法。

我希望自动读取激活码,而无需手动输入。

首先在 Android Manifest 中添加所需的权限:

<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />

这是Android项目中的SmsReceiver类:

using System.Linq;
using System.Text.RegularExpressions;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Telephony;
using Java.Lang;
using Xamarin.Forms;
namespace MyProject.Android
{
[BroadcastReceiver(Enabled = true, Label = "SMS Receiver")]
[IntentFilter(new string[] { "android.provider.Telephony.SMS_RECEIVED", Intent.CategoryDefault })]
public class SmsReceiver : BroadcastReceiver
{
private const string IntentAction = "android.provider.Telephony.SMS_RECEIVED";
private static readonly string Sender = "SMS Sender number here";
private static readonly string[] OtpMessageBodyKeywordSet = {"Keyword1", "Keyword2"}; //You must define your own Keywords
public override void OnReceive(Context context, Intent intent)
{
try
{
if (intent.Action != IntentAction) return;
var bundle = intent.Extras;
if (bundle == null) return;
var pdus = bundle.Get("pdus");
// var castedPdus = JNIEnv.GetArray(pdus.Handle);
var castedPdus = JNIEnv.GetArray<Object>(pdus.Handle);
var msgs = new SmsMessage[castedPdus.Length];
var sb = new StringBuilder();
string sender = null;
for (var i = 0; i < msgs.Length; i++)
{
var bytes = new byte[JNIEnv.GetArrayLength(castedPdus[i].Handle)];
JNIEnv.CopyArray(castedPdus[i].Handle, bytes);
string format = bundle.GetString("format");
msgs[i] = SmsMessage.CreateFromPdu(bytes, format);
if (sender == null)
sender = msgs[i].OriginatingAddress;
sb.Append(string.Format("SMS From: {0}{1}Body: {2}{1}", msgs[i].OriginatingAddress,
System.Environment.NewLine, msgs[i].MessageBody));
//Toast.MakeText(context, sb.ToString(), ToastLength.Long).Show();
//Log.Error("Vahid", sb.ToString());

var msgBody = msgs[i].MessageBody;
if(!sender.Contains(Sender)) return;
bool foundKeyword = OtpMessageBodyKeywordSet.Any(k => msgBody.Contains(k));

if (!foundKeyword) return;
var code = ExtractNumber(msgBody);
MessagingCenter.Send<RegisterSecondPageModel, string>(new RegisterSecondPageModel(), "OtpReceived", code);

}
}
catch (System.Exception ex)
{
//Toast.MakeText(context, ex.Message, ToastLength.Long).Show();
}
}
private static string ExtractNumber(string text)
{
if (string.IsNullOrEmpty(text)) return "";
var regPattern = @"d+";
var number = Regex.Match(text, regPattern).Value;
return number;
}
}
}

注意:为了过滤掉即将到来的短信并仅检测我们自己的短信,我们可以应用以下两个过滤器:

1-忽略所有短信,其发件人号码不是我们的短信发件人号码。

2- 有时我们的短信发送者可能会向我们的客户发送不同的短信,例如一条短信发送激活码,另一条短信通知并确认用户在系统中成功注册。也就是说,我们必须区分它们。为此,我们可以搜索消息正文以找到一些预定义的关键字。当然,我们的SMS服务器必须坚持定义的正文格式。"激活","代码","激活码"可能是英语中的一些示例关键字。当然,关键字应该相应地在每种语言中定义。

这是PCL项目中的RegisterSecondPageModel:

public class RegisterSecondPageModel
{
public RegisterSecondPageModel()
{
SubscribeToOtpReceiving();
}

private void SubscribeToOtpReceiving()
{
MessagingCenter.Subscribe<RegisterSecondPageModel, string>(this, "OtpReceived", (sender, code) =>
{
ActivationCode = code;
});
}
}

另一个注意事项是,正如Jason已经说过的那样,iOS不允许应用程序读取短信。

如果您已经确定您的客户的设备中有SIM卡,则可以创建令牌并向后进行身份验证,将包含您的令牌的短信从客户的设备发送到您的号码。

优点:

  • 没有阻止的号码:即使您在他们的黑名单上,或者他们正在阻止广告和未知发件人,也不会阻止从客户端发送消息。
  • 您无需支付身份验证费用。
  • 这也适用于您无法阅读但可以发送消息的 iOS。

缺点:

  • 客户端可能在另一台设备中使用另一个号码。这可以通过创建易于键入的令牌来克服,这些令牌的过期速度足够快,不会吸引暴力攻击。
  • 由于多种原因,客户可能无法向您的号码发送短信,包括但不限于没有足够的帐户费用。

最新更新