Как Использовать Широковещательный Приемник Для Отправки Команд Объектам В Макете?

#java #android

Вопрос:

Я использую сервис и широковещательный приемник. Когда служба запускается, она помещает уведомление в центр уведомлений пользователя, которое возвращает START_STICKY. Я добавил в это уведомление кнопку действия, которая остановит службу. Эта часть работает нормально, но у меня также есть объект switch на моем activity_main.xml макет, который я хочу, чтобы он снимал флажок, когда пользователь нажимает на эту кнопку действия, чтобы остановить службу, если у пользователя все еще открыт этот макет, и в фокусе на экране в то время, когда он нажимал на эту кнопку действия.

Я думал, что решение было таким же простым, как использование LayoutInflater, но оно не работает для меня.

Вот что я попробовал… Я поместил следующий код в метод onReceive в своем классе широковещательного приемника. Все остальное, что у меня есть в этом методе, работает нормально, за исключением этой части, о которой идет речь.

 LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.activity_main, null);
Switch sw = (Switch) v.findViewById(R.id.mySwitch);
sw.setChecked(false);
 

Вы могли бы подумать, что это сработает. Я говорю ему, чтобы он посмотрел на определенный макет, а затем я сказал ему выполнить команду «Снять флажок» для объекта switch, существующего на этом макете, с помощью кнопки «Действие» в уведомлении. Он не получает команду.

Есть какие-нибудь идеи? Я ценю вашу помощь!!

[введите описание изображения здесь] (https://i.stack.imgur.com/8UKu6.jpg)

Если это поможет, мой проект можно скачать здесь… введите описание ссылки здесь

Вот мои новые изменения…

Класс широковещательного приемника

 public static String ACTION_TURN_OFF_THE_LIGHTS = "com.mathiasapps.lightsonexample.action.TURN_OFF_THE_LIGHTS";


Intent actionStopIntent = new Intent(this, actionTurnOffReceiver.class);
        actionStopIntent.setAction(ACTION_TURN_OFF_THE_LIGHTS);
        PendingIntent actionStopPI = PendingIntent.getBroadcast(this, 0, actionStopIntent, PendingIntent.FLAG_UPDATE_CURRENT);
 

Класс основной активности

 @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        IntentFilter filter = new IntentFilter(ACTION_TURN_OFF_THE_LIGHTS);
        registerReceiver(receiver, filter);

 
     private final MyActivityReceiver receiver = new MyActivityReceiver();

    @SuppressLint("UseSwitchCompatOrMaterialCode")
    public Switch sw;


    class MyActivityReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            @SuppressLint("UseSwitchCompatOrMaterialCode")
            Switch sw = findViewById(R.id.lights_on_switch);
            sw.setChecked(false);
        }
    }
 

Комментарии:

1. может быть, в основной активности поставьте приемник и снимите его. Я думаю, что это не приведет к тому, что тот, который уже запущен

2. Это круто, если это невозможно сделать таким образом. Просто мне нравится, чтобы мои проекты были как можно более удобными для пользователей.

3. Пользователь не увидит ваш код. Поместите другого получателя в действие, использующее этот xml, и поместите veiw в var и выключите его, я думаю, это должно сработать. Другое действие может вызвать намерение, если оно имеет слишком

4. ОК. Итак, onReceive, о котором я говорил в своем вопросе, должен отправить команду, и onReceive, о котором вы упомянули, получит эту команду в классе MainActivity, который должен отключить этот переключатель?

5. да, я так думаю.

Ответ №1:

Вот что я попробовал… Я поместил следующий код в метод onReceive в своем классе широковещательного приемника. Все остальное, что у меня есть в этом методе, работает нормально, за исключением этой части, о которой идет речь.

Надуватель LayoutInflater = (надуватель LayoutInflater) контекст.getSystemService(контекст.LAYOUT_INFLATER_SERVICE); Представление v = inflater.inflate(R. layout.activity_main, null); Переключатель sw = (Переключатель) v. findViewById(R. id.mySwitch); sw.Установлен(false);

