Xamarin broadcastreceiver реагирует на закрытие приложения

В этом приложении я хочу записывать информацию о входящем SMS (с определенного номера) в файл, даже если программа не "активна" для пользователя. После некоторого исследования я нашел эти ссылки BroadcastReceiver SMS_Received не работает на новых устройствах (я использую Xiaomi Redmi Note 4) и Как заставить андроид запускать приложение по полученному конкретному смс, в котором говорится, что «BroadcastReceiver может быть запущен из ОС, если это указано в файле манифеста». Я пробовал эти решения, но ни одно из них не работает на моем устройстве. Они работают должным образом, когда приложение открыто, но когда оно закрывается, ничего не происходит (я также пытался перезагрузить свое устройство). * Параллельно есть также некоторые вопросы, на которые отмечен правильный ответ, чтобы создать услугу.

Код для BroadcastReceiver:

public class NewSMSReceived : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        if (Android.Provider.Telephony.Sms.Intents.SmsReceivedAction.Equals(intent.Action))
        {
            Toast.MakeText(context, "BroadcastReceiver is activated...", ToastLength.Long).Show();

            var info_Intent = intent.Extras;

            if (info_Intent != null)
            {
                Java.Lang.Object[] pdus = (Java.Lang.Object[])info_Intent.Get("pdus");

                var msg = SmsMessage.CreateFromPdu((byte[])pdus[0]);

                var msg_from = msg.DisplayOriginatingAddress;

                var CellNumfilePath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath.ToString(), "\\MyApp\\CellNum.txt");

                if (msg_from == ("xxxx" + File.ReadAllText(CellNumfilePath)))
                {

                    Toast.MakeText(Application.Context, "New message from XXXXX", ToastLength.Long).Show();

                    var msg_txt_date = msg.MessageBody + "\t" + DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss");

                    var DataStorfilePath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath.ToString(), "\\MyApp\\ObtainedData.txt");

                    File.AppendAllText(DataStorfilePath, msg_txt_date + Environment.NewLine);

                }
            }

        }

    }


}

Файл манифеста:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="myApp.AndroidApp" android:installLocation="auto">
    <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="25" />
    <uses-permission android:name="android.permission.READ_SMS" />
    <uses-permission android:name="android.permission.BROADCAST_SMS" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.WRITE_SMS" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme">
        <receiver android:name=".NewSMSReceived"
              android:enabled="true"
              android:exported="true"
              android:permission="android.permission.RECEIVE_SMS"
              >
            <intent-filter android:priority="1000">
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

Метод, используемый для запроса разрешений во время выполнения

    private void CheckMandatoryPermissions()
    {
        string SMSpermission = Manifest.Permission.ReadSms;

        string[] NeededPermissions =
        {
            Manifest.Permission.ReadSms,
            Manifest.Permission.ReceiveSms,
            Manifest.Permission.SendSms,
            Manifest.Permission.WriteSms,
            Manifest.Permission.BroadcastSms,
            Manifest.Permission.ReadExternalStorage,
            Manifest.Permission.WriteExternalStorage,
            Manifest.Permission.ReadSms,
            Manifest.Permission.ReceiveBootCompleted
        };

        bool needed_conditions = CheckSelfPermission(SMSpermission) != (int)Permission.Granted || CheckSelfPermission(Manifest.Permission.ReceiveSms) != (int)Permission.Granted;
        if (needed_conditions)
        {
            //Explain to the user why we need to access SMS and storage 
            var messageView = FindViewById<TextView>(Resource.Id.ZipCodeSearchLabel);

            string messageInfo = "XXXXX";

            Snackbar ReasonMessage = Snackbar.Make((View)messageView, messageInfo, Snackbar.LengthIndefinite);

            View snackbarView = ReasonMessage.View;

            TextView snacktext = (TextView)snackbarView.FindViewById<TextView>(Resource.Id.snackbar_text);

            snacktext.SetMaxLines(4);

            //snackbarView.SetMinimumHeight(300);

            ReasonMessage.SetAction("OK", v => RequestPermissions(NeededPermissions, 0)).Show();

            return;
        }
    }

Я также пытался указывать получателя не из манифеста, а из класса и всегда тот же результат. Не думаю, что проблема связана с разрешениями, потому что я могу «поймать» новое смс, когда приложение запущено. Какие-либо предложения? заранее спасибо

permission в элементе <receiver> должен быть android.permission.BROADCAST_SMS, а не RECEIVE. Кроме того, если вы работаете на Marshmallow или более поздней версии, вам может потребоваться запросить все разрешения SMS во время выполнения, но похоже, что вы справились с этим, если это необходимо.

Mike M. 31.10.2018 12:00

Только что попробовал, результат тот же. ОС - Nougat 7.1, и, как вы уже упоминали, я также запрашиваю разрешения во время выполнения. Я редактирую вопрос, чтобы добавить метод, используемый для запроса разрешений во время выполнения.

