সম্প্রচার ওভারভিউ

অ্যান্ড্রয়েড অ্যাপগুলো পাবলিশ-সাবস্ক্রাইব ডিজাইন প্যাটার্নের মতোই অ্যান্ড্রয়েড সিস্টেম এবং অন্যান্য অ্যান্ড্রয়েড অ্যাপ থেকে ব্রডকাস্ট মেসেজ পাঠায় ও গ্রহণ করে। নির্দিষ্ট কিছু ঘটনা ঘটলে সিস্টেম এবং অ্যাপগুলো সাধারণত ব্রডকাস্ট পাঠায়। উদাহরণস্বরূপ, সিস্টেম বুট বা ডিভাইস চার্জ হওয়ার মতো বিভিন্ন সিস্টেম ইভেন্ট ঘটলে অ্যান্ড্রয়েড সিস্টেম ব্রডকাস্ট পাঠায়। অ্যাপগুলো নিজস্ব ব্রডকাস্টও পাঠায়, যেমন—অন্যান্য অ্যাপকে তাদের আগ্রহের কোনো বিষয় (উদাহরণস্বরূপ, নতুন ডেটা ডাউনলোড) সম্পর্কে অবহিত করার জন্য।

অ্যাপগুলো নির্দিষ্ট ব্রডকাস্ট গ্রহণ করার জন্য নিবন্ধন করতে পারে। যখন কোনো ব্রডকাস্ট পাঠানো হয়, তখন সিস্টেম স্বয়ংক্রিয়ভাবে সেইসব অ্যাপে ব্রডকাস্টটি পাঠিয়ে দেয়, যারা সেই নির্দিষ্ট ধরনের ব্রডকাস্ট গ্রহণ করার জন্য সাবস্ক্রাইব করেছে।

সাধারণভাবে বলতে গেলে, ব্রডকাস্টকে বিভিন্ন অ্যাপের মধ্যে এবং স্বাভাবিক ইউজার ফ্লো-এর বাইরে একটি মেসেজিং সিস্টেম হিসেবে ব্যবহার করা যেতে পারে। তবে, ব্রডকাস্টের উত্তর দেওয়ার এবং ব্যাকগ্রাউন্ডে এমন কাজ চালানোর সুযোগের অপব্যবহার না করার ব্যাপারে আপনাকে অবশ্যই সতর্ক থাকতে হবে, যা সিস্টেমের পারফরম্যান্স ধীর করে দিতে পারে।

সিস্টেম সম্প্রচার সম্পর্কে

বিভিন্ন সিস্টেম ইভেন্ট ঘটলে, যেমন সিস্টেম যখন এয়ারপ্লেন মোডে চালু বা বন্ধ হয়, তখন সিস্টেমটি স্বয়ংক্রিয়ভাবে ব্রডকাস্ট পাঠায়। সাবস্ক্রাইব করা সমস্ত অ্যাপ এই ব্রডকাস্টগুলো গ্রহণ করে।

Intent অবজেক্টটি ব্রডকাস্ট মেসেজকে আবৃত করে রাখে। action স্ট্রিংটি সংঘটিত ইভেন্টটিকে শনাক্ত করে, যেমন android.intent.action.AIRPLANE_MODE । ইন্টেন্টটির extra ফিল্ডে অতিরিক্ত তথ্যও অন্তর্ভুক্ত থাকতে পারে। উদাহরণস্বরূপ, Airplane Mode ইন্টেন্টটিতে একটি boolean extra থাকে যা নির্দেশ করে যে Airplane Mode চালু আছে কি না।

কিভাবে ইনটেন্ট পড়তে হয় এবং ইনটেন্ট থেকে অ্যাকশন স্ট্রিং পেতে হয়, সে সম্পর্কে আরও তথ্যের জন্য ইনটেন্ট এবং ইনটেন্ট ফিল্টার দেখুন।

সিস্টেম সম্প্রচার কার্যক্রম

সিস্টেম ব্রডকাস্ট অ্যাকশনগুলির একটি সম্পূর্ণ তালিকার জন্য, অ্যান্ড্রয়েড এসডিকে-তে থাকা BROADCAST_ACTIONS.TXT ফাইলটি দেখুন। প্রতিটি ব্রডকাস্ট অ্যাকশনের সাথে একটি কনস্ট্যান্ট ফিল্ড যুক্ত থাকে। উদাহরণস্বরূপ, ACTION_AIRPLANE_MODE_CHANGED কনস্ট্যান্টটির মান হলো android.intent.action.AIRPLANE_MODE । প্রতিটি ব্রডকাস্ট অ্যাকশনের ডকুমেন্টেশন তার সংশ্লিষ্ট কনস্ট্যান্ট ফিল্ডে পাওয়া যায়।

সিস্টেম সম্প্রচারে পরিবর্তন

অ্যান্ড্রয়েড প্ল্যাটফর্মের বিবর্তনের সাথে সাথে, সিস্টেম ব্রডকাস্টের আচরণেও পর্যায়ক্রমে পরিবর্তন আসে। অ্যান্ড্রয়েডের সকল সংস্করণকে সমর্থন করার জন্য নিম্নলিখিত পরিবর্তনগুলো মনে রাখবেন।

অ্যান্ড্রয়েড ১৬

অ্যান্ড্রয়েড ১৬- এ, android:priority অ্যাট্রিবিউট বা IntentFilter.setPriority() ব্যবহার করে বিভিন্ন প্রসেসের মধ্যে ব্রডকাস্ট ডেলিভারির ক্রম নিশ্চিত করা হবে না। ব্রডকাস্ট প্রায়োরিটি সমস্ত প্রসেসের পরিবর্তে শুধুমাত্র একই অ্যাপ্লিকেশন প্রসেসের মধ্যেই কার্যকর থাকে।

এছাড়াও, ব্রডকাস্ট অগ্রাধিকার স্বয়ংক্রিয়ভাবে ( SYSTEM_LOW_PRIORITY + 1, SYSTEM_HIGH_PRIORITY - 1) পরিসরের মধ্যে সীমাবদ্ধ থাকে। শুধুমাত্র সিস্টেম কম্পোনেন্টগুলোই ব্রডকাস্ট অগ্রাধিকার হিসেবে SYSTEM_LOW_PRIORITY এবং SYSTEM_HIGH_PRIORITY সেট করতে পারে।

অ্যান্ড্রয়েড ১৪

অ্যাপগুলো যখন ক্যাশড অবস্থায় থাকে, তখন সিস্টেমের স্বাস্থ্য সুরক্ষার জন্য সিস্টেম ব্রডকাস্ট ডেলিভারি অপ্টিমাইজ করে। উদাহরণস্বরূপ, অ্যাপটি ক্যাশড অবস্থায় থাকাকালীন সিস্টেম ACTION_SCREEN_ON মতো কম গুরুত্বপূর্ণ সিস্টেম ব্রডকাস্টগুলো স্থগিত রাখে। অ্যাপটি ক্যাশড অবস্থা থেকে বেরিয়ে একটি সক্রিয় প্রসেস লাইফসাইকেলে প্রবেশ করার সাথে সাথে, সিস্টেম স্থগিত রাখা ব্রডকাস্টগুলো ডেলিভারি করে।

ম্যানিফেস্টে ঘোষিত গুরুত্বপূর্ণ ব্রডকাস্টগুলো ডেলিভারির জন্য অ্যাপগুলোকে সাময়িকভাবে ক্যাশড অবস্থা থেকে সরিয়ে দেয়।

অ্যান্ড্রয়েড ৯

অ্যান্ড্রয়েড ৯ (এপিআই লেভেল ২৮) থেকে শুরু করে, NETWORK_STATE_CHANGED_ACTION ব্রডকাস্টটি ব্যবহারকারীর অবস্থান বা ব্যক্তিগতভাবে শনাক্তযোগ্য ডেটা সম্পর্কিত তথ্য গ্রহণ করে না।

আপনার অ্যাপটি যদি অ্যান্ড্রয়েড ৯.০ (এপিআই লেভেল ২৮) বা তার উচ্চতর সংস্করণে চালিত কোনো ডিভাইসে ইনস্টল করা থাকে, তাহলে সিস্টেম ওয়াই-ফাই ব্রডকাস্টে এসএসআইডি, বিএসএসআইডি, সংযোগের তথ্য বা স্ক্যানের ফলাফল অন্তর্ভুক্ত করে না। এই তথ্যগুলো পেতে, এর পরিবর্তে getConnectionInfo() কল করুন।

অ্যান্ড্রয়েড ৮.০

অ্যান্ড্রয়েড ৮.০ (এপিআই লেভেল ২৬) থেকে শুরু করে, সিস্টেমটি ম্যানিফেস্টে ঘোষিত রিসিভারগুলোর ওপর অতিরিক্ত বিধিনিষেধ আরোপ করেছে।

আপনার অ্যাপটি যদি অ্যান্ড্রয়েড ৮.০ বা তার উচ্চতর সংস্করণকে টার্গেট করে, তাহলে আপনি বেশিরভাগ ইমপ্লিসিট ব্রডকাস্টের (যেসব ব্রডকাস্ট বিশেষভাবে আপনার অ্যাপকে টার্গেট করে না) জন্য রিসিভার ডিক্লেয়ার করতে ম্যানিফেস্ট ব্যবহার করতে পারবেন না। তবে, ব্যবহারকারী যখন সক্রিয়ভাবে আপনার অ্যাপটি ব্যবহার করছেন, তখন আপনি একটি কনটেক্সট-রেজিস্টার্ড রিসিভার ব্যবহার করতে পারবেন।

অ্যান্ড্রয়েড ৭.০

অ্যান্ড্রয়েড ৭.০ (এপিআই লেভেল ২৪) এবং এর পরবর্তী সংস্করণগুলো নিম্নলিখিত সিস্টেম ব্রডকাস্টগুলো পাঠায় না:

এছাড়াও, অ্যান্ড্রয়েড ৭.০ এবং তার পরবর্তী সংস্করণের জন্য তৈরি অ্যাপগুলোকে অবশ্যই registerReceiver(BroadcastReceiver, IntentFilter) ব্যবহার করে CONNECTIVITY_ACTION ব্রডকাস্টটি রেজিস্টার করতে হবে। ম্যানিফেস্টে রিসিভার ডিক্লেয়ার করলে তা কাজ করে না।

সম্প্রচার গ্রহণ করুন

অ্যাপগুলি দুইভাবে ব্রডকাস্ট গ্রহণ করতে পারে: কন্টেক্সট-রেজিস্টার্ড রিসিভার এবং ম্যানিফেস্ট-ডিক্লেয়ার্ড রিসিভারের মাধ্যমে।

প্রসঙ্গ-নিবন্ধিত রিসিভার

কন্টেক্সট-রেজিস্টার্ড রিসিভারগুলো তাদের রেজিস্টারিং কন্টেক্সট বৈধ থাকা পর্যন্ত ব্রডকাস্ট গ্রহণ করে। এটি সাধারণত registerReceiver এবং unregisterReceiver কলগুলোর মধ্যবর্তী সময়ে ঘটে। যখন সিস্টেম সংশ্লিষ্ট কন্টেক্সটটি ধ্বংস করে দেয়, তখন রেজিস্টারিং কন্টেক্সটটিও অবৈধ হয়ে যায়। উদাহরণস্বরূপ, যদি আপনি একটি Activity কন্টেক্সটের মধ্যে রেজিস্টার করেন, তাহলে অ্যাক্টিভিটিটি সক্রিয় থাকা পর্যন্ত আপনি ব্রডকাস্ট গ্রহণ করতে থাকবেন। যদি আপনি অ্যাপ্লিকেশন কন্টেক্সটের সাথে রেজিস্টার করেন, তাহলে অ্যাপটি চালু থাকা পর্যন্ত আপনি ব্রডকাস্ট গ্রহণ করতে থাকবেন।

একটি কনটেক্সটের সাথে রিসিভার রেজিস্টার করতে, নিম্নলিখিত ধাপগুলো অনুসরণ করুন:

  1. আপনার অ্যাপের মডিউল-স্তরের বিল্ড ফাইলে AndroidX Core লাইব্রেরির ১.৯.০ বা তার উচ্চতর সংস্করণ অন্তর্ভুক্ত করুন:

    খাঁজকাটা

    dependencies {
        def core_version = "1.18.0"
    
        // Java language implementation
        implementation "androidx.core:core:$core_version"
        // Kotlin
        implementation "androidx.core:core-ktx:$core_version"
    
        // To use RoleManagerCompat
        implementation "androidx.core:core-role:1.1.0"
    
        // To use the Animator APIs
        implementation "androidx.core:core-animation:1.0.0"
        // To test the Animator APIs
        androidTestImplementation "androidx.core:core-animation-testing:1.0.0"
    
        // Optional - To enable APIs that query the performance characteristics of GMS devices.
        implementation "androidx.core:core-performance:1.0.0"
    
        // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google
        implementation "androidx.core:core-google-shortcuts:1.1.0"
    
        // Optional - to support backwards compatibility of RemoteViews
        implementation "androidx.core:core-remoteviews:1.1.0"
    
        // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12
        implementation "androidx.core:core-splashscreen:1.2.0"
    }

    কোটলিন

    dependencies {
        val core_version = "1.18.0"
    
        // Java language implementation
        implementation("androidx.core:core:$core_version")
        // Kotlin
        implementation("androidx.core:core-ktx:$core_version")
    
        // To use RoleManagerCompat
        implementation("androidx.core:core-role:1.1.0")
    
        // To use the Animator APIs
        implementation("androidx.core:core-animation:1.0.0")
        // To test the Animator APIs
        androidTestImplementation("androidx.core:core-animation-testing:1.0.0")
    
        // Optional - To enable APIs that query the performance characteristics of GMS devices.
        implementation("androidx.core:core-performance:1.0.0")
    
        // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google
        implementation("androidx.core:core-google-shortcuts:1.1.0")
    
        // Optional - to support backwards compatibility of RemoteViews
        implementation("androidx.core:core-remoteviews:1.1.0")
    
        // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12
        implementation("androidx.core:core-splashscreen:1.2.0")
    }
  2. BroadcastReceiver এর একটি ইনস্ট্যান্স তৈরি করুন:

    কোটলিন

    val myBroadcastReceiver = MyBroadcastReceiver()
    

    জাভা

    MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();
    
  3. IntentFilter এর একটি ইনস্ট্যান্স তৈরি করুন:

    কোটলিন

    val filter = IntentFilter("com.example.snippets.ACTION_UPDATE_DATA")
    

    জাভা

    IntentFilter filter = new IntentFilter("com.example.snippets.ACTION_UPDATE_DATA");
    
  4. ব্রডকাস্ট রিসিভারটি এক্সপোর্ট করা হবে এবং ডিভাইসের অন্যান্য অ্যাপের কাছে দৃশ্যমান হবে কিনা তা নির্বাচন করুন। যদি এই রিসিভারটি সিস্টেম বা অন্যান্য অ্যাপ—এমনকি আপনার নিজের অ্যাপ থেকেও—পাঠানো ব্রডকাস্ট শোনার জন্য প্রস্তুত থাকে, তাহলে RECEIVER_EXPORTED ফ্ল্যাগটি ব্যবহার করুন। এর পরিবর্তে, যদি এই রিসিভারটি শুধুমাত্র আপনার অ্যাপ দ্বারা পাঠানো ব্রডকাস্ট শোনার জন্য প্রস্তুত থাকে, তাহলে RECEIVER_NOT_EXPORTED ফ্ল্যাগটি ব্যবহার করুন।

    কোটলিন

    val listenToBroadcastsFromOtherApps = false
    val receiverFlags = if (listenToBroadcastsFromOtherApps) {
        ContextCompat.RECEIVER_EXPORTED
    } else {
        ContextCompat.RECEIVER_NOT_EXPORTED
    }
    

    জাভা

    boolean listenToBroadcastsFromOtherApps = false;
    int receiverFlags = listenToBroadcastsFromOtherApps
            ? ContextCompat.RECEIVER_EXPORTED
            : ContextCompat.RECEIVER_NOT_EXPORTED;
    
  5. registerReceiver() কল করে রিসিভারটি রেজিস্টার করুন:

    কোটলিন

    ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags)
    

    জাভা

    ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags);
    
  6. ব্রডকাস্ট গ্রহণ করা বন্ধ করতে, unregisterReceiver(android.content.BroadcastReceiver) কল করুন। যখন আপনার আর এটির প্রয়োজন হবে না অথবা কনটেক্সটটি আর বৈধ থাকবে না, তখন রিসিভারটি আনরেজিস্টার করতে ভুলবেন না।

আপনার ব্রডকাস্ট রিসিভার নিবন্ধন বাতিল করুন

ব্রডকাস্ট রিসিভারটি রেজিস্টার করা থাকা অবস্থায়, এটি সেই কনটেক্সট-এর একটি রেফারেন্স ধরে রাখে যার সাথে আপনি এটিকে রেজিস্টার করেছেন। যদি রিসিভারের রেজিস্টার করা স্কোপটি কনটেক্সট লাইফসাইকেল স্কোপকে অতিক্রম করে, তবে এটি মেমোরি লিকের কারণ হতে পারে। উদাহরণস্বরূপ, এটি তখন ঘটতে পারে যখন আপনি একটি অ্যাক্টিভিটি স্কোপে রিসিভার রেজিস্টার করেন, কিন্তু সিস্টেম অ্যাক্টিভিটিটি ডেস্ট্রয় করার সময় আপনি এটিকে আনরেজিস্টার করতে ভুলে যান। অতএব, সর্বদা আপনার ব্রডকাস্ট রিসিভারটি আনরেজিস্টার করুন।

কোটলিন

class MyActivity : ComponentActivity() {
    private val myBroadcastReceiver = MyBroadcastReceiver()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
        ContextCompat.registerReceiver(this, myBroadcastReceiver, filter, receiverFlags)
        setContent { MyApp() }
    }

    override fun onDestroy() {
        super.onDestroy()
        // When you forget to unregister your receiver here, you're causing a leak!
        this.unregisterReceiver(myBroadcastReceiver)
    }
}

জাভা

class MyActivity extends ComponentActivity {
    MyBroadcastReceiver myBroadcastReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // ...
        ContextCompat.registerReceiver(this, myBroadcastReceiver, filter, receiverFlags);
        // Set content
    }
}

ক্ষুদ্রতম পরিসরে রেজিস্টার রিসিভার

আপনার ব্রডকাস্ট রিসিভারটি কেবল তখনই রেজিস্টার করা উচিত যখন আপনি ফলাফলের প্রতি সত্যিই আগ্রহী। সম্ভাব্য ক্ষুদ্রতম রিসিভার স্কোপটি বেছে নিন:

  • LifecycleResumeEffect অথবা অ্যাক্টিভিটির onResume / onPause লাইফসাইকেল মেথড: ব্রডকাস্ট রিসিভার শুধুমাত্র তখনই আপডেট গ্রহণ করে যখন অ্যাপটি তার রিজুমড অবস্থায় থাকে।
  • LifecycleStartEffect অথবা অ্যাক্টিভিটির onStart / onStop লাইফসাইকেল মেথড: ব্রডকাস্ট রিসিভার শুধুমাত্র তখনই আপডেট গ্রহণ করে যখন অ্যাপটি তার রিজুমড অবস্থায় থাকে।
  • DisposableEffect : ব্রডকাস্ট রিসিভার শুধুমাত্র তখনই আপডেট গ্রহণ করে যখন কম্পোজেবলটি কম্পোজিশন ট্রি-তে থাকে। এই স্কোপটি অ্যাক্টিভিটি লাইফসাইকেল স্কোপের সাথে সংযুক্ত নয়। রিসিভারটিকে অ্যাপ্লিকেশন কনটেক্সটে রেজিস্টার করার কথা বিবেচনা করুন। এর কারণ হলো, কম্পোজেবলটি তাত্ত্বিকভাবে অ্যাক্টিভিটি লাইফসাইকেল স্কোপের চেয়ে বেশি সময় ধরে টিকে থাকতে পারে এবং অ্যাক্টিভিটি লিক করতে পারে।
  • অ্যাক্টিভিটির onCreate / onDestroy : অ্যাক্টিভিটিটি যখন তার তৈরি অবস্থায় থাকে, তখন ব্রডকাস্ট রিসিভার আপডেট গ্রহণ করে। নিশ্চিত করুন যে আপনি onDestroy() ফাংশনে আনরেজিস্টার করছেন, onSaveInstanceState(Bundle) নয়, কারণ এটি কল নাও হতে পারে।
  • কাস্টম স্কোপ: উদাহরণস্বরূপ, আপনি আপনার ViewModel স্কোপে একটি রিসিভার রেজিস্টার করতে পারেন, যাতে এটি অ্যাক্টিভিটি পুনরায় তৈরি হওয়ার পরেও টিকে থাকে। রিসিভারটি রেজিস্টার করার জন্য অবশ্যই অ্যাপ্লিকেশন কনটেক্সট ব্যবহার করবেন, কারণ রিসিভারটি অ্যাক্টিভিটির লাইফসাইকেল স্কোপের চেয়ে বেশি সময় ধরে টিকে থাকতে পারে এবং অ্যাক্টিভিটি লিক করতে পারে।

স্টেটফুল এবং স্টেটলেস কম্পোজেবল তৈরি করুন

Compose-এ স্টেটফুল এবং স্টেটলেস কম্পোজেবল রয়েছে। একটি কম্পোজেবলের ভিতরে কোনো ব্রডকাস্ট রিসিভারকে রেজিস্টার বা আনরেজিস্টার করলে সেটি স্টেটফুল হয়ে যায়। কম্পোজেবল কোনো ডিটারমিনিস্টিক ফাংশন নয়, যা একই প্যারামিটার দিলে একই কন্টেন্ট রেন্ডার করে। রেজিস্টার করা ব্রডকাস্ট রিসিভারে কলের উপর ভিত্তি করে এর অভ্যন্তরীণ স্টেট পরিবর্তিত হতে পারে।

Compose-এ একটি উত্তম অনুশীলন হিসেবে, আমরা সুপারিশ করি যে আপনি আপনার কম্পোজেবলগুলোকে স্টেটফুল এবং স্টেটলেস সংস্করণে বিভক্ত করুন। অতএব, ব্রডকাস্ট রিসিভার তৈরির কাজটি একটি কম্পোজেবল থেকে বাইরে হোয়িস্ট করে এটিকে স্টেটলেস করার জন্য আমরা সুপারিশ করি:

@Composable
fun MyStatefulScreen() {
    val myBroadcastReceiver = remember { MyBroadcastReceiver() }
    val context = LocalContext.current
    LifecycleStartEffect(true) {
        // ...
        ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, flags)
        onStopOrDispose { context.unregisterReceiver(myBroadcastReceiver) }
    }
    MyStatelessScreen()
}

@Composable
fun MyStatelessScreen() {
    // Implement your screen
}

ম্যানিফেস্ট-ঘোষিত প্রাপক

আপনি যদি আপনার ম্যানিফেস্টে একটি ব্রডকাস্ট রিসিভার ঘোষণা করেন, তাহলে ব্রডকাস্ট পাঠানো হলে সিস্টেম আপনার অ্যাপটি চালু করে। যদি অ্যাপটি আগে থেকে চালু না থাকে, তবে সিস্টেম অ্যাপটি চালু করে।

ম্যানিফেস্টে একটি ব্রডকাস্ট রিসিভার ঘোষণা করতে, নিম্নলিখিত ধাপগুলি অনুসরণ করুন:

  1. আপনার অ্যাপের ম্যানিফেস্টে <receiver> এলিমেন্টটি উল্লেখ করুন।

    <!-- If this receiver listens for broadcasts sent from the system or from
         other apps, even other apps that you own, set android:exported to "true". -->
    <receiver android:name=".MyBroadcastReceiver" android:exported="false">
        <intent-filter>
            <action android:name="com.example.snippets.ACTION_UPDATE_DATA" />
        </intent-filter>
    </receiver>
    

    ইনটেন্ট ফিল্টারগুলো নির্দিষ্ট করে দেয় যে আপনার রিসিভার কোন কোন ব্রডকাস্ট অ্যাকশনে সাবস্ক্রাইব করবে।

  2. BroadcastReceiver নামে একটি সাবক্লাস তৈরি করুন এবং onReceive(Context, Intent) ইমপ্লিমেন্ট করুন। নিচের উদাহরণে ব্রডকাস্ট রিসিভারটি ব্রডকাস্টের বিষয়বস্তু লগ করে এবং প্রদর্শন করে:

    কোটলিন

    class MyBroadcastReceiver : BroadcastReceiver() {
    
        @Inject
        lateinit var dataRepository: DataRepository
    
        override fun onReceive(context: Context, intent: Intent) {
            if (intent.action == "com.example.snippets.ACTION_UPDATE_DATA") {
                val data = intent.getStringExtra("com.example.snippets.DATA") ?: "No data"
                // Do something with the data, for example send it to a data repository:
                dataRepository.updateData(data)
            }
        }
    }
    

    জাভা

    public static class MyBroadcastReceiver extends BroadcastReceiver {
    
        @Inject
        DataRepository dataRepository;
    
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Objects.equals(intent.getAction(), "com.example.snippets.ACTION_UPDATE_DATA")) {
                String data = intent.getStringExtra("com.example.snippets.DATA");
                // Do something with the data, for example send it to a data repository:
                if (data != null) { dataRepository.updateData(data); }
            }
        }
    }
    

অ্যাপটি ইনস্টল করার সময় সিস্টেম প্যাকেজ ম্যানেজার রিসিভারটিকে রেজিস্টার করে। এরপর রিসিভারটি আপনার অ্যাপের একটি পৃথক এন্ট্রি পয়েন্ট হয়ে ওঠে, যার অর্থ হলো অ্যাপটি চালু না থাকলেও সিস্টেম অ্যাপটি শুরু করতে এবং ব্রডকাস্টটি ডেলিভার করতে পারে।

সিস্টেমটি প্রাপ্ত প্রতিটি ব্রডকাস্ট পরিচালনা করার জন্য একটি নতুন BroadcastReceiver কম্পোনেন্ট অবজেক্ট তৈরি করে। এই অবজেক্টটি শুধুমাত্র onReceive(Context, Intent) কলটির সময়কাল পর্যন্ত বৈধ থাকে। আপনার কোড এই মেথড থেকে রিটার্ন করার সাথে সাথে, সিস্টেম কম্পোনেন্টটিকে আর সক্রিয় বলে গণ্য করে না।

প্রক্রিয়ার অবস্থার উপর প্রভাব

আপনার BroadcastReceiver চালু আছে কি না, তা এর অন্তর্ভুক্ত প্রসেসকে প্রভাবিত করে, যা এটিকে সিস্টেম থেকে বন্ধ করে দেওয়ার সম্ভাবনাকে পরিবর্তন করতে পারে। একটি ফোরগ্রাউন্ড প্রসেস একটি রিসিভারের onReceive() মেথডটি এক্সিকিউট করে। অতিরিক্ত মেমোরি চাপ ছাড়া সিস্টেম প্রসেসটি চালু রাখে।

সিস্টেম onReceive() এর পরে BroadcastReceiver নিষ্ক্রিয় করে দেয়। রিসিভারের হোস্ট প্রসেসের গুরুত্ব তার অ্যাপ কম্পোনেন্টগুলোর উপর নির্ভর করে। যদি সেই প্রসেসটি শুধুমাত্র একটি ম্যানিফেস্ট-ডিক্লেয়ার্ড রিসিভার হোস্ট করে, তবে অন্যান্য আরও গুরুত্বপূর্ণ প্রসেসের জন্য রিসোর্স মুক্ত করতে সিস্টেম onReceive() এর পরে সেটিকে কিল করে দিতে পারে। এটি এমন অ্যাপগুলোর ক্ষেত্রে সাধারণ, যেগুলোর সাথে ব্যবহারকারী কখনও ইন্টারঅ্যাক্ট করেনি বা সম্প্রতি করেনি।

সুতরাং, ব্রডকাস্ট রিসিভারগুলোর দীর্ঘক্ষণ ধরে চলা ব্যাকগ্রাউন্ড থ্রেড চালু করা উচিত নয়। সিস্টেম onReceive() এর পরে যেকোনো মুহূর্তে মেমরি পুনরুদ্ধারের জন্য প্রসেসটি বন্ধ করে দিতে পারে, যার ফলে তৈরি হওয়া থ্রেডটি টার্মিনেট হয়ে যায়। প্রসেসটিকে সচল রাখতে, JobScheduler ব্যবহার করে রিসিভার থেকে একটি JobService শিডিউল করুন, যাতে সিস্টেম জানতে পারে যে প্রসেসটি এখনও কাজ করছে। Background Work Overview-তে এ বিষয়ে আরও বিস্তারিত তথ্য দেওয়া আছে।

সম্প্রচার পাঠান

অ্যান্ড্রয়েড অ্যাপগুলিকে ব্রডকাস্ট পাঠানোর জন্য দুটি উপায় প্রদান করে:

  • ` sendOrderedBroadcast(Intent, String) ` মেথডটি একবারে একটি রিসিভারের কাছে ব্রডকাস্ট পাঠায়। প্রতিটি রিসিভার পর্যায়ক্রমে এক্সিকিউট হওয়ার সময়, এটি পরবর্তী রিসিভারের কাছে একটি ফলাফল প্রোপাগেট করতে পারে। এটি ব্রডকাস্টটিকে সম্পূর্ণরূপে অ্যাবোর্টও করতে পারে, যাতে এটি অন্য রিসিভারদের কাছে না পৌঁছায়। আপনি একই অ্যাপ প্রসেসের মধ্যে রিসিভারগুলো কোন ক্রমে চলবে তা নিয়ন্ত্রণ করতে পারেন। এটি করার জন্য, সংশ্লিষ্ট ইন্টেন্ট-ফিল্টারের android:priority অ্যাট্রিবিউটটি ব্যবহার করুন। একই প্রায়োরিটির রিসিভারগুলো যেকোনো ক্রমে রান হয়।
  • ` sendBroadcast(Intent) ` মেথডটি একটি অনির্ধারিত ক্রমে সমস্ত রিসিভারের কাছে ব্রডকাস্ট পাঠায়। একে `Normal Broadcast` বলা হয়। এটি অধিকতর কার্যকর, কিন্তু এর অর্থ হলো রিসিভাররা অন্য রিসিভারদের থেকে ফলাফল পড়তে, ব্রডকাস্ট থেকে প্রাপ্ত ডেটা প্রচার করতে, বা ব্রডকাস্টটি বাতিল করতে পারে না।

নিম্নলিখিত কোড স্নিপেটটি একটি Intent তৈরি করে এবং sendBroadcast(Intent) কল করার মাধ্যমে কীভাবে একটি ব্রডকাস্ট পাঠাতে হয় তা প্রদর্শন করে।

কোটলিন

val intent = Intent("com.example.snippets.ACTION_UPDATE_DATA").apply {
    putExtra("com.example.snippets.DATA", newData)
    setPackage("com.example.snippets")
}
context.sendBroadcast(intent)

জাভা

Intent intent = new Intent("com.example.snippets.ACTION_UPDATE_DATA");
intent.putExtra("com.example.snippets.DATA", newData);
intent.setPackage("com.example.snippets");
context.sendBroadcast(intent);

ব্রডকাস্ট মেসেজটি একটি Intent অবজেক্টের মধ্যে থাকে। ইন্টেন্টের action স্ট্রিং-এ অবশ্যই অ্যাপটির জাভা প্যাকেজ নেম সিনট্যাক্স থাকতে হবে এবং ব্রডকাস্ট ইভেন্টটিকে অনন্যভাবে শনাক্ত করতে হবে। আপনি putExtra(String, Bundle) ব্যবহার করে ইন্টেন্টের সাথে অতিরিক্ত তথ্য সংযুক্ত করতে পারেন। এছাড়াও, ইন্টেন্টের উপর setPackage(String) কল করে আপনি একই অর্গানাইজেশনের কয়েকটি অ্যাপের মধ্যে ব্রডকাস্ট সীমাবদ্ধ করতে পারেন।

