Câu trả lời:
Tôi không chắc API cung cấp trực tiếp API, nếu bạn xem xét chủ đề này :
Tôi đã tự hỏi điều tương tự.
Trong trường hợp của tôi, tôi có mộtBroadcastReceiver
triển khai gọiContext#unregisterReceiver(BroadcastReceiver)
chính nó là đối số sau khi xử lý Ý định mà nó nhận được.
Có một khả năng nhỏ làonReceive(Context, Intent)
phương thức của người nhận được gọi nhiều lần, vì nó được đăng ký với nhiềuIntentFilters
, tạo ra khả năngIllegalArgumentException
bị ném từ đóContext#unregisterReceiver(BroadcastReceiver)
.Trong trường hợp của tôi, tôi có thể lưu trữ một thành viên được đồng bộ hóa riêng tư để kiểm tra trước khi gọi
Context#unregisterReceiver(BroadcastReceiver)
, nhưng sẽ sạch hơn nhiều nếu API cung cấp phương thức kiểm tra.
Không có chức năng API để kiểm tra nếu người nhận đã đăng ký. Cách giải quyết là đặt mã của bạn vàotry catch block as done below.
try {
//Register or UnRegister your broadcast receiver here
} catch(IllegalArgumentException e) {
e.printStackTrace();
}
null
. Nhưng như bạn đã chỉ ra, tôi sẽ làm theo try catch
. Nực cười.
public class MyReceiver extends BroadcastReceiver {
public boolean isRegistered;
/**
* register receiver
* @param context - Context
* @param filter - Intent Filter
* @return see Context.registerReceiver(BroadcastReceiver,IntentFilter)
*/
public Intent register(Context context, IntentFilter filter) {
try {
// ceph3us note:
// here I propose to create
// a isRegistered(Contex) method
// as you can register receiver on different context
// so you need to match against the same one :)
// example by storing a list of weak references
// see LoadedApk.class - receiver dispatcher
// its and ArrayMap there for example
return !isRegistered
? context.registerReceiver(this, filter)
: null;
} finally {
isRegistered = true;
}
}
/**
* unregister received
* @param context - context
* @return true if was registered else false
*/
public boolean unregister(Context context) {
// additional work match on context before unregister
// eg store weak ref in register then compare in unregister
// if match same instance
return isRegistered
&& unregisterInternal(context);
}
private boolean unregisterInternal(Context context) {
context.unregisterReceiver(this);
isRegistered = false;
return true;
}
// rest implementation here
// or make this an abstract class as template :)
...
}
MyReceiver myReceiver = new MyReceiver();
myReceiver.register(Context, IntentFilter); // register
myReceiver.unregister(Context); // unregister
quảng cáo 1
- trả lời:
Điều này thực sự không thanh lịch bởi vì bạn phải nhớ đặt cờ isRegistered sau khi bạn đăng ký. - Rabbi tàng hình
- Phương thức được thêm vào "cách hợp pháp hơn" trong máy thu để đăng ký và đặt cờ
điều này sẽ không hoạt động nếu bạn khởi động lại thiết bị hoặc nếu ứng dụng của bạn bị hệ điều hành giết chết. - amin 6 giờ trước
@amin - xem thời gian tồn tại của mã (không phải hệ thống được đăng ký bởi mục nhập bảng kê khai) người nhận đã đăng ký :)
Tôi đang sử dụng giải pháp này
public class ReceiverManager {
private static List<BroadcastReceiver> receivers = new ArrayList<BroadcastReceiver>();
private static ReceiverManager ref;
private Context context;
private ReceiverManager(Context context){
this.context = context;
}
public static synchronized ReceiverManager init(Context context) {
if (ref == null) ref = new ReceiverManager(context);
return ref;
}
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter intentFilter){
receivers.add(receiver);
Intent intent = context.registerReceiver(receiver, intentFilter);
Log.i(getClass().getSimpleName(), "registered receiver: "+receiver+" with filter: "+intentFilter);
Log.i(getClass().getSimpleName(), "receiver Intent: "+intent);
return intent;
}
public boolean isReceiverRegistered(BroadcastReceiver receiver){
boolean registered = receivers.contains(receiver);
Log.i(getClass().getSimpleName(), "is receiver "+receiver+" registered? "+registered);
return registered;
}
public void unregisterReceiver(BroadcastReceiver receiver){
if (isReceiverRegistered(receiver)){
receivers.remove(receiver);
context.unregisterReceiver(receiver);
Log.i(getClass().getSimpleName(), "unregistered receiver: "+receiver);
}
}
}
Bạn có một vài lựa chọn
Bạn có thể đặt một lá cờ vào lớp học hoặc hoạt động của bạn. Đặt một biến boolean vào lớp của bạn và nhìn vào cờ này để biết bạn đã đăng ký Người nhận chưa.
Tạo một lớp mở rộng Người nhận và ở đó bạn có thể sử dụng:
Mẫu đơn chỉ có một thể hiện của lớp này trong dự án của bạn.
Thực hiện các phương pháp để biết nếu người nhận được đăng ký.
Bạn phải sử dụng thử / bắt:
try {
if (receiver!=null) {
Activity.this.unregisterReceiver(receiver);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
Bạn có thể làm điều đó dễ dàng ....
1) tạo một biến boolean ...
private boolean bolBroacastRegistred;
2) Khi bạn đăng ký Bộ thu phát sóng, hãy đặt nó thành TRUE
...
bolBroacastRegistred = true;
this.registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
....
3) Trong onPause () làm điều đó ...
if (bolBroacastRegistred) {
this.unregisterReceiver(mReceiver);
bolBroacastRegistred = false
}
Chỉ có nó và bây giờ, bạn sẽ không nhận được thêm thông báo lỗi ngoại lệ trên onPause ().
Mẹo1: Luôn sử dụng unregisterReceiver () trong onPause () không phải trong onDestroy () Tip2: Đừng quên đặt biến bolBroadcastRegistred thành FALSE khi chạy unregisterReceive ()
Sự thành công!
Nếu bạn đặt cái này vào phương thức onDestroy hoặc onStop. Tôi nghĩ rằng khi hoạt động được tạo lại, MessageReciver sẽ không được tạo.
@Override
public void onDestroy (){
super.onDestroy();
LocalBroadcastManager.getInstance(context).unregisterReceiver(mMessageReceiver);
}
Tôi đã sử dụng Ý định để cho Bộ thu phát sóng biết về phiên bản Trình xử lý của luồng Hoạt động chính và đã sử dụng Tin nhắn để truyền thông điệp đến Hoạt động chính
Tôi đã sử dụng cơ chế như vậy để kiểm tra xem Broadcast Receiver đã được đăng ký hay chưa. Đôi khi, cần thiết khi bạn đăng ký Bộ thu phát sóng một cách linh hoạt và không muốn thực hiện hai lần hoặc bạn trình bày cho người dùng nếu Bộ thu phát sóng đang chạy.
Hoạt động chủ yêu:
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;
}
.............
}
Phát sóng thu:
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();
}
}
.........
}
}
Cá nhân tôi sử dụng phương pháp gọi unregisterReceiver và nuốt ngoại lệ nếu nó bị ném. Tôi đồng ý điều này là xấu nhưng phương pháp tốt nhất hiện đang được cung cấp.
Tôi đã đưa ra một yêu cầu tính năng để có được phương thức boolean để kiểm tra xem người nhận có được đăng ký thêm vào API Android hay không. Vui lòng hỗ trợ tại đây nếu bạn muốn xem nó được thêm vào: https://code.google.com.vn/p/android/issues/detail?id=73718
Tôi nhận được vấn đề của bạn, tôi đã đối mặt với cùng một vấn đề trong Ứng dụng của tôi. Tôi đã gọi registerReceiver () nhiều lần trong ứng dụng.
Một giải pháp đơn giản cho vấn đề này là gọi registerReceiver () trong Lớp ứng dụng tùy chỉnh của bạn. Điều này sẽ đảm bảo rằng bộ thu phát của bạn sẽ chỉ được gọi là một trong toàn bộ vòng đời Ứng dụng của bạn.
public class YourApplication extends Application
{
@Override
public void onCreate()
{
super.onCreate();
//register your Broadcast receiver here
IntentFilter intentFilter = new IntentFilter("MANUAL_BROADCAST_RECIEVER");
registerReceiver(new BroadcastReciever(), intentFilter);
}
}
Đây là cách tôi đã thực hiện, đây là phiên bản sửa đổi của câu trả lời được đưa ra bởi ceph3us và được chỉnh sửa bởi slinden77 (trong số những thứ khác tôi đã xóa các giá trị trả về của các phương thức mà tôi không cần):
public class MyBroadcastReceiver extends BroadcastReceiver{
private boolean isRegistered;
public void register(final Context context) {
if (!isRegistered){
Log.d(this.toString(), " going to register this broadcast receiver");
context.registerReceiver(this, new IntentFilter("MY_ACTION"));
isRegistered = true;
}
}
public void unregister(final Context context) {
if (isRegistered) {
Log.d(this.toString(), " going to unregister this broadcast receiver");
context.unregisterReceiver(this);
isRegistered = false;
}
}
@Override
public void onReceive(final Context context, final Intent intent) {
switch (getResultCode()){
//DO STUFF
}
}
}
Sau đó, trên một lớp Activity:
public class MyFragmentActivity extends SingleFragmentActivity{
MyBroadcastReceiver myBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
registerBroacastReceiver();
}
@Override
protected Fragment createFragment(){
return new MyFragment();
}
//This method is called by the fragment which is started by this activity,
//when the Fragment is done, we also register the receiver here (if required)
@Override
public void receiveDataFromFragment(MyData data) {
registerBroacastReceiver();
//Do some stuff
}
@Override
protected void onStop(){
unregisterBroacastReceiver();
super.onStop();
}
void registerBroacastReceiver(){
if (myBroadcastReceiver == null)
myBroadcastReceiver = new MyBroadcastReceiver();
myBroadcastReceiver.register(this.getApplicationContext());
}
void unregisterReceiver(){
if (MyBroadcastReceiver != null)
myBroadcastReceiver.unregister(this.getApplicationContext());
}
}
tôi đặt mã này vào hoạt động của cha mẹ tôi
Danh sách đã đăng kýReceivers = new ArrayList <> ();
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
registeredReceivers.add(System.identityHashCode(receiver));
return super.registerReceiver(receiver, filter);
}
@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
if(registeredReceivers.contains(System.identityHashCode(receiver)))
super.unregisterReceiver(receiver);
}
Đối với tôi sau đây làm việc:
if (receiver.isOrderedBroadcast()) {
requireContext().unregisterReceiver(receiver);
}
Đây là những gì tôi đã làm để kiểm tra xem Broadcaster đã được đăng ký chưa, ngay cả khi bạn đóng ứng dụng của bạn (finish ())
Lần đầu tiên chạy ứng dụng của bạn, hãy gửi phát trước, nó sẽ trả về true / false tùy thuộc vào việc đài phát của bạn có còn chạy hay không.
Phát thanh viên của tôi
public class NotificationReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getExtras() != null && intent.getStringExtra("test") != null){
Log.d("onReceive","test");
return;
}
}
}
Chính của tôi
// init Broadcaster
private NotificationReceiver nr = new NotificationReceiver();
Intent msgrcv = new Intent("Msg");
msgrcv.putExtra("test", "testing");
boolean isRegistered = LocalBroadcastManager.getInstance(this).sendBroadcast(msgrcv);
if(!isRegistered){
Toast.makeText(this,"Starting Notification Receiver...",Toast.LENGTH_LONG).show();
LocalBroadcastManager.getInstance(this).registerReceiver(nr,new IntentFilter("Msg"));
}
Bạn có thể sử dụng Dagger để tạo một tham chiếu của người nhận đó.
Đầu tiên cung cấp nó:
@Provides
@YourScope
fun providesReceiver(): NotificationReceiver{
return NotificationReceiver()
}
Sau đó tiêm vào nơi bạn cần (sử dụng constructor
hoặc trường injection
)
và chỉ cần chuyển nó đến registerReceiver
.
Cũng đặt nó trong try/catch
khối quá.
if( receiver.isOrderedBroadcast() ){
// receiver object is registered
}
else{
// receiver object is not registered
}
Chỉ cần kiểm tra NullPulumException. Nếu máy thu không tồn tại, thì ...
try{
Intent i = new Intent();
i.setAction("ir.sss.smsREC");
context.sendBroadcast(i);
Log.i("...","broadcast sent");
}
catch (NullPointerException e)
{
e.getMessage();
}