Создание SMS-приложения по умолчанию в Xamarin.Forms - PullRequest
0 голосов
/ 27 апреля 2020

Я разрабатываю приложение SMS в Xamarin, которое должно быть SMS по умолчанию, я зарегистрировал класс Sms Receiver, но когда устройство получило сообщение, эта ошибка появляется.

Java.Lang.RuntimeException: 'Unable to instantiate receivercom.companyName.MySmsApp.DroidSmsReceiver: java.lang.ClassNotFoundException:Didn't find class "com.companyName.MySmsApp.DroidSmsReceiver" on path:DexPathList[[zip file "/data/app/com.companyName.MySmsApp-NaDrepA_GVue_nq4DxzmqA==/base.apk"],nativeLibraryDirectories=[/data/app/com.companyName.MySmsApp-NaDrepA_GVue_nq4DxzmqA==/lib/x86, /data/app/com.companyName.MySmsApp-NaDrepA_GVue_nq4DxzmqA==/base.apk!/lib/x86, /system/lib]]'

my Android Manifest :

     <receiver android:name=".DroidSmsReceiver"
        android:exported="true"
        android:permission="android.permission.BROADCAST_SMS">
        <intent-filter android:priority="999" >
            <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            <action android:name="android.provider.Telephony.SMS_DELIVER" />
            <action android:name="android.provider.Telephony.SMS_DELIVER_ACTION" />
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
        </intent-filter>
    </receiver>

    <receiver android:name=".MMSBroadcastReceiver"
        android:exported="true"
        android:permission="android.permission.BROADCAST_WAP_PUSH">
        <intent-filter android:priority="999" >
            <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
            <data android:mimeType="application/vnd.wap.mms-message" />
        </intent-filter>
    </receiver>



 <!--  Activity that allows the user to send new SMS/MMS messages -->
    <activity android:name=".ComposeSmsActivity" >
        <intent-filter>
            <action android:name="android.intent.action.SEND" />                
            <action android:name="android.intent.action.SENDTO" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="sms" />
            <data android:scheme="smsto" />
            <data android:scheme="mms" />
            <data android:scheme="mmsto" />
        </intent-filter>
    </activity>
<service
        android:name=".QuickResponseService"
        android:enabled="true"
        android:exported="true"
        android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE">
        <intent-filter>
            <category android:name="android.intent.category.DEFAULT" />
            <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
            <data android:scheme="sms" />
            <data android:scheme="smsto" />
            <data android:scheme="mms" />
            <data android:scheme="mmsto" />
        </intent-filter>
    </service>

Я также пытался

     <receiver android:name=".DroidSmsReceiver"
        android:permission="android.permission.BROADCAST_SMS">
         <intent-filter>
         <action android:name="android.provider.Telephony.SMS_RECEIVED" />
          <action android:name="android.provider.Telephony.SMS_DELIVER" />
     </intent-filter></receiver>

Мой приемник, расположенный в: MySmsApp.Droid

   [BroadcastReceiver(Enabled = true, Exported = true)]
   [IntentFilter(new[] { "android.provider.Telephony.SMS_RECEIVED" })]
   //[IntentFilter(new[] { "android.provider.Telephony.SMS_DELIVER" })]
   public class DroidSmsReceiver : BroadcastReceiver
   {

        //private const string IntentAction = "android.provider.Telephony.SMS_RECEIVED";

        protected string address, message = "";
        public override void OnReceive(Context context, Intent intent)
        {
               //message received
        }
     }

Я также зарегистрировал приемник в MainActivity .cs

   RegisterReceiver(new DroidSmsReceiver(), new IntentFilter("android.provider.Telephony.SMS_DELIVER"));

Заранее спасибо, ребята.

1 Ответ

1 голос
/ 27 апреля 2020

Хотите ли вы получить результат, например, следуя GIF в формах xamarin .?

enter image description here

Если это так, я использовал службу зависимости для достижения этой цели.

Во-первых, я создаю интерфейс в PCL

public interface ISmsReader
    {
        void GetSmsInbox();
    }

