Xamarin BroadcastReceiver реагирует, когда приложение закрыто

В этом приложении я хочу записать информацию о входящих SMS (с определенного номера) в файл, даже если программа не «активна» от пользователя. Что ж, после некоторых исследований я обнаружил, что эти ссылки BroadcastReceiver SMS_Received не работают на новых устройствах (я использую Xiaomi Redmi Note 4) и Как заставить Android запускать приложение при получении определенного sms, в котором говорится, что "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;
        }
    }

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


person Jonadri Bundo    schedule 31.10.2018    source источник
comment
permission в элементе <receiver> должно быть android.permission.BROADCAST_SMS, а не RECEIVE. Кроме того, если вы используете Marshmallow или более позднюю версию, вам может потребоваться запросить все разрешения для SMS во время выполнения, но, похоже, вы справились с этим, если это необходимо.   -  person Mike M.    schedule 31.10.2018
comment
Только что попробовал, тот же результат. ОС — Nougat 7.1, и, как вы уже упоминали, я также запрашиваю разрешения во время выполнения. Я редактирую вопрос, чтобы добавить метод, используемый для запроса разрешений во время выполнения.   -  person Jonadri Bundo    schedule 31.10.2018
comment
Хм, NewSMSReceived находится в вашем основном исходном каталоге? То есть правильный ли атрибут name в <receiver>? Пробовали ли вы что-то кроме Toasts для проверки приемника? Например, журнал печатает в самом верху OnReceive(), просто чтобы проверить, работает ли он вообще? Кроме того, само ваше приложение не может иметь разрешение BROADCAST_SMS, поэтому вы можете удалить соответствующий элемент <uses-permission> в манифесте и элемент NeededPermissions.   -  person Mike M.    schedule 31.10.2018
comment
О, кроме того, теперь, когда я только что заметил, что вы сказали, что ваше устройство является Xiaomi, убедитесь, что нет никаких дополнительных разрешений или настроек, которые не позволяют вашему приложению получать SMS в фоновом режиме. Я знаю, что у некоторых производителей есть специальные настройки для сторонних приложений.   -  person Mike M.    schedule 31.10.2018
comment
Класс NewSMSReceived находится в том же каталоге, что и MainActivity.cs, я имею в виду, что он не находится внутри подпапки проекта и имеет то же пространство имен, что и MainActivity. Я тестирую BroadcastReceiver, проверяя текстовый файл, который при активации BroadcastReceiver должен обновляться (он никогда не обновляется, когда приложение закрыто). Мои основные сомнения также связаны с атрибутом имени получателя. Любое предложение о том, как я могу указать полное имя, где я должен считать?   -  person Jonadri Bundo    schedule 31.10.2018
comment
Да, вы захотите поместить печать журнала вверху OnReceive() и проверить свои журналы на случай, если что-то не получится там до записи файла. Что касается name, AFAICT из других примеров, это должно быть хорошо, но я не очень хорошо знаком с Xamarin. Вы можете посмотреть этот ответ для получения информации о том, как обрабатывать это в обоих направлениях в Xamarin. Кроме того, пожалуйста, обратите внимание на этот параметр/разрешение, о котором я упоминал. У меня было несколько вопросов по SMS, решенных здесь, когда я обнаружил, что проблема в этом.   -  person Mike M.    schedule 31.10.2018
comment
Я проверял другие возможные конкретные ограничения производителя Xiaomi и думаю, что активировал их все, хотя не могу сказать наверняка. Я также проверил атрибут имени тега получателя, и он правильный. Сейчас я пытаюсь отладить с помощью печати журнала, а позже думаю проверить его на другом устройстве. Спасибо за вашу помощь!   -  person Jonadri Bundo    schedule 31.10.2018
comment
@МайкМ. После некоторого тестирования и некоторых исследований я заметил, что приложение может реагировать на получение нового смс, когда оно находится в фоновом режиме, но как только приложение закрывается, оно теряет функциональность. Возможно, это связано с Xiaomi, но я не могу скажу точно, так как я не тестировал его в другом устройстве   -  person Jonadri Bundo    schedule 31.10.2018
comment
Да, это не стандартное поведение, но я слышал, что это происходит с некоторыми производителями/моделями. Я бы сказал, что это, вероятно, сработает, если вы протестируете на обычном устройстве или эмуляторе.   -  person Mike M.    schedule 31.10.2018
comment
ТЫ ПРАВ! Только что выполнил тест с эмулятора. Я получил тост-сообщение, когда с нужного номера пришло определенное смс, но это только после того, как я открыл и закрыл приложение не раньше, но это может быть решено с намерением BOOT. Если вы опубликуете ответ, я проголосую за правильный! Спасибо!   -  person Jonadri Bundo    schedule 31.10.2018
comment
Да, вы должны запустить приложение хотя бы один раз после установки, прежде чем <receiver> заработает. Я предполагал, что вы уже делаете это, потому что вам нужно запрашивать разрешения во время выполнения. Была ли эта проблема и в Xiaomi? Или это все еще не работает, если вы полностью закроете приложение?   -  person Mike M.    schedule 31.10.2018
comment
Не каждый раз, потому что я не полностью удалял приложение с устройства, а только развертывал его и перед запуском проверял (вручную), что приложение имеет все необходимые разрешения и не имеет ограничений. Я думаю, что этого достаточно для получателя, я имею в виду наличие разрешений.   -  person Jonadri Bundo    schedule 31.10.2018
comment
Ах, хорошо, это мой плохой. Я не должен был предполагать, что вы запустили приложение после установки. Начиная с Android 3.1, ваше приложение должно быть явно запущено после установки, чтобы вывести его из состояния stopped. До тех пор этот Receiver, зарегистрированный в манифесте, не будет работать. Это для защиты от вредоносных программ. Anyhoo, извините, если я вызвал путаницу. Это распространенная проблема, поэтому я просто отмечу это как дубликат. Спасибо хоть. Рад, что у тебя получилось. Ваше здоровье!   -  person Mike M.    schedule 31.10.2018