Jonadri Bundo 31.10.2018 12:17

Хм, есть ли NewSMSReceived в вашем основном каталоге с исходными кодами? То есть правильный ли атрибут name на <receiver>? Вы пробовали что-то другое, кроме Toasts, для проверки приемника? Например, журнал распечатывается в самом верху OnReceive(), просто чтобы проверить, работает ли он вообще? Кроме того, ваше приложение не может содержать разрешение BROADCAST_SMS, поэтому вы можете удалить соответствующий элемент <uses-permission> в манифесте и элемент NeededPermissions.

Mike M. 31.10.2018 12:34

О, также, теперь, когда я только что заметил, что вы сказали, что ваше устройство - это Xiaomi, убедитесь, что нет дополнительных разрешений или настроек, которые не позволяют вашему приложению получать SMS в фоновом режиме. Я знаю, что у некоторых производителей есть специальные настройки для сторонних приложений.

Mike M. 31.10.2018 12:42

Класс NewSMSReceived находится в том же каталоге, что и MainActivity.cs, я имею в виду, что он не находится внутри подпапки проекта и имеет то же пространство имен, что и MainActivity. Я тестирую BroadcastReceiver, проверяя текстовый файл, который при активации BroadcastReceiver должен обновляться (он никогда не получает обновления при закрытии приложения). Мое главное сомнение также связано с атрибутом имени получателя. Любые предложения о том, как я могу указать полное имя, где мне считать?

Jonadri Bundo 31.10.2018 12:48

Да, вы захотите разместить печать журнала в верхней части OnReceive() и проверять свои журналы на случай, если что-то не так до записи файла. Что касается name, AFAICT из других примеров, это должно быть хорошо, но я не очень знаком с Xamarin. Вы можете взглянуть на этот ответ, чтобы узнать, как справиться с этим обоими способами в Xamarin. Кроме того, обратите внимание на тот параметр / разрешение, о котором я упоминал. У меня было несколько вопросов по SMS, которые я решил, обнаружив, что это проблема.

Mike M. 31.10.2018 13:03

Я проверял другие возможные конкретные ограничения производителя Xiaomi, и я думаю, что активировал их все, хотя я не могу сказать наверняка. Я также проверил атрибут имени тега приемника, и он правильный. Теперь я пытаюсь отладить с помощью печати журнала, а позже я думаю протестировать его на другом устройстве. Спасибо за вашу помощь!

Jonadri Bundo 31.10.2018 14:43

@MikeM. После некоторых тестов и некоторых исследований я заметил, что приложение может реагировать, когда приходит новое смс, когда оно находится в фоновом режиме, но как только приложение закрывается, оно теряет функциональность. Возможно, это связано с Xiaomi, но я не могу скажите точно так как не тестировал на другом устройстве

Jonadri Bundo 31.10.2018 16:17

Да, это нестандартное поведение, но я слышал, что такое случается с некоторыми производителями / моделями. Я бы сказал, что это, скорее всего, сработает, если вы протестируете на «обычном» устройстве или эмуляторе.

Mike M. 31.10.2018 16:22

ТЫ ПРАВ! Только что выполнив тест с эмулятора, я получил сообщение Toast, когда с желаемого номера пришло определенное sms, но это только после того, как я открыл и закрыл приложение не раньше, но это может быть решено с помощью намерения BOOT. Если вы опубликуете ответ, я проголосую за него как за правильный! Благодарность!

Jonadri Bundo 31.10.2018 16:36

Да, вы должны запустить приложение хотя бы один раз после установки, прежде чем <receiver> заработает. Я предполагал, что вы уже это делаете, потому что вам нужно запрашивать разрешения во время выполнения. Это тоже проблема Xiaomi? Или он все равно не работает, если вы полностью закроете приложение?

Mike M. 31.10.2018 16:56

Не каждый раз, потому что я не полностью удалял приложение с устройства, а только развертывал его и перед запуском проверял (вручную), что приложение имеет все необходимые разрешения и не имеет ограничений. Я думаю, что получателю этого достаточно, я имею в виду наличие разрешений.

Jonadri Bundo 31.10.2018 17:10

Ах, хорошо, это моя проблема. Я не должен был предполагать, что вы запускаете приложение после установки. Начиная с Android 3.1, ваше приложение должно быть явно запущено после установки, чтобы вывести его из состояния остановился. До этого момента получатель, зарегистрированный в манифесте, работать не будет. Это для защиты от вредоносных программ. Anyhoo, извините, если я вызвал путаницу. Это обычная проблема, поэтому я просто помечу ее как дубликат. Спасибо хоть. Рад, что у тебя все получилось. Ваше здоровье!

Mike M. 31.10.2018 17:33
0
13
159
0

Другие вопросы по теме