Вы можете использовать его в PCL MainPage.xaml.cs.

    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            MessagingCenter.Subscribe<List<string>>(this, "MyMessage", (expense) =>
            {
                List<string> mylist= expense as List<string>;
                string allText= "";
                foreach (string item in mylist)
                {
                    allText += item+"  ";
                }
                editorSms.Text = allText;
            });



        }
     private void Button_Clicked(object sender, EventArgs e)
        {
            Xamarin.Forms.DependencyService.Get<ISmsReader>().GetSmsInbox();
        }
    }

Вот мой MainPage.xaml.

 <StackLayout>
        <Button Text="open broadcase" Clicked="Button_Clicked"/>
        <Label x:Name="editorSms"/>
   </StackLayout>

Затем добейтесь этого интерфейса в папке xxxx.Droid. Примечание: Ваш new IntentFilter("android.provider.Telephony.SMS_DELIVER") IntentFilter неверен в вашем MainActivity.cs, он должен быть android.provider.Telephony.SMS_RECEIVED

[assembly: Xamarin.Forms.Dependency(typeof(MySmsReader))]
namespace ScanDemo.Droid
{
   public class MySmsReader : ISmsReader
    {
        public void GetSmsInbox()
        {
            IntentFilter filter = new IntentFilter();
            filter.AddAction("android.provider.Telephony.SMS_RECEIVED");


            SmsBroadcastRceiver receiver = new SmsBroadcastRceiver();
            Application.Context.RegisterReceiver(receiver, filter);

        }
    }
}

Тогда вот мой код о SmsBroadcastRceiver.

 [BroadcastReceiver(Enabled = true, Exported = true)]
    [IntentFilter(new[] { "android.provider.Telephony.SMS_RECEIVED" })]
    public class SmsBroadcastRceiver : BroadcastReceiver
    {

        public SmsBroadcastRceiver()
        {

        }



        public override void OnReceive(Context context, Intent intent)
        {
            var msgs = Telephony.Sms.Intents.GetMessagesFromIntent(intent);

            List<string> msgList = new List<string>();
            foreach (var msg in msgs)
            {
                msgList.Add(msg.DisplayMessageBody);

            }

            MessagingCenter.Send<List<string>>(msgList, "MyMessage");
        }
    }
}

Если вы установили атрибуты выше класса SmsBroadcastRceiver, вам не нужно объявлять его в манифесте Android.

Вот мое демо (я не получаю разрешение во время выполнения, если вы тестируете мое демо, вы должны добавить разрешение вручную).

https://github.com/851265601/BroadcastReceSMS

==== Обновление ====

Вот мой запущенный GIF (установите сообщение как прочитанное). enter image description here

Если вы хотите установить сообщение как прочитанное, во-первых, мы должны установить для моего приложения приложение по умолчанию для смс.

Мы должны выполнить следующие шаги ( Если нам не хватает одного из них, он не будет работать).

  • В приемнике вещания включите фильтр намерений для SMS_DELIVER_ACTION ("android .provider.Telephony.SMS_DELIVER") , Приемник вещания также должен требовать разрешения BROADCAST_SMS. Это позволяет вашему приложению напрямую получать входящие SMS-сообщения.

  • В приемнике вещания включите фильтр намерений для WAP_PUSH_DELIVER_ACTION ("android .provider.Telephony.WAP_PUSH_DELIVER") с MIME введите "application / vnd.wap.mms-message". Приемник вещания также должен требовать разрешения BROADCAST_WAP_PU SH. Это позволяет вашему приложению напрямую получать входящие MMS-сообщения.

  • В свою деятельность, которая доставляет новые сообщения, включите фильтр намерений для ACTION_SENDTO ("android .intent.action.SENDTO") со схемами, sms :, smsto:, mms: и mmsto :. Это позволяет вашему приложению получать намерения от других приложений, которые хотят доставить сообщение.

  • В службу включите фильтр намерений для ACTION_RESPONSE_VIA_MESSAGE ("android .intent.action.RESPOND_VIA_MESSAGE ") со схемами: sms :, smsto :, mms: и mmsto :. Эта служба также должна требовать разрешения SEND_RESPOND_VIA_MESSAGE.

Без всех четырех ваше приложение не будет отображаться в диалоговом окне выбора SMS по умолчанию.

