Как обновить пользовательский интерфейс в BroadcastReceiver



Я создал приложение, в котором я зарегистрировал широковещательный приемник в моем основном классе (Main Activity), и всякий раз, когда я получаю что-то в моем BroadcastReceiver, я хочу обновить пользовательский интерфейс, например, я хочу показать окно оповещения или установить некоторое текстовое представление моего MainActivity. Я получаю все значения в моем приемнике, но не могу установить их, может кто-нибудь помочь мне, чтобы я мог обновить свой пользовательский интерфейс в BroadcastReceiver.



Мой класс BroadcastReceiver является внутренним классом MainActivity следующим образом: -



public class MainActivity extends Activity {

..........

public static class NissanTabBroadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
SharedPreferences shrd = context.getSharedPreferences("NissanGallery", context.MODE_WORLD_READABLE);
type = shrd.getString("type", "null");
badges = shrd.getString("badge_count", "null");

//badge_tips_text.setText(badges);
/*Editor edit = shrd.edit();
edit.remove("type");*/

Toast.makeText(context, "" + type + "n" + badge_tips_text.getText().toString(), Toast.LENGTH_LONG).show();
}
}
}


Любая помощь будет заметно



Спасибо

417   9  

9 ответов:

Я предлагаю вам использовать обработчик.

  1. инициализировать обработчик в действии, Пример: handler = new Handler()
  2. снабдите обработчик BroadcastReceiver в конструкторе, таким же образом, как я сделал для NissanTabBroadcast выше
  3. Используйте метод post() вашего экземпляра обработчика в методе onReceive() для отправки Runnable, обновляющего пользовательский интерфейс
Это самое чистое решение, которое я могу себе представить.
public class MainActivity extends Activity {

    private MyReceiver receiver;

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

        receiver = new MyReceiver(new Handler()); // Create the receiver
        registerReceiver(receiver, new IntentFilter("some.action")); // Register receiver

        sendBroadcast(new Intent("some.action")); // Send an example Intent
    }

    public static class MyReceiver extends BroadcastReceiver {

        private final Handler handler; // Handler used to execute code on the UI thread

        public MyReceiver(Handler handler) {
            this.handler = handler;
        }

        @Override
        public void onReceive(final Context context, Intent intent) {
            // Post the UI updating code to our Handler
            handler.post(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(context, "Toast from broadcast receiver", Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
}

Мой случай состоял в том, чтобы обновить текстовое поле в одном из фрагментов, размещенных MainActivity.Самое простое решение, которое я нашел, было таково: --

В моем классе MainActivity извлек запущенный экземпляр MainActivtiy.Это моя основная активность

private static MainActivity mainActivityRunningInstance;
    public static MainActivity  getInstace(){
        return mainActivityRunningInstance;
    }
  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mainActivityRunningInstance =this;
----------
}

Теперь в методе Onrecieve широковещательного получателя получите этот экземпляр и вызовите метод update

 @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().matches(Intents.PROVIDER_CHANGED_ACTION)) {
                String textValue="the text field value";
// the null check is for, if the activity is not running or in paused state, in my case the update was required onlyif the main activity is active or paused
            if(MainActivity.getInstace()!=null)
                MainActivity.getInstace().updateUI(textValue);
}

Теперь для части, где нам нужно запустить обновление в UIThread, метод updateUI MainActivity вызовет обновление фрагментов метод.

  public void updateUI(final String str) {
        MainActivity.this.runOnUiThread(new Runnable() {
            public void run() {
     //use findFragmentById for fragments defined in XML ((SimpleFragment)getSupportFragmentManager().findFragmentByTag(fragmentTag)).updateUI(str);
            }
        });
    }

И последний шаг-обновление текстового поля фрагмента

public void updateUI(String str){
        tv_content.setText(str);
    }

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

Использовать runOnUiThread:

 MainActivity.this.runOnUiThread(new Runnable() {

        @Override
        public void run() {
            // show alert

        }
    });

Я использовал Intent, чтобы сообщить Широковещательному приемнику об экземпляре обработчика потока main Activity, и использовал Message для передачи сообщения в Main activity

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

Основная деятельность:

public class Example extends Activity {

private BroadCastReceiver_example br_exemple;

final Messenger mMessenger = new Messenger(new IncomingHandler());

private boolean running = false;

static class IncomingHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        running = false;    
        switch (msg.what) {
        case BroadCastReceiver_example.ALIVE:
    running = true;
            ....
            break;
        default:

            super.handleMessage(msg);
        }

    }
    }

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    IntentFilter filter = new IntentFilter();
        filter.addAction("pl.example.CHECK_RECEIVER");

        br_exemple = new BroadCastReceiver_example();
        getApplicationContext().registerReceiver(br_exemple , filter); //register the Receiver
    }

// call it whenever you want to check if Broadcast Receiver is running.

