Android 如何在广播接收器中更新UI

Android 如何在广播接收器中更新UI,android,broadcastreceiver,Android,Broadcastreceiver,我创建了一个应用程序,其中我在主类(main Activity)中注册了一个广播接收器,每当我在我的BroadcastReceiver中收到某个内容时,我都想更新其UI,例如,我想显示一个警报框或设置我的main Activity的一些文本视图。我在接收器中接收到所有值,但无法设置它们,有人能帮我更新BroadcastReceiver中的UI吗 我的BroadcastReceiver类是MainActivity的内部类,如下所示:- public class MainActivity exten

我创建了一个应用程序,其中我在主类(
main Activity
)中注册了一个广播接收器,每当我在我的
BroadcastReceiver
中收到某个内容时,我都想更新其UI,例如,我想显示一个警报框或设置我的
main Activity
的一些文本视图。我在接收器中接收到所有值,但无法设置它们,有人能帮我更新
BroadcastReceiver
中的UI吗

我的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();
        }
    }
}
任何帮助都是值得的


谢谢

使用
runOnUiThread

 MainActivity.this.runOnUiThread(new Runnable() {

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

        }
    });

我使用的是完全不同的方法。通过将处理程序的实例放入intent中,将其传递给广播接收器。广播接收器使用该处理程序向活动类发送消息,该类将更新自定义处理程序类的onHandleMessage方法中的UI

create handler class like

   public class MyHandler extends Handler{

onHandlerMessage(Message msg){//do whatever you want here after broadcast get fired}
}
现在使用
Myhandler=newmyhandler()在活动的全局级别作用域上创建此处理程序对象

现在通过
putExtra
将此处理程序放入您的intent中,然后通过
sendBraodcast(intent)
发送此intent

在broadcast receiver类中,通过getExtras获取这个处理程序对象,并使用它,如下所示 在
onReceive()
方法中

 handler.sendEmptyMessage();

我建议你用一个处理器

  • 在活动中初始化处理程序,例如:
    Handler=newhandler()
  • 在构造函数中向BroadcastReceiver提供处理程序,方法与我在上面为NissanTabBroadcast所做的相同
  • onReceive()
    方法中使用处理程序实例的
    post()
    方法提交更新UI的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();
                    }
                });
            }
        }
    }
    

    我使用意图让广播接收器知道主活动线程的处理程序实例,并使用消息将消息传递给主活动

    我已经使用这种机制来检查广播接收器是否已经注册。有时,当您动态注册广播接收器且不想重复注册两次或在广播接收器正在运行时向用户演示时,需要使用该选项

    主要活动:

    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();
            }
        }
        .........
    
    }
    
    }
    
    我使用了Handler及其post()方法。而不是runOnUiThread()。无需将上下文强制转换为活动。它是runOnUiThread()的另一种选择


    在我的情况下,我想用传入的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");
    
    不确定它是否有帮助,但肯定会引导你达到你想要的


    干杯

    我的案例是更新MainActivity托管的一个片段中的textfield。我找到的最简单的解决方案是:--

    在my MainActivity类中,检索了MainActivityy的运行实例。这是我的MainActivity

    private static MainActivity mainActivityRunningInstance;
        public static MainActivity  getInstace(){
            return mainActivityRunningInstance;
        }
      @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mainActivityRunningInstance =this;
    ----------
    }
    
    现在在Broadcast Receiver的onReceive方法中,获取该实例并调用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中运行更新的部分,MainActivity的updateUI方法将调用片段更新方法

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

    宾果游戏,结束了。我引用link来解决我的问题。希望对其他人有所帮助。

    您应该将广播接收器设置为内部类,这样它就可以访问所有字段以更新UI

    查看nick butcher的格子布应用程序
    使用getter和setter可以轻松解决此问题

    只需声明一个类,如下所示

    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(视图)

    在广播接收器上,获取视图为
    newdetailsinstance.getview(视图)

    下面的代码可用于从片段获取视图,并使用setText等更新Ui

    要更新主活动上的UI,请传递Textview并更改DeailsGetters类,并为Textview创建getter和setter。希望这对其他人有所帮助。

    如何在任何活动中重复使用BroadcastReceiver?
    考虑以下情况,

    • 您想在不同的模式下使用相同的
      BroadcastReceiver
      活动
    • 您已将
      BroadcastReceiver
      写入一个单独的文件,并希望访问
      Activity
      方法、UI元素等
    在这些情况下,使用接口是一个好主意。我将更详细地解释优势和用例。但首先,让我们看看它是如何完成的

    1)创建一个接口

    public interface MyBroadcastListener{
    
        public void doSomething(String value);
    
    }
    
    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");
    
        }
    }
    
    2)初始化广播接收器中的侦听器

    public interface MyBroadcastListener{
    
        public void doSomething(String value);
    
    }
    
    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获取结果的活动 然后开始一个详细的活动

    请注意,这是一个完全 不同的任务,但您可以使用相同的广播接收器,甚至不需要 广播接收器内的任何代码更改

    怎么做?
    简单!在
    活动中实现接口
    并重写该方法。就这样

    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
          }
    
    }
    

    通过广播接收器在UI中获取当前日期、时间、秒和更新

        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>
    
    package com.keshav.broadcasttest;
    导入java.util.Date;
    导入android.app.Service;
    导入android.content.Intent;
    导入android.os.Handler;
    导入android.os.IBinder;
    导入android.util.Log;
    公营班