ฉันต้องตรวจสอบว่าผู้รับที่ลงทะเบียนของฉันยังคงลงทะเบียนอยู่หรือไม่ถ้าฉันจะตรวจสอบวิธีการใด ๆ ได้บ้าง?
ฉันต้องตรวจสอบว่าผู้รับที่ลงทะเบียนของฉันยังคงลงทะเบียนอยู่หรือไม่ถ้าฉันจะตรวจสอบวิธีการใด ๆ ได้บ้าง?
คำตอบ:
ฉันไม่แน่ใจว่า API ให้ API โดยตรงหากคุณพิจารณาหัวข้อนี้ :
ฉันสงสัยในสิ่งเดียวกัน
ในกรณีของฉันฉันมีการBroadcastReceiver
ใช้งานที่โทรContext#unregisterReceiver(BroadcastReceiver)
ผ่านตัวเองเป็นอาร์กิวเมนต์หลังจากจัดการกับเจตนาที่ได้รับ
มีโอกาสเล็ก ๆ ที่ผู้รับเป็นonReceive(Context, Intent)
วิธีการที่เรียกว่ามากกว่าหนึ่งครั้งเพราะมันมีการลงทะเบียนที่มีหลายIntentFilters
สร้างศักยภาพในการที่จะถูกโยนลงมาจากIllegalArgumentException
Context#unregisterReceiver(BroadcastReceiver)
ในกรณีของฉันฉันสามารถเก็บสมาชิกที่ซิงโครไนซ์ส่วนตัวเพื่อตรวจสอบก่อนการโทร
Context#unregisterReceiver(BroadcastReceiver)
แต่มันจะสะอาดกว่านี้ถ้า API ให้วิธีการตรวจสอบ
ไม่มีฟังก์ชั่น API เพื่อตรวจสอบว่ามีการลงทะเบียนผู้รับหรือไม่ วิธีแก้ปัญหาคือการใส่รหัสของคุณในtry catch block as done below.
try {
//Register or UnRegister your broadcast receiver here
} catch(IllegalArgumentException e) {
e.printStackTrace();
}
null
ฉันกำลังจะไปเก็บตัวอย่างของการรับของฉันและตรวจสอบเพื่อยกเลิกการลงทะเบียนมันถ้ามันไม่ได้เป็น try catch
แต่เป็นคุณชี้ให้เห็นฉันจะมี ไร้สาระ.
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
โฆษณา 1
-- ตอบกลับ:
สิ่งนี้ไม่หรูหราอย่างนั้นเพราะคุณต้องจำไว้ว่าให้ตั้งค่าสถานะ isRegistered หลังจากคุณลงทะเบียน - รับบีชิงทรัพย์
- "เพิ่มเติมวิธีที่ละเอียดอ่อน" เพิ่มวิธีในผู้รับเพื่อลงทะเบียนและตั้งค่าสถานะ
สิ่งนี้จะไม่ทำงานหากคุณรีสตาร์ทอุปกรณ์หรือแอปของคุณถูกฆ่าโดยระบบปฏิบัติการ - อามิน 6 ชั่วโมงที่ผ่านมา
@amin - ดูอายุการใช้งานของรหัส (ไม่ใช่ระบบที่ลงทะเบียนโดยรายการชัดแจ้ง) ผู้รับที่ลงทะเบียน :)
ฉันใช้โซลูชันนี้
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);
}
}
}
คุณมีหลายทางเลือก
คุณสามารถใส่ธงลงในชั้นเรียนหรือกิจกรรมของคุณ ใส่ตัวแปรบูลีนลงในชั้นเรียนของคุณแล้วดูที่ธงนี้เพื่อทราบว่าคุณได้ลงทะเบียนตัวรับสัญญาณแล้วหรือยัง
สร้างคลาสที่ขยายตัวรับและคุณสามารถใช้:
รูปแบบซิงเกิลสำหรับมีเพียงอินสแตนซ์เดียวของคลาสนี้ในโครงการของคุณ
ใช้วิธีการเพื่อทราบว่าผู้รับลงทะเบียนหรือไม่
คุณต้องใช้ลอง / จับ:
try {
if (receiver!=null) {
Activity.this.unregisterReceiver(receiver);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
คุณทำได้ง่ายๆ ....
1) สร้างตัวแปรบูลีน ...
private boolean bolBroacastRegistred;
2) เมื่อคุณลงทะเบียน Broadcast Receiver ให้ตั้งเป็น TRUE
...
bolBroacastRegistred = true;
this.registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
....
3) ใน onPause () ทำมัน ...
if (bolBroacastRegistred) {
this.unregisterReceiver(mReceiver);
bolBroacastRegistred = false
}
แค่นี้และตอนนี้คุณจะไม่ได้รับข้อความแสดงข้อผิดพลาดเพิ่มเติมอีกใน onPause ()
Tip1: ใช้ unregisterReceiver () ใน onPause () ไม่ได้อยู่ใน onDestroy () Tip2: อย่าลืมตั้งค่าตัวแปร bolBroadcastRegistred เป็น FALSE เมื่อเรียกใช้ unregisterReceive ()
ที่ประสบความสำเร็จ!
หากคุณวางไว้บนวิธีการทำลายหรือวิธีการหยุด ฉันคิดว่าเมื่อกิจกรรมถูกสร้างขึ้นอีกครั้ง MessageReciver ไม่ได้ถูกสร้างขึ้น
@Override
public void onDestroy (){
super.onDestroy();
LocalBroadcastManager.getInstance(context).unregisterReceiver(mMessageReceiver);
}
ฉันใช้ Intent เพื่อให้ Broadcast Receiver ทราบเกี่ยวกับอินสแตนซ์ตัวจัดการของเธรดกิจกรรมหลักและใช้ข้อความเพื่อส่งข้อความไปยังกิจกรรมหลัก
ฉันใช้กลไกดังกล่าวเพื่อตรวจสอบว่า Broadcast Receiver ได้รับการลงทะเบียนแล้วหรือไม่ บางครั้งมีความจำเป็นเมื่อคุณลงทะเบียน Broadcast Receiver ของคุณแบบไดนามิกและไม่ต้องการที่จะทำให้มันสองครั้งหรือคุณนำเสนอให้กับผู้ใช้ถ้า 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();
}
}
.........
}
}
ส่วนตัวฉันใช้วิธีการโทร unregisterReceiver และกลืนข้อยกเว้นถ้ามันถูกโยน ฉันเห็นด้วยนี้น่าเกลียด แต่วิธีที่ดีที่สุดในขณะนี้ให้
ฉันได้ส่งคำขอฟีเจอร์เพื่อรับวิธีบูลีนเพื่อตรวจสอบว่ามีการเพิ่มผู้รับลงทะเบียนใน Android API หรือไม่ โปรดสนับสนุนที่นี่หากคุณต้องการที่จะเห็นมันเพิ่ม: https://code.google.com/p/android/issues/detail?id=73718
ฉันพบปัญหาฉันประสบปัญหาเดียวกันในแอปพลิเคชันของฉัน ฉันเรียก registerReceiver () หลายครั้งภายในแอปพลิเคชัน
ทางออกที่ง่ายสำหรับปัญหานี้คือการเรียก registerReceiver () ใน Custom Application Class ของคุณ สิ่งนี้จะช่วยให้มั่นใจได้ว่าตัวรับสัญญาณออกอากาศของคุณจะถูกเรียกเพียงครั้งเดียวในรอบการใช้งานทั้งหมดของคุณ
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);
}
}
นี่คือวิธีที่ฉันทำมันเป็นคำตอบที่แก้ไขโดย ceph3us และแก้ไขโดย slinden77 (เหนือสิ่งอื่นใดฉันได้ลบค่าส่งคืนของวิธีการที่ฉันไม่ต้องการ):
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
}
}
}
จากนั้นในชั้นเรียนกิจกรรม:
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());
}
}
ฉันใส่รหัสนี้ในกิจกรรมหลักของฉัน
List registerReceivers = 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);
}
สำหรับฉันทำงานต่อไปนี้:
if (receiver.isOrderedBroadcast()) {
requireContext().unregisterReceiver(receiver);
}
นี่คือสิ่งที่ฉันทำเพื่อตรวจสอบว่าผู้ลงโฆษณาได้ลงทะเบียนแล้วแม้ว่าคุณจะปิดแอปพลิเคชันของคุณ (เสร็จสิ้น ())
Firsttime ใช้แอปพลิเคชั่นของคุณส่งการออกอากาศก่อนที่มันจะคืนค่าจริง / เท็จขึ้นอยู่กับว่าผู้ประกาศของคุณยังคงทำงานอยู่หรือไม่
โฆษกของฉัน
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;
}
}
}
MainActivity ของฉัน
// 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"));
}
คุณสามารถใช้กริชเพื่อสร้างการอ้างอิงของผู้รับนั้น
ก่อนอื่นให้มัน:
@Provides
@YourScope
fun providesReceiver(): NotificationReceiver{
return NotificationReceiver()
}
จากนั้นฉีดที่คุณต้องการ (ใช้constructor
หรือฟิลด์injection
)
และส่งต่อไปยัง registerReceiver
และก็ผ่านไป
ใส่ไว้ในtry/catch
บล็อกด้วย
if( receiver.isOrderedBroadcast() ){
// receiver object is registered
}
else{
// receiver object is not registered
}
เพียงตรวจสอบ NullPointerException หากผู้รับไม่มีอยู่ดังนั้น ...
try{
Intent i = new Intent();
i.setAction("ir.sss.smsREC");
context.sendBroadcast(i);
Log.i("...","broadcast sent");
}
catch (NullPointerException e)
{
e.getMessage();
}