web-dev-qa-db-ja.com

BroadcastReceiverでUIを更新する方法

メインクラス内にブロードキャストレシーバーを登録するアプリケーションを作成しました(Main ActivityBroadcastReceiverで何かを受け取ったときはいつでも、たとえば警告ボックスを表示したり、MainActivityのテキストビューを設定したい。レシーバーですべての値を受け取りましたが、それらを設定できません。誰かが私を助けて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();
        }
    }
}

どんな助けも認められます

ありがとう

22
Salman Khan

ハンドラーを使用することをお勧めします。

  1. アクティビティのハンドラーを初期化します。例:handler = new Handler()
  2. 上記のNissanTabBroadcastで行ったのと同じ方法で、コンストラクターでBroadcastReceiverにハンドラーを提供します
  3. post()メソッドでHandlerインスタンスのonReceive()メソッドを使用して、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();
                }
            });
        }
    }
}
32
allprog

私の場合は、MainActivityがホストするフラグメントの1つのテキストフィールドを更新することでした。

MainActivityクラスで、MainActivtiyの実行中のインスタンスを取得しました。これが私のMAinActivityです。

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で更新を実行する必要がある部分については、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);
    }

そしてビンゴ、完了です。 this リンクを参照して問題を解決しました。それが他の人を助けることを願っています。

8
Nicks

runOnUiThreadを使用:

 MainActivity.this.runOnUiThread(new Runnable() {

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

        }
    });
6
Nermeen

BroadcastReceiverをアクティビティで再利用する方法は?

enter image description here
次のような状況を検討します、

  • 異なるアクティビティで同じBroadcastReceiverを使用したい
  • 別のファイルにBroadcastReceiverを記述し、Activityメソッド、UI要素などにアクセスしたい.

これらの場合、インターフェースを使用することは素晴らしいアイデアです。利点とユースケースについて詳しく説明します。しかし、最初に、それがどのように行われるかを見てみましょう。

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

2
Rohit Singh

ハンドラーのインスタンスをインテントに入れて、ブロードキャストレシーバーに渡します。ブロードキャストレシーバーでは、ハンドラーを使用して、カスタムハンドラーのonHandleMessageメソッドのUIを更新するアクティビティクラスにメッセージを送信しますクラス。

_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();
_
1
kaushal trivedi

ゲッターとセッターを使用すると、この問題を簡単に解決できます。

次のようにクラスを宣言するだけです。

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

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

メインアクティビティまたはフラグメントアクティビティで、DetailsGettersクラスのインスタンスを作成します。

_DetailsGetters newdetailsinstance=new DetailsGetters();
_

ビューを呼び出す前にcallnewdetailsinstance.setview(view);

ブロードキャストレシーバーでは、ビューをnewdetailsinstance.getview(view);として取得します

以下を使用して、フラグメントからビューを取得し、setTextなどを使用してUiを更新できます。

メインアクティビティのUIを更新するには、Textviewを渡してDeailsGettersクラスを変更し、Textviewのゲッターとセッターを作成します。これが誰かに役立つことを願っています。

1
Elaiya

Intentを使用してBroadcast Receiverにメインアクティビティスレッドのハンドラーインスタンスを通知し、Messageを使用してメインアクティビティにメッセージを渡しました

このようなメカニズムを使用して、Broadcast Receiverが既に登録されているかどうかを確認しました。 Broadcast Receiverを動的に登録し、2回作成したくない場合や、Broadcast Receiverが実行されている場合にユーザーに提示する場合に必要になることがあります。

主な活動:

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

}

}
1
jarek

私の場合、着信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");

それが役立つかどうかはわかりませんが、間違いなくあなたが望むものにあなたを導くでしょう。

乾杯!

1
Srinivas Kumar

現在の日付と時刻を取得し、ブロードキャストレシーバーを介して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>
0
Keshav Gera

ブロードキャストレシーバーを内部クラスとして作成する必要があります。これにより、UIを更新するためにすべてのフィールドにアクセスできるようになります。

ニック・ブッチャーによるこのプレイド・アプリをご覧ください Plaid- Nick Butcher(Github)

0
Uzair

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();
0
Pavan Pyati