向不在前台的 Activity 发送广播
Send a broadcast to an Activity that is not in the foreground
我有一个带有倒数计时器的后台服务。当 CountdownTimer 倒计时时,我向 Activity 发送广播。当 CountdownTimer 倒计时时,Activity 会收到警报,我可以停止服务并注销接收器。
我已经将普通的接收器注销方法从 onStop 和 onPause 移动到我自己的方法中,一旦使用 "timer_finished" 接收到广播,我就会调用该方法。这样我就可以在不注销的情况下离开 Activity。
如果用户当前正在查看 Activity,一切正常。如果用户离开 Activity,CoundownTimer 仍然是 运行 但 Activity 没有收到广播。
我怎样才能让 Activity 收到最后的广播 "timer_finished"?
public class CountDownBroadcastService extends Service {
private static final String TAG = CountDownBroadcastService.class.getSimpleName();
public static final String COUNTDOWN_BR = "com.carefreegroup.rr3.countdown_br";
Intent bi = new Intent(COUNTDOWN_BR);
CountDownTimer cdt = null;
Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
Log.i(TAG, "Starting timer...");
cdt = new CountDownTimer(10000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
Log.i(TAG, "Countdown seconds remaining: " + millisUntilFinished / 1000);
bi.putExtra("countdown", millisUntilFinished);
bi.putExtra("timer_status", "timer_not_finished");
sendBroadcast(bi);
}
@Override
public void onFinish() {
Log.i(TAG, "Timer finished");
bi.putExtra("timer_status", "timer_finished");
sendBroadcast(bi);
}
};
cdt.start();
}
@Override
public void onDestroy() {
cdt.cancel();
Log.i(TAG, "Timer cancelled");
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
}
.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e(TAG, "start of oncreate");
setContentView(R.layout.loneworker);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setIcon(R.drawable.ic_launcher);
setTitle("Lone Worker");
nfcscannerapplication = (NfcScannerApplication) getApplication();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
tvCountDown = (TextView)findViewById(R.id.tvloneworkercountdown);
callFinished = (Button)findViewById(R.id.buttonlwcallfinished);
callFinished.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "inside callFinished");
//maybe alert carer is safe***************************************
setCountDownFinished();
}
});
startService(new Intent(this, CountDownBroadcastService.class));
Log.i(TAG, "Started service");
}//end of onCreate
private BroadcastReceiver br = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateGUI(intent); // or whatever method used to update your GUI fields
}
};
public void onResume() {
super.onResume();
registerReceiver(br, new IntentFilter(CountDownBroadcastService.COUNTDOWN_BR));
Log.i(TAG, "Registered broacast receiver");
}
private void updateGUI(Intent intent) {
if (intent.getExtras() != null) {
long millisUntilFinished = intent.getLongExtra("countdown", 0);
//Log.i(TAG, "Countdown seconds remaining: " + millisUntilFinished / 1000);
String status = intent.getStringExtra("timer_status");
if(status.equalsIgnoreCase("timer_not_finished")){
tvCountDown.setText("Countdown seconds remaining: " + millisUntilFinished / 1000);
}else if(status.equalsIgnoreCase("timer_finished")){
setCountDownFinished();
}
}
}//end of updateGUI
public void setCountDownFinished(){
tvCountDown.setText("0");
unregisterReceiver(br);
Log.i(TAG, "Unregistered broacast receiver");
stopService(new Intent(this, CountDownBroadcastService.class));
Log.e(TAG, "Stopped CountDownBroadcastService");
}// end of setCountDownFinished()
}
When you register a broadcast receiver programmatically in an
activity, it will not get broadcasts when the activity is paused. The
BroadcastReceiver docs are not as clear as they could be on this
point. They recommend unregistering on onPause solely to reduce system
overhead.
If you want to receive events even when your activity is not in the foreground, register the receiver in your manifest using the
receiver element.
我有一个带有倒数计时器的后台服务。当 CountdownTimer 倒计时时,我向 Activity 发送广播。当 CountdownTimer 倒计时时,Activity 会收到警报,我可以停止服务并注销接收器。
我已经将普通的接收器注销方法从 onStop 和 onPause 移动到我自己的方法中,一旦使用 "timer_finished" 接收到广播,我就会调用该方法。这样我就可以在不注销的情况下离开 Activity。
如果用户当前正在查看 Activity,一切正常。如果用户离开 Activity,CoundownTimer 仍然是 运行 但 Activity 没有收到广播。
我怎样才能让 Activity 收到最后的广播 "timer_finished"?
public class CountDownBroadcastService extends Service {
private static final String TAG = CountDownBroadcastService.class.getSimpleName();
public static final String COUNTDOWN_BR = "com.carefreegroup.rr3.countdown_br";
Intent bi = new Intent(COUNTDOWN_BR);
CountDownTimer cdt = null;
Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
Log.i(TAG, "Starting timer...");
cdt = new CountDownTimer(10000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
Log.i(TAG, "Countdown seconds remaining: " + millisUntilFinished / 1000);
bi.putExtra("countdown", millisUntilFinished);
bi.putExtra("timer_status", "timer_not_finished");
sendBroadcast(bi);
}
@Override
public void onFinish() {
Log.i(TAG, "Timer finished");
bi.putExtra("timer_status", "timer_finished");
sendBroadcast(bi);
}
};
cdt.start();
}
@Override
public void onDestroy() {
cdt.cancel();
Log.i(TAG, "Timer cancelled");
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
}
.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e(TAG, "start of oncreate");
setContentView(R.layout.loneworker);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setIcon(R.drawable.ic_launcher);
setTitle("Lone Worker");
nfcscannerapplication = (NfcScannerApplication) getApplication();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
tvCountDown = (TextView)findViewById(R.id.tvloneworkercountdown);
callFinished = (Button)findViewById(R.id.buttonlwcallfinished);
callFinished.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "inside callFinished");
//maybe alert carer is safe***************************************
setCountDownFinished();
}
});
startService(new Intent(this, CountDownBroadcastService.class));
Log.i(TAG, "Started service");
}//end of onCreate
private BroadcastReceiver br = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateGUI(intent); // or whatever method used to update your GUI fields
}
};
public void onResume() {
super.onResume();
registerReceiver(br, new IntentFilter(CountDownBroadcastService.COUNTDOWN_BR));
Log.i(TAG, "Registered broacast receiver");
}
private void updateGUI(Intent intent) {
if (intent.getExtras() != null) {
long millisUntilFinished = intent.getLongExtra("countdown", 0);
//Log.i(TAG, "Countdown seconds remaining: " + millisUntilFinished / 1000);
String status = intent.getStringExtra("timer_status");
if(status.equalsIgnoreCase("timer_not_finished")){
tvCountDown.setText("Countdown seconds remaining: " + millisUntilFinished / 1000);
}else if(status.equalsIgnoreCase("timer_finished")){
setCountDownFinished();
}
}
}//end of updateGUI
public void setCountDownFinished(){
tvCountDown.setText("0");
unregisterReceiver(br);
Log.i(TAG, "Unregistered broacast receiver");
stopService(new Intent(this, CountDownBroadcastService.class));
Log.e(TAG, "Stopped CountDownBroadcastService");
}// end of setCountDownFinished()
}
When you register a broadcast receiver programmatically in an activity, it will not get broadcasts when the activity is paused. The BroadcastReceiver docs are not as clear as they could be on this point. They recommend unregistering on onPause solely to reduce system overhead. If you want to receive events even when your activity is not in the foreground, register the receiver in your manifest using the receiver element.