ব্রডকাস্টের ওভারভিউ

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

নির্দিষ্ট ব্রডকাস্ট পাওয়ার জন্য অ্যাপ রেজিস্টার করতে পারে। কোনও ব্রডকাস্ট পাঠানো হলে, সেই নির্দিষ্ট ধরনের ব্রডকাস্ট পাওয়ার জন্য সাবস্ক্রাইব করা অ্যাপে সিস্টেম অটোমেটিক ব্রডকাস্ট রাউট করে দেয়।

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

সিস্টেম ব্রডকাস্ট সম্পর্কে

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

Intent অবজেক্ট ব্রডকাস্ট মেসেজকে র‍্যাপ করে। action স্ট্রিংটি ঘটে যাওয়া ইভেন্টকে শনাক্ত করে, যেমন android.intent.action.AIRPLANE_MODE। এছাড়াও, ইনটেন্টের অতিরিক্ত ফিল্ডে বান্ডেল করা অতিরিক্ত তথ্যও থাকতে পারে। যেমন, বিমান মোড ইনটেন্টে একটি বুলিয়ান এক্সট্রা থাকে যা বিমান মোড চালু আছে কিনা তা নির্দেশ করে।

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

সিস্টেম ব্রডকাস্ট অ্যাকশন

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

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

Android প্ল্যাটফর্মের উন্নতির সাথে সাথে, সিস্টেম ব্রডকাস্টের আচরণও সময়ে সময়ে পরিবর্তিত হয়। Android-এর সব ভার্সনে কাজ করার জন্য নিম্নলিখিত পরিবর্তনগুলি মনে রাখবেন।

Android 16

Android 16-এ, বিভিন্ন প্রসেস জুড়ে android:priority অ্যাট্রিবিউট বা IntentFilter.setPriority() ব্যবহার করে ব্রডকাস্ট ডেলিভারি অর্ডারের গ্যারান্টি দেওয়া হবে না। সম্প্রচার সংক্রান্ত অগ্রাধিকার শুধুমাত্র একই অ্যাপ্লিকেশন প্রসেসের মধ্যে বিবেচনা করা হয়, সব প্রসেস জুড়ে নয়।

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

Android 14

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

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

Android 9

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

আপনার অ্যাপ Android 9.0 (API লেভেল ২৮) বা তার চেয়ে উন্নত ভার্সন দ্বারা পরিচালিত ডিভাইসে ইনস্টল করা থাকলে, সিস্টেম ওয়াই-ফাই ব্রডকাস্টে SSID, BSSID, কানেকশন সংক্রান্ত তথ্য বা স্ক্যান ফলাফল অন্তর্ভুক্ত করে না। এই তথ্য পেতে, getConnectionInfo() নম্বরে কল করুন।

Android 8.0

Android 8.0 (API লেভেল ২৬) থেকে শুরু করে, সিস্টেম ম্যানিফেস্ট-ঘোষিত রিসিভারের উপর অতিরিক্ত বিধিনিষেধ আরোপ করে।

আপনার অ্যাপ Android 8.0 বা তার পরবর্তী যেকোনও ভার্সনকে টার্গেট করলে, বেশিরভাগ ইমপ্লিসিট ব্রডকাস্টের (যেসব ব্রডকাস্ট আপনার অ্যাপকে নির্দিষ্টভাবে টার্গেট করে না) জন্য রিসিভার ঘোষণা করতে আপনি ম্যানিফেস্ট ব্যবহার করতে পারবেন না। ব্যবহারকারী আপনার অ্যাপ সক্রিয়ভাবে ব্যবহার করার সময়ও আপনি কন্টেক্সট-রেজিস্টার করা রিসিভার ব্যবহার করতে পারবেন।

Android 7.0

Android 7.0 (API লেভেল ২৪) এবং তার পরবর্তী ভার্সন নিম্নলিখিত সিস্টেম ব্রডকাস্ট পাঠায় না:

এছাড়াও, Android 7.0 এবং তার পরবর্তী যেকোনও ভার্সনকে টার্গেট করা অ্যাপকে অবশ্যই registerReceiver(BroadcastReceiver, IntentFilter) ব্যবহার করে CONNECTIVITY_ACTION ব্রডকাস্ট রেজিস্টার করতে হবে। ম্যানিফেস্টে রিসিভার ঘোষণা করা কাজ করে না।