private void check_broadcastRunning() {    
        /**
        * checkBroadcastHandler - the handler will start runnable which will check if Broadcast Receiver is running
        */
        Handler checkBroadcastHandler = null;

        /**
        * checkBroadcastRunnable - the runnable which will check if Broadcast Receiver is running
        */
        Runnable checkBroadcastRunnable = null;

        Intent checkBroadCastState = new Intent();
        checkBroadCastState .setAction("pl.example.CHECK_RECEIVER");
        checkBroadCastState .putExtra("mainView", mMessenger);
        this.sendBroadcast(checkBroadCastState );
        Log.d(TAG,"check if broadcast is running");

        checkBroadcastHandler = new Handler();
        checkBroadcastRunnable = new Runnable(){    

            public void run(){
                if (running == true) {
                    Log.d(TAG,"broadcast is running");
                }
                else {
                    Log.d(TAG,"broadcast is not running");
                }
            }
        };
        checkBroadcastHandler.postDelayed(checkBroadcastRunnable,100);
        return;
    }

.............
}

Широковещательный Приемник:

public class BroadCastReceiver_example extends BroadcastReceiver {


public static final int ALIVE = 1;
@Override
public void onReceive(Context context, Intent intent) {
    // TODO Auto-generated method stub
    Bundle extras = intent.getExtras();
    String action = intent.getAction();
    if (action.equals("pl.example.CHECK_RECEIVER")) {
        Log.d(TAG, "Received broadcast live checker");
        Messenger mainAppMessanger = (Messenger) extras.get("mainView");
        try {
            mainAppMessanger.send(Message.obtain(null, ALIVE));
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    .........

}

}

Я использую для этого совершенно другой подход.Передайте экземпляр обработчика широковещательному приемнику, поместив его в intent.Чем в broadcast receiver используется этот обработчик для отправки сообщения в класс activity, который обновляет пользовательский интерфейс в методе onHandleMessage вашего пользовательского класса обработчика.

create handler class like

   public class MyHandler extends Handler{

onHandlerMessage(Message msg){//do whatever you want here after broadcast get fired}
}

Теперь используйте Myhandler handler=new MyHandler(); создать этот объект обработчика на глобальном уровне области в activity.

Теперь поместите этот обработчик в ваше намерение с помощью putExtra , а затем отправьте это намерение через sendBraodcast(intent).

В классе широковещательного приемника получить этот объект обработчика getExtras и использовать его, как показано ниже в onReceive() методе

 handler.sendEmptyMessage();

В моем случае я хочу обновить свой textview в моей деятельности с входящим sms, что я сделал, добавил необходимую информацию с помощью putextra, а затем начал работу с широковещательного приемника:

Intent intentone = new Intent(context.getApplicationContext(), enroll.class);
intentone.putExtra("pinbody",message);
intentone.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intentone);    

А затем на приемной стороне, т. е. в процессе регистрации, я извлек эту информацию, используя нижеприведенное, и обновил свой textview:

Bundle extras = getIntent().getExtras();
String message = extras.getString("pinbody");
Не уверен, что это поможет, но определенно приведет вас к тому, чего вы хотите .

Ура !

Использование геттеров и сеттеров может легко решить эту проблему.

Просто объявите класс следующим образом.

public class DetailsGetters {
    private View view;
    public View getview() {
        return view;
    }

    public void setview(View view) {
        this.view = view;
    }
}

На вашем основном действии или фрагменте действия создайте экземпляр класса DetailsGetters.

DetailsGetters newdetailsinstance=new DetailsGetters();

Перед повторным вызовом видаnewdetailsinstance.setview(view);

На широковещательном приемнике получаем вид как newdetailsinstance.getview(view);

Follwing можно использовать для получения представления из фрагмента и обновления пользовательского интерфейса с помощью setText и так далее..

Для обновления пользовательского интерфейса по основной деятельности передайте Textview и измените класс DeailsGetters и создайте геттеры и сеттеры для Textview. Надеюсь, это кому-то поможет.

Я использовал метод Handler & its post (). Вместо runOnUiThread (). Нет необходимости создавать контекст для деятельности. Это альтернатива для runOnUiThread ()

Handler handler = new Handler();
Runnable runnable = new Runnable() {
    private long startTime = System.currentTimeMillis();
    public void run() {
        while (gameState == GameState.Playing) {  
            try {
                Thread.sleep(1000);
            }    
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            handler.post(new Runnable(){
                public void run() {
                   tvTime.setText("" + ((System.currentTimeMillis() - this.startTime) / 1000));
            }
        });
        }
    }
};
new Thread(runnable).start();

Вы должны сделать Broadcast receiver внутренним классом, таким образом, он будет иметь доступ ко всем полям для обновления пользовательского интерфейса.

См. этот плед приложение по нику мясника Плед-Ник Бутчер (Github)

Comments

    Ничего не найдено.