অনুমতি সাপেক্ষে সম্প্রচার সীমাবদ্ধ করুন

অনুমতির মাধ্যমে আপনি নির্দিষ্ট অনুমতি থাকা অ্যাপগুলোর মধ্যে সম্প্রচার সীমাবদ্ধ করতে পারেন। আপনি একটি সম্প্রচারের প্রেরক বা প্রাপক উভয়ের উপরই এই বিধিনিষেধ আরোপ করতে পারেন।

অনুমতি সাপেক্ষে সম্প্রচার পাঠান

যখন আপনি sendBroadcast(Intent, String) অথবা sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) কল করেন, তখন আপনি একটি পারমিশন প্যারামিটার নির্দিষ্ট করতে পারেন। শুধুমাত্র সেইসব রিসিভারই ব্রডকাস্টটি গ্রহণ করতে পারে, যারা তাদের ম্যানিফেস্টে <uses-permission> ট্যাগ ব্যবহার করে সেই পারমিশনের জন্য অনুরোধ করেছে। যদি পারমিশনটি বিপজ্জনক হয়, তবে রিসিভার ব্রডকাস্টটি গ্রহণ করার আগে আপনাকে অবশ্যই পারমিশনটি মঞ্জুর করতে হবে। উদাহরণস্বরূপ, নিম্নলিখিত কোডটি একটি পারমিশন সহ একটি ব্রডকাস্ট পাঠায়:

কোটলিন

context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION)

জাভা

context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION);

সম্প্রচারটি গ্রহণ করার জন্য, গ্রহণকারী অ্যাপটিকে নিম্নলিখিতভাবে অনুমতির জন্য অনুরোধ করতে হবে:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

আপনি BLUETOOTH_CONNECT মতো কোনো বিদ্যমান সিস্টেম পারমিশন নির্দিষ্ট করতে পারেন অথবা <permission> এলিমেন্ট ব্যবহার করে একটি কাস্টম পারমিশন সংজ্ঞায়িত করতে পারেন। সাধারণভাবে পারমিশন এবং নিরাপত্তা সম্পর্কে তথ্যের জন্য, সিস্টেম পারমিশন (System Permissions) দেখুন।

অনুমতি সাপেক্ষে সম্প্রচার গ্রহণ করুন

যদি আপনি একটি ব্রডকাস্ট রিসিভার রেজিস্টার করার সময় ( registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) ব্যবহার করে অথবা আপনার ম্যানিফেস্টের <receiver> ট্যাগে) একটি পারমিশন প্যারামিটার নির্দিষ্ট করেন, তাহলে শুধুমাত্র সেইসব ব্রডকাস্টারই রিসিভারটিতে একটি ইন্টেন্ট পাঠাতে পারবে, যারা তাদের ম্যানিফেস্টে <uses-permission> ট্যাগ ব্যবহার করে পারমিশনটির জন্য অনুরোধ করেছে। যদি পারমিশনটি বিপজ্জনক হয়, তবে ব্রডকাস্টারকেও সেই পারমিশনটি প্রদান করতে হবে।

উদাহরণস্বরূপ, ধরে নিন আপনার গ্রহণকারী অ্যাপটিতে নিম্নলিখিতভাবে একটি ম্যানিফেস্ট-ঘোষিত রিসিভার রয়েছে:

<!-- If this receiver listens for broadcasts sent from the system or from
     other apps, even other apps that you own, set android:exported to "true". -->
<receiver
    android:name=".MyBroadcastReceiverWithPermission"
    android:permission="android.permission.ACCESS_COARSE_LOCATION"
    android:exported="true">
    <intent-filter>
        <action android:name="com.example.snippets.ACTION_UPDATE_DATA" />
    </intent-filter>
</receiver>

অথবা আপনার গ্রহণকারী অ্যাপটিতে নিম্নরূপ একটি প্রসঙ্গ-নিবন্ধিত রিসিভার রয়েছে:

কোটলিন

ContextCompat.registerReceiver(
    context, myBroadcastReceiver, filter,
    android.Manifest.permission.ACCESS_COARSE_LOCATION,
    null, // scheduler that defines thread, null means run on main thread
    receiverFlags
)

জাভা

ContextCompat.registerReceiver(
        context, myBroadcastReceiver, filter,
        android.Manifest.permission.ACCESS_COARSE_LOCATION,
        null, // scheduler that defines thread, null means run on main thread
        receiverFlags
);

তারপর, সেই রিসিভারগুলিতে ব্রডকাস্ট পাঠাতে সক্ষম হওয়ার জন্য, প্রেরক অ্যাপটিকে অবশ্যই নিম্নোক্তভাবে অনুমতির জন্য অনুরোধ করতে হবে:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

নিরাপত্তা সংক্রান্ত বিবেচনা