ব্রডকাস্ট পাওয়া

অ্যাপ দুটি উপায়ে ব্রডকাস্ট পেতে পারে: কনটেক্সট-রেজিস্টার করা রিসিভার এবং ম্যানিফেস্ট-ঘোষিত রিসিভারের মাধ্যমে।

প্রসঙ্গ-রেজিস্টার করা রিসিভার

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

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

  1. আপনার অ্যাপের মডিউল-লেভেল বিল্ড ফাইলে, AndroidX Core লাইব্রেরি-এর ভার্সন 1.9.0 বা তার পরবর্তী যেকোনও ভার্সন অন্তর্ভুক্ত করুন:

    খাঁজকাটা

    dependencies {
        def core_version = "1.19.1"
    
        // 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.19.1"
    
        // 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-এর একটি ইনস্ট্যান্স তৈরি করুন:

    Kotlin

    val myBroadcastReceiver = MyBroadcastReceiver()
    

    জাভা

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

    Kotlin

    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 ফ্ল্যাগ ব্যবহার করুন।

    Kotlin

    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() নম্বরে কল করে রিসিভার রেজিস্টার করুন:

    Kotlin

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

    জাভা

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

আপনার ব্রডকাস্ট রিসিভার আনরেজিস্টার করুন

ব্রডকাস্ট রিসিভার রেজিস্টার করা থাকাকালীন, এটি সেই Context-এর রেফারেন্স ধরে রাখে যার সাথে আপনি এটি রেজিস্টার করেছেন। রিসিভারের রেজিস্টার করা স্কোপ Context লাইফসাইকেল স্কোপের থেকে বেশি হলে, এটি সম্ভাব্য লিক ঘটাতে পারে। যেমন, আপনি কোনও অ্যাক্টিভিটি স্কোপে রিসিভার রেজিস্টার করলে, কিন্তু সিস্টেম অ্যাক্টিভিটি নষ্ট করার সময় আপনি এটি আনরেজিস্টার করতে ভুলে গেলে এটি ঘটতে পারে। তাই, সবসময় আপনার ব্রডকাস্ট রিসিভার আনরেজিস্টার করুন।

Kotlin

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) প্রয়োগ করুন। নিচে দেওয়া লগের উদাহরণে ব্রডকাস্ট রিসিভার ব্রডকাস্টের কন্টেন্ট দেখায়:

    Kotlin

    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); }
            }
        }
    }
    

অ্যাপ ইনস্টল করার সময় সিস্টেম প্যাকেজ ম্যানেজার রিসিভারকে রেজিস্টার করে। The receiver then becomes a separate entry point into your app which means that the system can start the app and deliver the broadcast if the app is not running.

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

প্রসেসের স্ট্যাটাসের উপর প্রভাব

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

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

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

ব্রডকাস্ট পাঠান

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

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

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

Kotlin

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> ট্যাগ সহ অনুমতির জন্য অনুরোধ করেছেন। অনুমতি বিপজ্জনক হলে, ব্রডকাস্ট গ্রহণকারীর ব্রডকাস্ট পাওয়ার আগে আপনাকে অবশ্যই অনুমতি দিতে হবে। যেমন, নিম্নলিখিত কোডটি অনুমতি সহ একটি ব্রডকাস্ট পাঠায়:

Kotlin

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> এলিমেন্টের মাধ্যমে কাস্টম অনুমতি নির্ধারণ করতে পারেন। সাধারণভাবে অনুমতি ও নিরাপত্তা সম্পর্কে তথ্য পেতে, সিস্টেমের অনুমতি দেখুন।

অনুমতি সহ ব্রডকাস্ট পাওয়া

