在Xamarin表单中自动阅读SMS激活码,而不是由用户手动键入

Nar*_*ani 2 xaml xamarin.android xamarin.forms

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

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

Vah*_*hir 5

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

<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
Run Code Online (Sandbox Code Playgroud)

这是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;
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

这是PCL项目中的RegisterSecondPageModel:

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

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

另一个注意事项是,正如Jason已经说过的,iOS不允许应用读取SMS。