@OM1

Android: как ловить Broadcast'ы в AsyncTask'е?

Всем привет! Опыта в андройдах очень мало, решил попробовать спросить тут,
Есть класс для async:

class CtTask extends AsyncTask<String, String, Void> {

        String SENT_SMS_FLAG = "SENT_SMS";
        String DELIVER_SMS_FLAG = "DELIVER_SMS";

        PendingIntent sentIn;
        PendingIntent deliverIn;

        BroadcastReceiver sentReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context c, Intent in) {
                switch (getResultCode()) {
                    case Activity.RESULT_OK:
                        // sent SMS message successfully;
                        Toast toast = Toast.makeText(getApplicationContext(),
                                "Сообщение отправлено!", Toast.LENGTH_SHORT);
                        toast.show();
                        break;
                    default:
                        // sent SMS message failed
                        break;
                }
            }
        };

        BroadcastReceiver deliverReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context c, Intent in) {
                // SMS delivered actions
                switch (getResultCode()) {
                    case Activity.RESULT_OK:
                        // sent SMS message successfully;
                        Toast toast = Toast.makeText(getApplicationContext(),
                                "Сообщение доставлено!", Toast.LENGTH_SHORT);
                        toast.show();
                        break;
                    default:
                        // sent SMS message failed
                        break;
                }
            }
        };

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            Toast.makeText(getApplicationContext(), "onPreExecute()", Toast.LENGTH_LONG).show();

            Intent sentIn = new Intent(SENT_SMS_FLAG);
            final PendingIntent sentPIn = PendingIntent.getBroadcast(getApplicationContext(),
                    0,
                    sentIn, 0);

            Intent deliverIn = new Intent(SENT_SMS_FLAG);
            final PendingIntent deliverPIn = PendingIntent.getBroadcast(getApplicationContext(), 0,
                    deliverIn, 0);

            registerReceiver(sentReceiver, new IntentFilter(SENT_SMS_FLAG));
            registerReceiver(deliverReceiver, new IntentFilter(DELIVER_SMS_FLAG));
        }

        @Override
        protected Void doInBackground(String... urls) {

            try {
                for (String url : urls) {
                    send(url);
                    publishProgress(url);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            Toast.makeText(getApplicationContext(), "onPostExecute()", Toast.LENGTH_LONG).show();
            unregisterReceiver(sentReceiver);
            unregisterReceiver(deliverReceiver);
        }

        @Override
        protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);
            Toast.makeText(getApplicationContext(), "progress: "+values[0], Toast.LENGTH_LONG).show();
        }


        private String send(String number) throws InterruptedException {
            smsManager.sendTextMessage(number, null, "text", sentIn, deliverIn);
            return "ok";
        }



    }


Из активити работаю с ним вот так:

ArrayList numbers = new ArrayList();
SmsManager smsManager = SmsManager.getDefault();
String[] f = (String[]) numbers.toArray(new String[0]);
CtTask catTask = new CatTask();
ctTask.execute(f);


Что имею: нужная функция smsManager.sendTextMessage(); выполняется, в идеальных условиях смски уходят и приходят. Но суть Broadcast для отлова статуса сообщений не работает как надо.

Вопрос: как правильно использовать Broadcast в классе AsyncTask?

Спасибо за помощь!
  • Вопрос задан
  • 529 просмотров
Пригласить эксперта
Ответы на вопрос 2
artemgapchenko
@artemgapchenko
Вопрос: как правильно использовать Broadcast в классе AsyncTask?

Ответ: никак. После завершения работы AsyncTask тут же прибивается системой, с выполнением метода onPostExecute, в котором ваши broadcast receivers отвязываются от broadcast manager'a. А так как широковещательное сообщение может прийти в BroadcastReceiver с задержкой, то у вас и получается, что AsyncTask отработал, broadcast receivers отвязались, сообщение пришло, но обработать его некому.

Вынесите свои broadcast receivers на уровень Activity, и отключайте их в onPause().
Ответ написан
Комментировать
@OM1 Автор вопроса
Ок, попробую

UPD:

1. Регистрирую BroadcastReceiver в активити
2. В onPause() отменяю в том же активити
3. В классе асинхронном, в onPreExecute() создаю intent

Как-то так? Все равно что-то не то...

UPD2: Вроде додумался, на эмуляторе работает. Принцип:

1. В главном активити:

protected void onResume() {
        super.onResume();
        registerReceiver(sentReceiver, new IntentFilter(SENT_SMS_FLAG));
        registerReceiver(deliverReceiver, new IntentFilter(DELIVER_SMS_FLAG));

    }


    @Override
    public void onPause() {
        super.onPause();
        unregisterReceiver(sentReceiver);
        unregisterReceiver(deliverReceiver);
    }

BroadcastReceiver sentReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context c, Intent in) {
            switch (getResultCode()) {
                case Activity.RESULT_OK:
                    // sent SMS message successfully;
                    Toast toast = Toast.makeText(getApplicationContext(),
                            "Сообщение отправлено!", Toast.LENGTH_SHORT);
                    toast.show();
                    break;
                default:
                    // sent SMS message failed
                    break;
            }
        }
    };

    BroadcastReceiver deliverReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context c, Intent in) {
            // SMS delivered actions
            switch (getResultCode()) {
                case Activity.RESULT_OK:
                    // sent SMS message successfully;
                    Toast toast = Toast.makeText(getApplicationContext(),
                            "Сообщение доставлено!", Toast.LENGTH_SHORT);
                    toast.show();
                    break;
                default:
                    // sent SMS message failed
                    break;
            }
        }
    };



    Intent sentIn = new Intent(SENT_SMS_FLAG);
    Intent deliverIn = new Intent(SENT_SMS_FLAG);


2. В асинхронном классе:

private String send(String number) throws InterruptedException {
            TimeUnit.SECONDS.sleep(1);
            final PendingIntent deliverPIn = PendingIntent.getBroadcast(getApplicationContext(), 0, deliverIn, 0);
            final PendingIntent sentPIn = PendingIntent.getBroadcast(getApplicationContext(), 0,sentIn, 0);
            smsManager.sendTextMessage(number, null, "text", sentPIn, deliverPIn);


            return "ok";
        }


Send() вызывается в protected Void doInBackground(String... urls)

Единственное, за что сомневаюсь - это PendingIntent в ф-ии, которая вызывается из doInBackground.
Как бы там не перемешалось всё это поточное дело?
Еще не понятно как обрабатывать от какого потока пришёл BroadcastReceiver?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы