مروری بر پخش ها

برنامه‌های Android، مشابه الگوی طراحی انتشار-اشتراک، پیام‌های پخش را از سیستم Android و سایر برنامه‌های Android ارسال و دریافت می‌کنند. سیستم و برنامه‌ها معمولاً زمانی که رویدادهای خاصی رخ می‌دهند، پخش را ارسال می‌کنند. به عنوان مثال، سیستم Android زمانی که رویدادهای مختلف سیستم مانند بوت شدن سیستم یا شارژ دستگاه رخ می دهد، پخش ها را ارسال می کند. برنامه‌ها همچنین پخش‌های سفارشی را ارسال می‌کنند، برای مثال، برای اطلاع دادن به برنامه‌های دیگر از چیزی که ممکن است مورد علاقه آنها باشد (مثلاً دانلود داده‌های جدید).

برنامه ها می توانند برای دریافت پخش های خاص ثبت نام کنند. هنگامی که یک پخش ارسال می شود، سیستم به طور خودکار پخش را به برنامه هایی هدایت می کند که برای دریافت آن نوع پخش خاص مشترک شده اند.

به طور کلی، پخش ها می توانند به عنوان یک سیستم پیام رسانی در بین برنامه ها و خارج از جریان عادی کاربر استفاده شوند. با این حال، باید مراقب باشید که از فرصت پاسخگویی به پخش‌ها و اجرای کارهایی در پس‌زمینه که می‌توانند به کندی عملکرد سیستم کمک کنند، سوء استفاده نکنید.

درباره پخش های سیستمی

هنگامی که رویدادهای مختلف سیستم رخ می دهد، مانند زمانی که سیستم در حالت هواپیما قرار می گیرد و از حالت هواپیما خارج می شود، سیستم به طور خودکار پخش را ارسال می کند. همه برنامه های مشترک این پخش ها را دریافت می کنند.

شی Intent پیام پخش شده را می پیچد. رشته action رویدادی را که رخ داده است، مانند android.intent.action.AIRPLANE_MODE را شناسایی می کند. این هدف همچنین ممکن است شامل اطلاعات اضافی همراه با فیلد اضافی آن باشد. به عنوان مثال، هدف حالت هواپیما شامل یک بولی اضافی است که نشان می دهد که آیا حالت هواپیما روشن است یا خیر.

برای اطلاعات بیشتر در مورد نحوه خواندن intent ها و دریافت رشته عملکرد از یک intent، به Intent و Intent Filters مراجعه کنید.

اقدامات پخش سیستم

برای فهرست کامل اقدامات پخش سیستم، فایل BROADCAST_ACTIONS.TXT را در Android SDK ببینید. هر اقدام پخش دارای یک فیلد ثابت مرتبط با آن است. برای مثال، مقدار ثابت ACTION_AIRPLANE_MODE_CHANGED android.intent.action.AIRPLANE_MODE است. اسناد برای هر اقدام پخش در فیلد ثابت مرتبط با آن موجود است.

تغییرات در پخش سیستم

همانطور که پلت فرم اندروید تکامل می یابد، به طور دوره ای نحوه رفتار پخش سیستم را تغییر می دهد. برای پشتیبانی از تمامی نسخه های اندروید، تغییرات زیر را در نظر داشته باشید.

اندروید 14

در حالی که برنامه‌ها در حالت حافظه پنهان هستند، سیستم تحویل پخش را برای سلامت سیستم بهینه می‌کند. برای مثال، زمانی که برنامه در حالت حافظه پنهان است، سیستم پخش‌های کمتر مهم سیستم مانند ACTION_SCREEN_ON را به تعویق می‌اندازد. هنگامی که برنامه از حالت حافظه پنهان به چرخه حیات فرآیند فعال می‌رود، سیستم هر گونه پخش معوقی را ارائه می‌کند.

پخش‌های مهمی که در مانیفست اعلام می‌شوند، موقتاً برنامه‌ها را برای تحویل از حالت حافظه پنهان حذف می‌کنند.

اندروید 9

با شروع Android 9 (سطح API 28)، پخش NETWORK_STATE_CHANGED_ACTION اطلاعاتی درباره مکان کاربر یا داده‌های قابل شناسایی شخصی دریافت نمی‌کند.