Вы могли бы подумать, что это сработает.

Нет, ты бы этого не сделал.

Я говорю ему, чтобы он посмотрел на определенный макет, а затем я сказал ему выполнить команду «Снять флажок» для объекта switch, существующего на этом макете, с помощью кнопки «Действие» в уведомлении.

Нет, это не так.

Ваша Проблема

Вы раздуваете совершенно новый экземпляр своего основного макета активности, находите переключатель в этом макете и устанавливаете этот переключатель, который НЕ является переключателем в вашей деятельности, на непроверенный. Делая это, вы не касаетесь своего фактического плана действий.

Решение

Вам необходимо зарегистрировать приемник широковещательной передачи в Действии, чтобы фактический запущенный экземпляр Действия мог принимать широковещательную передачу и переключать переключатель, который он содержит. Пример см. в документации.

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

 class MyActivity {
    // The receiver that will listen for the "off" broadcast
    class MyActivityReceiver : BroadcastReceiver {
        // When this receiver gets notified, call the owning activity's method
        void onReceive(Intent intent) {
            turnOffToggle();
        }
    }

    private final MyActivityReceiver receiver = new MyActivityReceiver();

    protected void onCreate(...) {
        super.onCreate(...)

        // Register the receiver so we get notified while this activity is active
        IntentFilter filter = // create filter for your broadcast intent
        registerReceiver(receiver, filter);
    }

    proteced void onDestroy() {
        // Stop listening once we're killed
        unregisterReceiver(receiver);
    }

    private void turnOffToggle() {
        // Find the switch in THIS active Activity's layout
        Switch sw = (Switch) findViewById(R.id.mySwitch);
        sw.setChecked(false);
    }
}
 

Редактировать после вопросов:

1 — когда вы настраиваете действие, вы нацеливаетесь на локального получателя службы с вашим намерением:

 // Will only invoke `actionTurnOffReceiver` declared in the service.
Intent actionStopIntent = new Intent(this, actionTurnOffReceiver.class);
 

Вам нужно более общее намерение, которое может прослушивать любой получатель (т. Е. тот, кто участвует в действии).

 // ACTION_TURN_OFF_THE_LIGHTS is some string like "com.my.package.action.TURN_OFF_THE_LIGHTS"
Intent actionStopIntent = new Intent(this, ACTION_TURN_OFF_THE_LIGHTS)
 

2 — Ваша регистрация активности слишком универсальна:

 // This is blindly registering for all broadcasts - or Android will just ignore it
IntentFilter filter = new IntentFilter();
registerReceiver(receiver, filter);
 

Как показано в примере в документации, на которую я ссылался, вы должны настроить свой фильтр в соответствии с интересующими вас целями. В данном случае это для действия «выключить» :

 IntentFilter filter = new IntentFilter(ACTION_TURN_OFF_THE_LIGHTS);
registerReceiver(receiver, filter);
 

Пожалуйста, просмотрите весь раздел о трансляциях, чтобы лучше понять, как они работают. А вот статья среднего уровня, посвященная радиовещательным приемникам.

Комментарии:

1. Спасибо, но это тоже не сработало для меня.

2. Я просто буду считать, что это невозможно.

3. Это определенно возможно, используя описанный мной шаблон. «Это не сработало» не говорит мне, что вы на самом деле сделали и как выглядит ваш код. Обновите свой вопрос или задайте новый с четкой информацией о том, что вы пытаетесь сделать и что происходит.

4. Я добавил ссылку на скачивание своего проекта к этому вопросу.

5. Спасибо, что уделили мне время. Я не понимал, что это более сложная проблема, чем то, чего она стоит для моего уровня в программировании. Это просто слишком сложно для меня, и я этого не понимаю. Я просто пропущу это. Остальная часть проекта работает так, как задумано.