Вот мой AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.scandemo" android:installLocation="auto">
    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
    <application android:label="ScanDemo.Android">



    <!-- BroadcastReceiver that listens for incoming MMS messages -->

    <receiver android:name=".MmsReceiver"
        android:permission="android.permission.BROADCAST_WAP_PUSH">
      <intent-filter>
        <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
        <data android:mimeType="application/vnd.wap.mms-message" />
      </intent-filter>
    </receiver>
    <!-- Activity that allows the user to send new SMS/MMS messages -->

    <activity android:name=".ComposeSmsActivity" >
      <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <action android:name="android.intent.action.SENDTO" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="sms" />
        <data android:scheme="smsto" />
        <data android:scheme="mms" />
        <data android:scheme="mmsto" />
      </intent-filter>
    </activity>

    <!-- Service that delivers messages from the phone "quick response" -->
    <service android:name=".HeadlessSmsSendService"
             android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
             android:exported="true" >
      <intent-filter>
        <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="sms" />
        <data android:scheme="smsto" />
        <data android:scheme="mms" />
        <data android:scheme="mmsto" />
      </intent-filter>
    </service>



  </application>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_SMS" />
    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.BROADCAST_SMS" />
</manifest>

Достигните MmsReceiver, HeadlessSmsSendService, ComposeSmsActivity, SmsBroadcastRceiver

Вот код о MmsReceiver.cs.

    public class MmsReceiver : BroadcastReceiver
    {
        public override void OnReceive(Context context, Intent intent)
        {
            Toast.MakeText(context, "Received intent!", ToastLength.Short).Show();
        }
    }

Здесь код примерно HeadlessSmsSendService.cs.

    public class HeadlessSmsSendService : Service
    {
        public override IBinder OnBind(Intent intent)
        {
            return null;
        }
    }

код примерно ComposeSmsActivity.cs.

  public class ComposeSmsActivity : Activity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Create your application here
        }
    }

код примерно SmsBroadcastRceiver.cs.

    [BroadcastReceiver(Enabled = true, Exported = true,Permission = "android.permission.BROADCAST_SMS")]
    [IntentFilter(new[] { "android.provider.Telephony.SMS_RECEIVED", "android.provider.Telephony.SMS_DELIVER" })]
    public class SmsBroadcastRceiver : BroadcastReceiver
    {

        public SmsBroadcastRceiver()
        {

        }



        public override void OnReceive(Context context, Intent intent)
        {
            var msgs = Telephony.Sms.Intents.GetMessagesFromIntent(intent);

            List<string> msgList = new List<string>();
            string address = "";
            string body = "";
            foreach (var msg in msgs)
            {
                msgList.Add(msg.DisplayMessageBody);
                address = msg.DisplayOriginatingAddress;
                body = msg.DisplayMessageBody;


            }
            markMessageRead(Android.App.Application.Context, address, body);


            MessagingCenter.Send<List<string>>(msgList, "MyMessage");
        }


        public void markMessageRead(Context context, String number, String body)
        {

            Android.Net.Uri uri = Android.Net.Uri.Parse("content://sms/inbox");
            ICursor cursor = context.ContentResolver.Query(uri, null, null, null, null);
            try
            {

                while (cursor.MoveToNext())
                {
                    if ((cursor.GetString(cursor.GetColumnIndex("address")).Equals(number)) && (cursor.GetInt(cursor.GetColumnIndex("read")) == 0))
                    {
                        if (cursor.GetString(cursor.GetColumnIndex("body")).StartsWith(body))
                        {
                            String SmsMessageId = cursor.GetString(cursor.GetColumnIndex("_id"));
                            ContentValues values = new ContentValues();
                            values.Put("read", true);
                            context.ContentResolver.Update(Android.Net.Uri.Parse("content://sms/inbox"), values, "_id=" + SmsMessageId, null);
                            return;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Log.Error("Mark Read", "Error in Read: " + e.ToString());
            }
        }
    }

Я добавляю следующий код в MainActivity.cs, чтобы установить для моего приложения приложение по умолчанию для смс.

            //Add this to make your app default
            Intent intent = new Intent();
            intent.SetAction(Telephony.Sms.Intents.ActionChangeDefault);
            intent.PutExtra(Telephony.Sms.Intents.ExtraPackageName, this.PackageName);
            StartActivity(intent);

Вот мое новое демо.

https://github.com/851265601/XFormsSMSFilter

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...