اگر برنامه شما روی دستگاهی با Android نسخه 9.0 (سطح API 28) یا بالاتر نصب شده است، سیستم شامل SSID، BSSID، اطلاعات اتصال یا نتایج اسکن در پخش‌های Wi-Fi نمی‌شود. برای دریافت این اطلاعات، به جای آن getConnectionInfo() را فراخوانی کنید.

اندروید 8.0

با شروع Android 8.0 (سطح API 26)، این سیستم محدودیت‌های بیشتری را بر گیرنده‌های اعلام شده توسط مانیفست اعمال می‌کند.

اگر برنامه شما Android 8.0 یا بالاتر را هدف قرار می دهد، نمی توانید از مانیفست برای اعلام گیرنده برای اکثر پخش های ضمنی (پخش هایی که به طور خاص برنامه شما را هدف قرار نمی دهند) استفاده کنید. هنگامی که کاربر به طور فعال از برنامه شما استفاده می کند، همچنان می توانید از یک گیرنده ثبت شده در زمینه استفاده کنید.

اندروید 7.0

Android 7.0 (سطح API 24) و بالاتر، پخش‌های سیستمی زیر را ارسال نکنید:

همچنین، برنامه‌هایی که Android نسخه ۷.۰ و بالاتر را هدف قرار می‌دهند، باید پخش CONNECTIVITY_ACTION را با استفاده از registerReceiver(BroadcastReceiver, IntentFilter) ثبت کنند. اعلام یک گیرنده در مانیفست کار نمی کند.

پخش ها را دریافت کنید

برنامه ها می توانند پخش ها را به دو صورت دریافت کنند: از طریق گیرنده های ثبت شده در زمینه و گیرنده های اعلام شده توسط مانیفست.

گیرنده های ثبت شده در زمینه

گیرنده های ثبت شده در زمینه تا زمانی که زمینه ثبت آنها معتبر باشد، پخش را دریافت می کنند. این معمولاً بین تماس های registerReceiver و unregisterReceiver است. زمینه ثبت نام نیز زمانی که سیستم زمینه مربوطه را از بین می برد، نامعتبر می شود. به عنوان مثال، اگر در یک زمینه Activity ثبت نام کنید، تا زمانی که فعالیت فعال باقی بماند، پخش را دریافت خواهید کرد. اگر در زمینه برنامه ثبت نام کنید، تا زمانی که برنامه اجرا می شود، پخش ها را دریافت خواهید کرد.

برای ثبت یک گیرنده با زمینه، مراحل زیر را انجام دهید:

  1. در فایل ساخت ماژول برنامه خود، نسخه 1.9.0 یا بالاتر از کتابخانه AndroidX Core را قرار دهید:

    شیار

    dependencies {
        def core_version = "1.13.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.0.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-alpha02"
    }

    کاتلین

    dependencies {
        val core_version = "1.13.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.0.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-alpha02")
    }
  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) تماس بگیرید. زمانی که گیرنده دیگر به آن نیاز ندارید یا متن دیگر معتبر نیست، حتماً ثبت نام را لغو کنید.

گیرنده پخش خود را لغو ثبت کنید

در حالی که گیرنده پخش ثبت شده است، ارجاعی به زمینه ای دارد که شما آن را با آن ثبت کرده اید. اگر محدوده ثبت شده گیرنده از محدوده چرخه حیات Context فراتر رود، به طور بالقوه می تواند باعث نشت شود. به عنوان مثال، این ممکن است زمانی رخ دهد که یک گیرنده را در یک محدوده Activity ثبت می کنید، اما فراموش می کنید که زمانی که سیستم Activity را از بین می برد، آن را لغو ثبت کنید. بنابراین، همیشه گیرنده پخش خود را لغو ثبت کنید.

کاتلین

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 : گیرنده پخش فقط زمانی که composable در درخت ترکیب قرار دارد به‌روزرسانی‌ها را دریافت می‌کند. این محدوده به محدوده چرخه حیات فعالیت متصل نیست. ثبت گیرنده در زمینه برنامه را در نظر بگیرید. این به این دلیل است که ترکیب‌پذیر می‌تواند از نظر تئوری بیش از محدوده چرخه حیات فعالیت داشته باشد و فعالیت را نشت کند.
  • Activity onCreate / onDestroy : گیرنده پخش به‌روزرسانی‌ها را در حالی که فعالیت در حالت ایجاد شده است دریافت می‌کند. مطمئن شوید که در onDestroy() و نه onSaveInstanceState(Bundle) ثبت نام را لغو کرده اید زیرا ممکن است این نام خوانده نشود.
  • یک محدوده سفارشی: برای مثال، می‌توانید یک گیرنده را در محدوده ViewModel خود ثبت کنید، بنابراین از فعالیت‌های تفریحی جان سالم به در می‌برد. اطمینان حاصل کنید که از زمینه برنامه برای ثبت گیرنده استفاده می کنید، زیرا گیرنده می تواند بیش از محدوده چرخه حیات فعالیت داشته باشد و فعالیت را افشا کند.

