Подтвердить что ты не робот

Как обновить пользовательский интерфейс в 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();
        }
    }
}

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

Спасибо

4b9b3361

Ответ 1

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

  • Инициализировать обработчик в Activity, например: handler = new Handler()
  • Предоставить обработчик BroadcastReceiver в конструкторе, так же, как и для NissanTabBroadcast выше
  • Используйте метод post() экземпляра Handler в методе 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();
                }
            });
        }
    }
}

Ответ 2

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

В моем классе MainActivity был загружен исполняемый экземпляр MainActivtiy.Это мой MAinActivity

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

Теперь в приемнике Broadcast onRecieve, получите этот экземпляр и вызовите метод обновления

 @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);
    }

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

Ответ 3

Используйте runOnUiThread:

 MainActivity.this.runOnUiThread(new Runnable() {

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

        }
    });

Ответ 4

Я использую совершенно другой подход для этого. Проведите экземпляр обработчика для вещания приемника, поставив его в намерение. В широковещательном приемнике этот обработчик использовал для отправки сообщения вашему классу активности, который обновляет пользовательский интерфейс в вашем методе 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(); создайте этот объект-обработчик в области глобального уровня в активности.

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

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

 handler.sendEmptyMessage();

Ответ 5

Я использовал Intent, чтобы позволить Broadcast Receiver узнать о экземпляре Handler основного потока 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();
        }
    }
    .........

}

}

Ответ 6

В моем случае я хочу обновить свое текстовое представление в своей деятельности с помощью входящих 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);    

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

Bundle extras = getIntent().getExtras();
String message = extras.getString("pinbody");

Не уверен, что это поможет, но определенно приведет вас к тому, что вы хотите.

Приветствия!

Ответ 7

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

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

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);

Описание может использоваться для получения представления из фрагмента и обновления Ui с использованием setText и т.д.

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

Ответ 8

Как повторно использовать BroadcastReceiver в любой деятельности?

enter image description here
Рассмотрим ситуации, когда

  • Вы хотите использовать один и тот же BroadcastReceiver в разных действиях
  • Вы написали BroadcastReceiver в отдельном файле и хотите получить доступ к методам Activity, элементам пользовательского интерфейса и т.д.

В этих случаях использование интерфейса - отличная идея. Я объясню преимущество и пример использования более подробно. Но сначала давайте посмотрим, как это делается.

1) Создать интерфейс

public interface MyBroadcastListener{

    public void doSomething(String value);

}

2) Инициализируйте прослушиватель в вашем BroadcastReceiver

public class MyReceiver extends BroadcastReceiver {

    private MyBroadcastListener listener;

    public MyReceiver(MyBroadcastListener listener){
        this.listener = listener;
    }

    @Override
    public void onReceive(Context context, Intent intent) {

        listener.doSomething("Some Result");

    }
}

3) Реализуйте интерфейс в своей деятельности и переопределите метод

 public MainActivity extends AppCompatActivity implements MyBroadcastListener{

      private BroadcastReceiver receiver;

      @Override
      public void onCreate(Bundle sis){

           // Related code 

           receiver = new MyReceiver(this);   // This is how you initialise receiver

          // Register receiver etc
      }


      public void updateUI(String msg) {
           TextView textView = (TextView) findViewById(R.id.textView);
           textView .setText(msg);
      }

      @Override
      public void doSomething(String result){
           updateUI(result);        // Calling method from Interface
      }

 }

Преимущество и вариант использования?

Использование интерфейсного подхода делает BroadcastReceiver независимым от любого действия. Допустим, в будущем вы хотите использовать этот BroadCastReceiver с другим действием, которое берет результат из BroadcastReceiver и запускает DetailActivity.

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

Как это сделать?
Просто! Реализуйте интерфейс в Activity и переопределите метод. Это!

public ListActivity extends AppCompatActivity implements MyBroadcastListener{

      // Your Activity code goes here

     public void startDetailActivity(String title) {
         Intent i = new Intent(ListActivity,this, DetailActivity.class);
         i.putExtra("Title", title);
         startActivity(i);
     }

      @Override
      public void doSomething(String result){
           startDetailActivity(String title);    // Calling method from Interface
      }

}