আপনি যদি ব্রডকাস্ট রিসিভার রেজিস্টার করার সময় কোনও অনুমতির প্যারামিটার উল্লেখ করেন (আপনার ম্যানিফেস্টে 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>

অথবা আপনার গ্রহণকারী অ্যাপে নিম্নলিখিতভাবে একটি কন্টেক্সট-রেজিস্টার্ড রিসিভার আছে:

Kotlin

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" />

একই প্রসেসের মধ্যে ব্রডকাস্ট এড়িয়ে চলুন

ব্রডকাস্টকে বিভিন্ন অ্যাপ জুড়ে বা সিস্টেম ও অ্যাপের মধ্যে মেসেজ পাঠানোর জন্য ইন্টারপ্রসেস কমিউনিকেশন (IPC) মেকানিজম হিসেবে ডিজাইন করা হয়েছে। সেল্ফ-ব্রডকাস্ট পাঠানো, যা এমন একটি ব্রডকাস্ট যার জন্য সব প্রাপক একই প্রসেসে রান করে যা ব্রডকাস্ট পাঠিয়েছে, এটি খুবই অদক্ষ, অপ্রয়োজনীয় সিস্টেম ওভারহেড তৈরি করে এবং এটি করার জন্য কঠোরভাবে নিরুৎসাহিত করা হয়।

দুটি সাধারণ পরিস্থিতি যেখানে অ্যাপ নিজেকে ব্রডকাস্ট পাঠায়:

  • একই প্রসেসে কম্পোনেন্টগুলির মধ্যে যোগাযোগ করা: যেমন, অ্যাক্টিভিটি, ফ্র্যাগমেন্ট, পরিষেবা বা ব্যাকগ্রাউন্ড থ্রেডের মধ্যে ইভেন্ট বা ডেটা পাস করা। ব্রডকাস্ট পাঠানোর পরিবর্তে, স্ট্যান্ডার্ড ইন-প্রসেস যোগাযোগের মেকানিজম ব্যবহার করুন, যেমন অবজার্ভার প্যাটার্ন বা রিঅ্যাক্টিভ স্ট্রিম:

    • Kotlin Flows (SharedFlow ও StateFlow): আপনার অ্যাপের কোরাউটিন ও কম্পোনেন্ট জুড়ে ইভেন্ট স্ট্রিম বা স্টেট আপডেট এমিট ও পর্যবেক্ষণ করার জন্য Kotlin-এ একটি আধুনিক, ইডিওম্যাটিক সমাধান।
    • শেয়ার করা ViewModel: একই অ্যাক্টিভিটির মধ্যে বিভিন্ন UI কম্পোনেন্ট (যেমন, ফ্র্যাগমেন্ট বা কম্পোজ করার উপযুক্ত) এর মধ্যে ডেটা ও ইভেন্ট শেয়ার করার সুবিধা দেয়।
    • কলব্যাক ও লিসেনার: স্ট্যান্ডার্ড ইন্টারফেস কলব্যাক বা ফাংশন রেফারেন্স সরাসরি কম্পোনেন্টের মধ্যে পাস করা হয় অথবা সেন্ট্রাল রিপোজিটরি বা কন্ট্রোলারের সাথে রেজিস্টার করা হয়।
  • সিস্টেম ইভেন্ট, কাজ বা অ্যালার্ম ম্যানেজ করা: যেমন, শিডিউল করা কাজ, অ্যালার্ম বা সিস্টেম কলব্যাক রিসিভ করা এবং তারপরে আসল কাজ ট্রিগার করার জন্য ব্রডকাস্ট পাঠানো। ব্রডকাস্ট পাঠানোর পরিবর্তে, সরাসরি সেই কাজের মধ্যে কাজ সম্পূর্ণ করুন (যেমন JobService বা WorkManager কর্মী), অ্যালার্ম হ্যান্ডলার বা সিস্টেম কলব্যাক কম্পোনেন্ট, অথবা সরাসরি আপনার অ্যাপের বিজনেস লজিক ক্লাসে ডেলিগেট করুন।

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

অ্যাপ কম্পোনেন্টের মধ্যে কমিউনিকেশন ডিজাইন করার ব্যাপারে আরও তথ্যের জন্য, অ্যাপ আর্কিটেকচার সংক্রান্ত নির্দেশিকা দেখুন।

নিরাপত্তা সংক্রান্ত বিষয়

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

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

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

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

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

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

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