قابلیت ترکیب حالت و بدون حالت ایجاد کنید

Compose دارای انشاپذیرهای حالت دار و بدون حالت است. ثبت یا لغو ثبت یک گیرنده پخش در داخل یک Composable آن را حالت حالت می کند. Composable یک تابع قطعی نیست که محتوای یکسانی را در صورت ارسال پارامترهای یکسان ارائه دهد. وضعیت داخلی می تواند بر اساس تماس با گیرنده پخش ثبت شده تغییر کند.

به عنوان بهترین روش در Compose، توصیه می‌کنیم که composable‌های خود را به نسخه‌های Stateful و Stateless تقسیم کنید. بنابراین، توصیه می‌کنیم که ایجاد گیرنده پخش را از یک Composable خارج کنید تا حالت بی‌حالت نداشته باشد:

@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. Subclass 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() گیرنده را اجرا می کند. سیستم فرآیند را به جز تحت فشار شدید حافظه اجرا می کند.

سیستم BroadcastReceiver بعد از onReceive() غیرفعال می کند. اهمیت فرآیند میزبان گیرنده به اجزای برنامه آن بستگی دارد. اگر آن فرآیند فقط یک گیرنده اعلام شده توسط مانیفست را میزبانی کند، سیستم ممکن است پس از onReceive() آن را بکشد تا منابعی برای سایر فرآیندهای حیاتی‌تر آزاد کند. این برای برنامه‌هایی که کاربر هرگز با آنها تعامل نداشته یا اخیراً با آن‌ها تعامل نداشته است، رایج است.

بنابراین، گیرنده های پخش نباید رشته های پس زمینه طولانی مدت را شروع کنند. سیستم می تواند در هر لحظه پس از onReceive() فرآیند را متوقف کند تا حافظه را بازیابی کند و رشته ایجاد شده را خاتمه دهد. برای زنده نگه داشتن فرآیند، یک JobService از گیرنده با استفاده از JobScheduler برنامه ریزی کنید تا سیستم بداند که این فرآیند هنوز کار می کند. Background Work Overview جزئیات بیشتری را ارائه می دهد.

ارسال پخش

اندروید دو راه را برای برنامه ها برای ارسال پخش ارائه می دهد:

  • روش sendOrderedBroadcast(Intent, String) پخش ها را در یک زمان به یک گیرنده ارسال می کند. همانطور که هر گیرنده به نوبه خود اجرا می شود، می تواند نتیجه را به گیرنده بعدی منتقل کند. همچنین می تواند پخش را به طور کامل قطع کند تا به گیرنده های دیگر نرسد. شما می توانید ترتیب عملکرد گیرنده ها را کنترل کنید. برای انجام این کار، از ویژگی android:priority فیلتر قصد منطبق استفاده کنید. گیرنده های با همان اولویت به ترتیب دلخواه اجرا می شوند.
  • روش sendBroadcast(Intent) پخش ها را به ترتیب نامشخصی به همه گیرنده ها ارسال می کند. به این یک پخش عادی می گویند. این کارآمدتر است، اما به این معنی است که گیرنده‌ها نمی‌توانند نتایج گیرنده‌های دیگر را بخوانند، داده‌های دریافتی از پخش را منتشر کنند، یا پخش را متوقف کنند.

قطعه کد زیر نحوه ارسال یک پخش را با ایجاد 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 intent باید نحو نام بسته جاوای برنامه را ارائه کند و رویداد پخش را به طور منحصربه‌فرد شناسایی کند. با putExtra(String, Bundle) می توانید اطلاعات بیشتری را به intent پیوست کنید. همچنین می‌توانید با فراخوانی setPackage(String) روی intent، پخش را به مجموعه‌ای از برنامه‌ها در همان سازمان محدود کنید.

محدود کردن پخش با مجوز

مجوزها به شما این امکان را می دهند که پخش را به مجموعه برنامه هایی که دارای مجوزهای خاصی هستند محدود کنید. می توانید محدودیت هایی را برای فرستنده یا گیرنده پخش اعمال کنید.

ارسال پخش با مجوز

وقتی 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> تعریف کنید. برای اطلاعات در مورد مجوزها و امنیت به طور کلی، به مجوزهای سیستم مراجعه کنید.

دریافت پخش با مجوز

اگر هنگام ثبت یک گیرنده پخش، یک پارامتر مجوز را مشخص کنید (چه با registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) یا در برچسب <receiver> در مانیفست خود)، پس فقط پخش کنندگانی که مجوز را با <uses-permission> درخواست کرده اند. تگ در مانیفست آنها می تواند یک Intent را برای گیرنده ارسال کند. اگر مجوز خطرناک باشد، باید به پخش کننده هم مجوز داده شود.

به عنوان مثال، فرض کنید برنامه دریافت کننده شما دارای یک گیرنده اعلام شده توسط مانیفست به شرح زیر است:

<!-- 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 فقط به گیرنده های ثبت شده در زمینه ارائه می شود.

  • اطلاعات حساس را با هدف ضمنی پخش نکنید. هر برنامه ای در صورت ثبت نام برای دریافت پخش، می تواند اطلاعات را بخواند. سه راه برای کنترل اینکه چه کسی می تواند پخش شما را دریافت کند وجود دارد:

    • هنگام ارسال پخش، می توانید مجوزی را تعیین کنید.
    • در اندروید 4.0 (سطح API 14) و بالاتر، می‌توانید هنگام ارسال پخش، بسته‌ای را با setPackage(String) مشخص کنید. سیستم پخش را به مجموعه برنامه هایی که با بسته مطابقت دارند محدود می کند.
  • هنگامی که یک گیرنده را ثبت می کنید، هر برنامه ای می تواند پخش های مخرب احتمالی را به گیرنده برنامه شما ارسال کند. راه های مختلفی برای محدود کردن پخش هایی که برنامه شما دریافت می کند وجود دارد:

    • هنگام ثبت یک گیرنده پخش، می توانید مجوزی را تعیین کنید.
    • برای گیرنده‌های اعلام‌شده با مانیفست، می‌توانید ویژگی android:exported را روی «false» در مانیفست تنظیم کنید. گیرنده پخش را از منابع خارج از برنامه دریافت نمی کند.
  • فضای نام برای اقدامات پخش جهانی است. مطمئن شوید که نام اکشن ها و رشته های دیگر در فضای نامی که متعلق به شماست نوشته شده باشد. در غیر این صورت، ممکن است به طور ناخواسته با برنامه های دیگر تداخل داشته باشید.

  • از آنجایی که متد onReceive(Context, Intent) گیرنده روی رشته اصلی اجرا می شود، باید به سرعت اجرا شود و برگردد. اگر نیاز به انجام کارهای طولانی مدت دارید، مراقب ایجاد رشته ها یا راه اندازی خدمات پس زمینه باشید زیرا سیستم می تواند کل فرآیند را پس از بازگشت onReceive() از بین ببرد. برای اطلاعات بیشتر، به تأثیر بر وضعیت فرآیند مراجعه کنید برای انجام کارهای طولانی مدت، توصیه می کنیم:

    • فراخوانی goAsync() در متد onReceive() گیرنده و ارسال BroadcastReceiver.PendingResult به رشته پس زمینه. این امر پخش را پس از بازگشت از onReceive() فعال نگه می دارد. با این حال، حتی با این رویکرد، سیستم انتظار دارد که پخش را خیلی سریع (زیر 10 ثانیه) به پایان برسانید. این به شما امکان می‌دهد کار را به رشته‌ای دیگر منتقل کنید تا از مشکل در رشته اصلی جلوگیری کنید.
    • برنامه ریزی یک کار با JobScheduler . برای اطلاعات بیشتر، برنامه‌ریزی هوشمند شغلی را ببینید.
  • فعالیت‌ها را از گیرنده‌های پخش شروع نکنید زیرا تجربه کاربر آزاردهنده است. به خصوص اگر بیش از یک گیرنده وجود داشته باشد. در عوض، نمایش یک اعلان را در نظر بگیرید.