enter image description here

Ответ 9

Я использовал Handler и его метод 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();

Ответ 10

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

Посмотрите это приложение Plaid от майора Plaid-Nick Butcher (Github)

Ответ 11

Получить текущую дату, время и секунды и обновить в интерфейсе через широковещательный приемник

    package com.keshav.broadcasttest;

    import java.util.Date;

    import android.app.Service;
    import android.content.Intent;
    import android.os.Handler;
    import android.os.IBinder;
    import android.util.Log;

    public class BroadcastService  extends Service {
       private static final String TAG = "BroadcastService";
       public static final String BROADCAST_ACTION = "com.keshav.broadcasttest.displayevent";
       private final Handler handler = new Handler();
       Intent intent;
       int counter = 0;

       @Override
       public void onCreate() {
          super.onCreate();

           intent = new Intent(BROADCAST_ACTION); 
       }

        @Override
        public void onStart(Intent intent, int startId) {
            handler.removeCallbacks(sendUpdatesToUI_Runnable);
            handler.postDelayed(sendUpdatesToUI_Runnable, 1000); // 1 second

        }

        private Runnable sendUpdatesToUI_Runnable = new Runnable() {
           public void run() {
              DisplayLoggingInfo();         
               handler.postDelayed(this, 10000); // 10 seconds
           }
        };    

        private void DisplayLoggingInfo() {
           Log.d(TAG, "entered DisplayLoggingInfo");

           intent.putExtra("time", new Date().toLocaleString());
           intent.putExtra("counter", String.valueOf(++counter));
           sendBroadcast(intent);
        }

       @Override
       public IBinder onBind(Intent intent) {
          return null;
       }

       @Override
       public void onDestroy() {     
            handler.removeCallbacks(sendUpdatesToUI_Runnable);
          super.onDestroy();
       }     
    }
    ============================================

    package com.keshav.broadcasttest;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class BroadcastTest extends Activity {
    private static final String TAG = "BroadcastTest";
    private Intent intent;

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

        intent = new Intent(this, BroadcastService.class);
    }

    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            updateUI(intent);       
        }
    };    

    @Override
    public void onResume() {
        super.onResume();       
        startService(intent);
        registerReceiver(broadcastReceiver, new IntentFilter(BroadcastService.BROADCAST_ACTION));
    }

    @Override
    public void onPause() {
        super.onPause();
        unregisterReceiver(broadcastReceiver);
        stopService(intent);        
    }   

    private void updateUI(Intent intent) {
        String counter = intent.getStringExtra("counter"); 
        String time = intent.getStringExtra("time");
        Log.d(TAG, counter);
        Log.d(TAG, time);

        TextView txtDateTime = (TextView) findViewById(R.id.txtDateTime);   
        TextView txtCounter = (TextView) findViewById(R.id.txtCounter);
        txtDateTime.setText(time);
        txtCounter.setText(counter);
    }
}
    =============================

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
        <TableLayout android:id="@+id/tableGPS"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="7px"
            android:stretchColumns="1">
            <TableRow
                android:layout_margin="1dip">
                <TextView android:layout_gravity="right"
                    android:text="Time:"
                    android:layout_marginRight="7px"
                    android:layout_width="130px" />
                <TextView android:id="@+id/txtDateTime"
                    android:gravity="left"
                    android:layout_span="2" />
            </TableRow>
            <TableRow
                android:layout_margin="1px">
                <TextView android:layout_gravity="right"
                    android:text="Counter:"
                    android:layout_marginRight="7px"
                    android:layout_width="160px" />
                <TextView android:id="@+id/txtCounter"
                    android:gravity="left" />
            </TableRow>
        </TableLayout>
    </LinearLayout>

    ===========================================

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.keshav.broadcasttest">

        <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">
            <activity android:name=".BroadcastTest">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />

                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>

            <service android:name=".BroadcastService" />
        </application>

    </manifest>