উত্তর:
আমি এই বিষয়ে নিশ্চিত নই যে আপনি যদি এই থ্রেডটি বিবেচনা করেন তবে API সরাসরি সরাসরি একটি এপিআই সরবরাহ করে :
আমিও একই জিনিস ভাবছিলাম।
আমার ক্ষেত্রে আমার এমন একটিBroadcastReceiver
বাস্তবায়ন রয়েছেContext#unregisterReceiver(BroadcastReceiver)
যা এটি প্রাপ্ত ইন্টেন্টকে পরিচালনা করার পরে নিজেকে যুক্তি হিসাবে আখ্যায়িত করে।
একটি ছোট সুযোগ রয়েছে যে প্রাপকেরonReceive(Context, Intent)
পদ্ধতিটিকে একাধিকবার বলা হয়, যেহেতু এটি একাধিকের সাথে নিবন্ধিত হয়IntentFilters
, যারIllegalArgumentException
ফলে নিক্ষেপ হওয়ার সম্ভাবনা তৈরি হয়Context#unregisterReceiver(BroadcastReceiver)
।আমার ক্ষেত্রে, আমি কল করার আগে চেক করতে একটি বেসরকারী সিঙ্ক্রোনাইজ সদস্যকে সঞ্চয় করতে পারি
Context#unregisterReceiver(BroadcastReceiver)
, তবে এপিআই যদি একটি চেক পদ্ধতি সরবরাহ করে তবে এটি অনেকটা ক্লিনার হবে।
কোনও রিসিভার নিবন্ধিত হয়েছে কিনা তা যাচাই করার জন্য কোনও এআইপি ফাংশন নেই। কাজের কোডটি আপনার কোডটি একটিতে স্থাপন করা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
- এর উত্তরে:
এটি সত্যিই এটি মার্জিত নয় কারণ আপনার নিবন্ধকরণের পরে আপনাকে আইস-রেজিস্টার্ড পতাকা সেট করতে হবে remember - স্টিলথ রাব্বি
- "আরও অভিজাত উপায়" নিবন্ধ এবং পতাকা সেট করার জন্য রিসিভারে পদ্ধতি যুক্ত করেছে
আপনি যদি ডিভাইসটি পুনরায় চালু করেন বা আপনার অ্যাপ্লিকেশন ওএস দ্বারা নিহত হয়ে থাকে তবে এটি কাজ করবে না। - আমিন 6 ঘন্টা আগে
@ আমিন - কোড অফ আজীবন দেখুন (ম্যানিফেস্ট এন্ট্রি দ্বারা নিবন্ধিত সিস্টেম নয়) নিবন্ধিত রিসিভার :)
আমি এই সমাধানটি ব্যবহার করছি
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;
২) আপনি যখন আপনার ব্রডকাস্ট রিসিভারটি নিবন্ধভুক্ত করবেন তখন এটিকে সত্যে সেট করুন
...
bolBroacastRegistred = true;
this.registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
....
3) অনপেজ () এ এটি করুন ...
if (bolBroacastRegistred) {
this.unregisterReceiver(mReceiver);
bolBroacastRegistred = false
}
কেবল এটি, এবং এখন আপনি অনপেজ () এ আরও ব্যতিক্রম ত্রুটি বার্তা পাবেন না।
টিপ 1: সর্বদা অনডিজার রিসিভার () অনপ্রেসে () অনডেস্ট্রয় () এ না ব্যবহার করুন
সফল!
আমি প্রধান ক্রিয়াকলাপের থ্রেডের হ্যান্ডলারের উদাহরণ সম্পর্কে ব্রডকাস্ট রিসিভারকে জানতে দেওয়ার উদ্দেশ্যে ব্যবহার করেছি এবং মূল ক্রিয়াকলাপে একটি বার্তা প্রেরণের জন্য বার্তা ব্যবহার করেছি
আমি ব্রডকাস্ট রিসিভারটি ইতিমধ্যে নিবন্ধিত আছে কিনা তা যাচাই করার জন্য আমি এই জাতীয় প্রক্রিয়া ব্যবহার করেছি। আপনি যখন আপনার ব্রডকাস্ট রিসিভারটি গতিশীলভাবে নিবন্ধভুক্ত করেন এবং দুবার এটি তৈরি করতে চান না বা ব্রডকাস্ট রিসিভার চালু থাকে তবে আপনি ব্যবহারকারীর কাছে উপস্থাপন করতে চাইলে কখনও কখনও এটি প্রয়োজন হয়।
যথোপযুক্ত সৃষ্টিকর্তা:
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();
}
}
.........
}
}
ব্যক্তিগতভাবে আমি অনিবন্ধিত রিসিভারকে কল করার এবং ব্যতিক্রমটি যদি নিক্ষেপ করা হয় তবে তা গিলে ফেলার পদ্ধতিটি ব্যবহার করি। আমি সম্মতি জানাই এটি কুৎসিত তবে বর্তমানে প্রদত্ত সেরা পদ্ধতি
অ্যান্ড্রয়েড এপিআইতে কোনও রিসিভার নিবন্ধিত আছে কিনা তা পরীক্ষা করার জন্য আমি বুলিয়ান পদ্ধতিটি পাওয়ার জন্য একটি বৈশিষ্ট্য অনুরোধ উত্থাপন করেছি। আপনি যদি এটি যুক্ত দেখতে চান তবে দয়া করে এখানে এটি সমর্থন করুন: https://code.google.com/p/android/issues/detail?id=73718
আমি আপনার সমস্যা পেয়েছি, আমি আমার অ্যাপ্লিকেশনটিতে একই সমস্যার মুখোমুখি হয়েছি। আমি আবেদনের মধ্যে একাধিকবার নিবন্ধনকারীকে () কল করছিলাম।
এই সমস্যাটির একটি সহজ সমাধান হ'ল আপনার কাস্টম অ্যাপ্লিকেশন ক্লাসে রেজিস্ট্রার রিসিভার () কল করুন। এটি নিশ্চিত করবে যে আপনার ব্রডকাস্টটি রিসিভারকে আপনার পুরো অ্যাপ্লিকেশন লাইফসাইকেলে কেবল একজন বলা হবে।
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);
}
}
এটি আমি এইভাবে এটি করেছি, এটি সিফ 3us দ্বারা প্রদত্ত উত্তরের একটি সংশোধিত সংস্করণ এবং স্লাইডেন 77 by দ্বারা সম্পাদিত (অন্যান্য জিনিসের মধ্যে আমি যে পদ্ধতিগুলির আমার প্রয়োজন ছিল না তার রিটার্ন মানগুলি সরিয়ে নিয়েছি):
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());
}
}
আমি আমার পিতামাতার ক্রিয়াকলাপে এই কোডটি রেখেছি
তালিকাভুক্ত তালিকাভুক্ত = নতুন অ্যারেলিস্ট <> ();
@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);
}
আপনি আবেদন বন্ধ করে দিলেও ব্রডকাস্টার ইতিমধ্যে নিবন্ধভুক্ত হয়েছে কিনা তা যাচাই করার জন্য আমি এখানে যা করেছি (সমাপ্ত ())
আপনার অ্যাপ্লিকেশনটি চলমান, প্রথমে একটি সম্প্রচার প্রেরণ করুন এটি সত্য / মিথ্যা ফিরে আসবে আপনার ব্রডকাস্টার এখনও চলছে কিনা তা নির্ভর করে।
আমার সম্প্রচারক
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;
}
}
}
আমার প্রধান কার্যকলাপ
// 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
}
শুধু নালপয়েন্টার এক্সসেপশন পরীক্ষা করুন। যদি রিসিভারের অস্তিত্ব না থাকে তবে ...
try{
Intent i = new Intent();
i.setAction("ir.sss.smsREC");
context.sendBroadcast(i);
Log.i("...","broadcast sent");
}
catch (NullPointerException e)
{
e.getMessage();
}