ব্রডকাস্ট পাঠানো এবং গ্রহণ করার ক্ষেত্রে কিছু নিরাপত্তা সংক্রান্ত বিষয় নিচে দেওয়া হলো:

  • যদি অনেকগুলো অ্যাপ তাদের ম্যানিফেস্টে একই ব্রডকাস্ট গ্রহণ করার জন্য রেজিস্টার করে থাকে, তবে এর ফলে সিস্টেম একসাথে অনেক অ্যাপ চালু করে দিতে পারে, যা ডিভাইসের পারফরম্যান্স এবং ব্যবহারকারীর অভিজ্ঞতা উভয়ের উপরই ব্যাপক প্রভাব ফেলে। এটি এড়ানোর জন্য, ম্যানিফেস্ট ডিক্লারেশনের পরিবর্তে কনটেক্সট রেজিস্ট্রেশন ব্যবহার করা শ্রেয়। কখনও কখনও, অ্যান্ড্রয়েড সিস্টেম নিজেই কনটেক্সট-রেজিস্টার্ড রিসিভারদের ব্যবহার বাধ্যতামূলক করে। উদাহরণস্বরূপ, CONNECTIVITY_ACTION ব্রডকাস্টটি শুধুমাত্র কনটেক্সট-রেজিস্টার্ড রিসিভারদের কাছেই পাঠানো হয়।

  • ইমপ্লিসিট ইন্টেন্ট ব্যবহার করে সংবেদনশীল তথ্য ব্রডকাস্ট করবেন না। যেকোনো অ্যাপ ব্রডকাস্টটি গ্রহণ করার জন্য রেজিস্টার করলে সেই তথ্য পড়তে পারে। আপনার ব্রডকাস্ট কে কে গ্রহণ করতে পারবে তা নিয়ন্ত্রণ করার তিনটি উপায় আছে:

    • ব্রডকাস্ট পাঠানোর সময় আপনি অনুমতি নির্দিষ্ট করে দিতে পারেন।
    • অ্যান্ড্রয়েড ৪.০ (এপিআই লেভেল ১৪) এবং এর পরবর্তী সংস্করণগুলোতে, ব্রডকাস্ট পাঠানোর সময় আপনি setPackage(String) ব্যবহার করে একটি প্যাকেজ নির্দিষ্ট করতে পারেন। সিস্টেমটি ব্রডকাস্টটিকে শুধুমাত্র সেই অ্যাপগুলোর মধ্যে সীমাবদ্ধ রাখে, যেগুলো প্যাকেজটির সাথে মেলে।
  • যখন আপনি একটি রিসিভার রেজিস্টার করেন, তখন যেকোনো অ্যাপ আপনার অ্যাপের রিসিভারে সম্ভাব্য ক্ষতিকারক ব্রডকাস্ট পাঠাতে পারে। আপনার অ্যাপ যে ব্রডকাস্টগুলো গ্রহণ করে, তা সীমিত করার বেশ কয়েকটি উপায় রয়েছে:

    • ব্রডকাস্ট রিসিভার নিবন্ধন করার সময় আপনি একটি অনুমতি নির্দিষ্ট করে দিতে পারেন।
    • ম্যানিফেস্টে ঘোষিত রিসিভারের জন্য, আপনি ম্যানিফেস্টে android:exported অ্যাট্রিবিউটটিকে "false" সেট করতে পারেন। রিসিভারটি অ্যাপের বাইরের উৎস থেকে ব্রডকাস্ট গ্রহণ করে না।
  • ব্রডকাস্ট অ্যাকশনের নেমস্পেসটি গ্লোবাল। নিশ্চিত করুন যে অ্যাকশনের নাম এবং অন্যান্য স্ট্রিং আপনার নিজের নেমস্পেসে লেখা হয়েছে। অন্যথায়, আপনি অনিচ্ছাকৃতভাবে অন্যান্য অ্যাপের সাথে সংঘাত তৈরি করতে পারেন।

  • যেহেতু একটি রিসিভারের onReceive(Context, Intent) মেথডটি মেইন থ্রেডে চলে, তাই এটি দ্রুত এক্সিকিউট হয়ে রিটার্ন করা উচিত। যদি আপনার দীর্ঘ সময় ধরে চলা কোনো কাজ করার প্রয়োজন হয়, তবে থ্রেড স্পন করা বা ব্যাকগ্রাউন্ড সার্ভিস চালু করার ব্যাপারে সতর্ক থাকুন, কারণ onReceive() রিটার্ন করার পর সিস্টেম পুরো প্রসেসটি বন্ধ করে দিতে পারে। আরও তথ্যের জন্য, প্রসেসের অবস্থার উপর প্রভাব দেখুন। দীর্ঘ সময় ধরে চলা কাজ সম্পাদনের জন্য, আমরা সুপারিশ করি:

    • আপনার রিসিভারের onReceive() মেথডে goAsync() কল করে BroadcastReceiver.PendingResult কে একটি ব্যাকগ্রাউন্ড থ্রেডে পাস করুন। এটি onReceive() থেকে রিটার্ন করার পরেও ব্রডকাস্টটিকে সক্রিয় রাখে। তবে, এই পদ্ধতিতেও সিস্টেম আশা করে যে আপনি খুব দ্রুত (১০ সেকেন্ডের মধ্যে) ব্রডকাস্টটি শেষ করবেন। এটি আপনাকে মেইন থ্রেডের গ্লিচিং এড়ানোর জন্য কাজটি অন্য থ্রেডে সরিয়ে নেওয়ার সুযোগ দেয়।
    • JobScheduler ব্যবহার করে একটি কাজের সময়সূচী নির্ধারণ করা। আরও তথ্যের জন্য, ইন্টেলিজেন্ট জব শিডিউলিং দেখুন।
  • ব্রডকাস্ট রিসিভার থেকে কোনো কার্যক্রম শুরু করবেন না, কারণ এতে ব্যবহারকারীর অভিজ্ঞতা অস্বস্তিকর হয়; বিশেষ করে যদি একাধিক রিসিভার থাকে। এর পরিবর্তে, একটি নোটিফিকেশন দেখানোর কথা বিবেচনা করুন।