Tổng quan về truyền tin

Các ứng dụng Android có thể gửi hoặc nhận thông báo phát đi từ hệ thống Android và các ứng dụng Android khác, tương tự như xuất bản-đăng ký mẫu thiết kế. Những thông báo này được gửi khi một sự kiện quan tâm xảy ra. Ví dụ: hệ thống Android gửi thông báo khi các sự kiện hệ thống khác nhau xảy ra, chẳng hạn như khi hệ thống khởi động hoặc thiết bị bắt đầu sạc. Chiến dịch Quảng cáo ứng dụng cũng có thể gửi thông báo truyền tin tuỳ chỉnh, chẳng hạn như để thông báo cho các ứng dụng khác về điều gì đó mà họ có thể quan tâm (ví dụ: một số dữ liệu mới đã tải xuống).

Hệ thống tối ưu hoá việc phân phối tin truyền để duy trì tình trạng hệ thống tối ưu. Do đó, thời gian phân phối của thông báo không được được đảm bảo. Các ứng dụng cần giao tiếp liên quy trình có độ trễ thấp nên hãy cân nhắc đến các dịch vụ ràng buộc.

Các ứng dụng có thể đăng ký nhận các thông báo truyền tin cụ thể. Khi thông báo được gửi đi, hệ thống tự động định tuyến thông báo truyền phát đến các ứng dụng đã đăng ký nhận loại tin truyền phát cụ thể đó.

Nói chung, thông báo có thể được dùng làm hệ thống nhắn tin trên các ứng dụng và nằm ngoài luồng người dùng thông thường. Tuy nhiên, bạn phải cẩn thận để không lạm dụng cơ hội phản hồi các thông báo truyền tin và chạy các công việc trong nền có thể khiến hệ thống hoạt động chậm.

Giới thiệu về thông báo của hệ thống

Hệ thống tự động gửi thông báo khi các sự kiện hệ thống khác nhau diễn ra, chẳng hạn như khi hệ thống chuyển vào và thoát khỏi chế độ trên máy bay. Hệ thống thông báo truyền tin sẽ được gửi đến tất cả ứng dụng đã đăng ký nhận sự kiện.

Thông báo phát đi được gói trong một Intent đối tượng có chuỗi hành động xác định sự kiện đã xảy ra (ví dụ: android.intent.action.AIRPLANE_MODE). Ý định cũng có thể bao gồm thông tin bổ sung được nhóm vào trường bổ sung. Ví dụ: máy bay ý định của chế độ bao gồm một thuộc tính boolean bổ sung cho biết liệu Máy bay có phải là Máy bay hay không Chế độ đang bật.

Để biết thêm thông tin về cách đọc ý định và lấy chuỗi hành động từ về một ý định, hãy xem phần Ý định và ý định Bộ lọc.

Để biết danh sách đầy đủ các thao tác truyền tin của hệ thống, hãy xem BROADCAST_ACTIONS.TXT trong SDK Android. Mỗi hành động truyền tin có một trường không đổi liên kết với trường đó. Ví dụ: giá trị của hằng số ACTION_AIRPLANE_MODE_CHANGEDandroid.intent.action.AIRPLANE_MODE Tài liệu cho từng hành động truyền tin có sẵn trong trường hằng số liên kết.

Thay đổi đối với thông báo của hệ thống

Khi nền tảng Android phát triển, nền tảng này sẽ định kỳ thay đổi cách hệ thống truyền tin hành xử. Hãy lưu ý những thay đổi sau để hỗ trợ tất cả phiên bản Android.

Android 14

Khi các ứng dụng đang ở trong bộ nhớ đệm trạng thái, phân phối tin truyền phát là được tối ưu hoá để cải thiện tình trạng hệ thống. Ví dụ: các thông báo truyền tin ít quan trọng hơn là với tên ACTION_SCREEN_ON bị trì hoãn khi ứng dụng đang ở trạng thái đã lưu vào bộ nhớ đệm. Sau khi ứng dụng chuyển từ bộ nhớ đệm trạng thái thành quá trình hoạt động vòng đời, hệ thống sẽ phân phối bất kỳ thông báo truyền phát bị trì hoãn nào.

Thông báo truyền tin quan trọng được khai báo trong tệp kê khai tạm thời xóa các ứng dụng khỏi bộ nhớ đệm để phân phối.

Android 9

Kể từ Android 9 (API cấp 28), NETWORK_STATE_CHANGED_ACTION thông báo truyền tin không nhận được thông tin về vị trí hoặc thông tin cá nhân của người dùng dữ liệu nhận dạng cá nhân.

Ngoài ra, nếu ứng dụng được cài đặt trên một thiết bị chạy Android 9 trở lên, thông báo của hệ thống từ Wi-Fi không chứa SSID, BSSID, kết nối hoặc quét kết quả. Để nhận thông tin này, hãy gọi getConnectionInfo() thay thế.

Android 8.0

Kể từ Android 8.0 (API cấp 26), hệ thống áp dụng thêm các chế độ cài đặt đối với các dịch vụ nhận đã khai báo trong tệp kê khai.

Nếu ứng dụng của bạn nhắm đến Android 8.0 trở lên, bạn không thể sử dụng tệp kê khai để khai báo trình nhận cho hầu hết các thông báo truyền tin ngầm ẩn (thông báo truyền tin không nhắm mục tiêu) ứng dụng của bạn). Bạn vẫn có thể sử dụng bộ nhận đăng ký theo bối cảnh khi người dùng đang tích cực sử dụng ứng dụng của bạn.

Android 7.0

Android 7.0 (API cấp 24) trở lên không gửi hệ thống sau thông báo truyền tin:

Ngoài ra, các ứng dụng nhắm đến Android 7.0 trở lên phải đăng ký thông báo truyền tin CONNECTIVITY_ACTION đang sử dụng registerReceiver(BroadcastReceiver, IntentFilter). Việc khai báo trình nhận trong tệp kê khai không hoạt động.

Đang nhận thông báo truyền tin

Ứng dụng có thể nhận thông báo truyền tin theo hai cách: thông qua dịch vụ nhận đã khai báo trong tệp kê khai và bộ thu đã đăng ký theo bối cảnh.

Trình nhận được khai báo trong tệp kê khai

Nếu bạn khai báo broadcast receiver trong tệp kê khai của mình, hệ thống sẽ khởi chạy ứng dụng (nếu ứng dụng chưa chạy) khi thông báo truyền tin được gửi.

Để khai báo broadcast receiver trong tệp kê khai, hãy thực hiện các bước sau:

  1. Chỉ định <receiver> trong tệp kê khai của ứng dụng.

    <!-- 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="APP_SPECIFIC_BROADCAST" />
        </intent-filter>
    </receiver>
    

    Bộ lọc ý định chỉ định các hành động truyền tin mà bộ thu của bạn đăng ký.

  2. Lớp con BroadcastReceiver và triển khai onReceive(Context, Intent). Chiến lược phát hành đĩa đơn broadcast receiver trong nhật ký mẫu sau đây và hiển thị nội dung của chương trình phát sóng:

    Kotlin

    private const val TAG = "MyBroadcastReceiver"
    
    class MyBroadcastReceiver : BroadcastReceiver() {
    
        override fun onReceive(context: Context, intent: Intent) {
            StringBuilder().apply {
                append("Action: ${intent.action}\n")
                append("URI: ${intent.toUri(Intent.URI_INTENT_SCHEME)}\n")
                toString().also { log ->
                    Log.d(TAG, log)
    
                    val binding = ActivityNameBinding.inflate(layoutInflater)
                    val view = binding.root
                    setContentView(view)
    
                    Snackbar.make(view, log, Snackbar.LENGTH_LONG).show()
                }
            }
        }
    }
    

    Java

    public class MyBroadcastReceiver extends BroadcastReceiver {
            private static final String TAG = "MyBroadcastReceiver";
            @Override
            public void onReceive(Context context, Intent intent) {
                StringBuilder sb = new StringBuilder();
                sb.append("Action: " + intent.getAction() + "\n");
                sb.append("URI: " + intent.toUri(Intent.URI_INTENT_SCHEME).toString() + "\n");
                String log = sb.toString();
                Log.d(TAG, log);
    
                ActivityNameBinding binding =
                        ActivityNameBinding.inflate(layoutInflater);
                val view = binding.root;
                setContentView(view);
    
                Snackbar.make(view, log, Snackbar.LENGTH_LONG).show();
            }
        }
    

    Để bật tính năng liên kết thành phần hiển thị, định cấu hình viewBinding ở cấp mô-đun tệp build.gradle.

Trình quản lý gói hệ thống đăng ký trình nhận khi ứng dụng được cài đặt. Sau đó, receiver sẽ trở thành một điểm truy cập riêng vào ứng dụng của bạn, tức là hệ thống có thể khởi động ứng dụng và phân phối thông báo truyền tin nếu ứng dụng không hiện đang chạy.

Hệ thống tạo một thành phần BroadcastReceiver mới để xử lý từng thông báo truyền tin mà đối tượng đó nhận được. Đối tượng này chỉ hợp lệ trong thời lượng của lệnh gọi đến onReceive(Context, Intent). Sau khi mã trả về từ phương thức này, hệ thống sẽ coi thành phần không còn đang hoạt động.

Bộ nhận đã đăng ký theo bối cảnh

Bộ thu đã đăng ký theo bối cảnh sẽ nhận thông báo, miễn là ngữ cảnh là hợp lệ. Ví dụ: nếu bạn đăng ký trong một Activity ngữ cảnh, bạn sẽ nhận được thông báo miễn là hoạt động không bị huỷ bỏ. Nếu bạn đăng ký với ngữ cảnh Ứng dụng, bạn sẽ nhận được thông báo truyền tin miễn là ứng dụng đang chạy.

Để đăng ký trình nhận bằng ngữ cảnh, hãy thực hiện các bước sau:

  1. Trong tệp bản dựng cấp mô-đun của ứng dụng, hãy thêm phiên bản 1.9.0 trở lên của thư viện AndroidX Core:

    Groovy

    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-alpha01"
    }
    

    Kotlin

    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-alpha01")
    }
    
  2. Tạo một thực thể của BroadcastReceiver:

    Kotlin

    val br: BroadcastReceiver = MyBroadcastReceiver()
    

    Java

    BroadcastReceiver br = new MyBroadcastReceiver();
    
  3. Tạo một thực thể của IntentFilter:

    Kotlin

    val filter = IntentFilter(APP_SPECIFIC_BROADCAST)
    

    Java

    IntentFilter filter = new IntentFilter(APP_SPECIFIC_BROADCAST);
    
  4. Chọn xem có xuất và hiển thị broadcast receiver với các ứng dụng khác trên thiết bị. Nếu receiver này đang nghe các thông báo truyền tin đã gửi từ hệ thống hoặc từ các ứng dụng khác (ngay cả những ứng dụng khác mà bạn sở hữu) hãy sử dụng Cờ RECEIVER_EXPORTED. Nếu thay vào đó, bộ thu này chỉ nghe thông báo truyền tin do ứng dụng của bạn gửi, hãy sử dụng cờ RECEIVER_NOT_EXPORTED.

    Kotlin

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

    Java

    boolean listenToBroadcastsFromOtherApps = false;
    if (listenToBroadcastsFromOtherApps) {
        receiverFlags = ContextCompat.RECEIVER_EXPORTED;
    } else {
        receiverFlags = ContextCompat.RECEIVER_NOT_EXPORTED;
    }
    
  5. Đăng ký receiver bằng cách gọi registerReceiver():

    Kotlin

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

    Java

    ContextCompat.registerReceiver(context, br, filter, receiverFlags);
    
  6. Để ngừng nhận thông báo truyền tin, hãy gọi unregisterReceiver(android.content.BroadcastReceiver). Hãy nhớ huỷ đăng ký trình nhận khi bạn không còn cần đến hoặc ngữ cảnh không còn hợp lệ.

    Hãy chú ý đến nơi bạn đăng ký và huỷ đăng ký người nhận, vì ví dụ: nếu đăng ký trình nhận trong onCreate(Bundle) bằng cách sử dụng ngữ cảnh của hoạt động, bạn nên huỷ đăng ký trong onDestroy() để ngăn rò rỉ trình thu nhận ra khỏi ngữ cảnh hoạt động. Nếu bạn đăng ký là một receiver trong onResume(), bạn nên huỷ đăng ký trong onPause() để ngăn đăng ký nó nhiều lần (Nếu bạn không muốn nhận thông báo khi bị tạm dừng và điều này có thể làm giảm chi phí hệ thống không cần thiết). Không nên huỷ đăng ký trong onSaveInstanceState(Bundle), vì lệnh này không được gọi nếu người dùng quay lại ngăn xếp nhật ký.

Ảnh hưởng đến trạng thái quy trình

Cho dù BroadcastReceiver của bạn đang hoạt động hoặc không ảnh hưởng đến quá trình chứa trong đó, điều này có thể làm thay đổi khả năng hạ gục hệ thống. Quy trình trên nền trước sẽ thực thi phương thức onReceive() của trình nhận. Chiến lược phát hành đĩa đơn hệ thống sẽ chạy quy trình này ngoại trừ áp lực bộ nhớ cực kỳ nghiêm trọng.

BroadcastReceiver bị huỷ kích hoạt sau onReceive(). Máy chủ lưu trữ của người nhận chỉ có ý nghĩa quan trọng như các thành phần ứng dụng. Nếu quá trình đó chỉ lưu trữ trình thu nhận được khai báo trong tệp kê khai (điều này thường xảy ra đối với các ứng dụng mà người dùng chưa bao giờ hoặc chưa tương tác gần đây), hệ thống có thể tắt sau onReceive() để khiến sẵn có cho các quá trình quan trọng hơn khác.

Do đó, broadcast receiver không nên bắt đầu các luồng chạy trong nền trong thời gian dài. Hệ thống có thể dừng quá trình này bất cứ lúc nào sau ngày onReceive() để xác nhận lại quyền sở hữu bộ nhớ, chấm dứt luồng đã tạo. Để duy trì quy trình, hãy lên lịch JobService từ trình nhận bằng cách sử dụng JobScheduler để hệ thống biết là quá trình vẫn đang hoạt động. Bài viết Tổng quan về công việc ở chế độ nền cung cấp thêm thông tin chi tiết.

Đang gửi thông báo truyền phát

Android cung cấp 3 cách để ứng dụng gửi thông báo truyền tin:

  • sendOrderedBroadcast(Intent, String) sẽ gửi thông báo đến một trình thu nhận tại một thời điểm. Khi mỗi receiver thực thi nó có thể truyền kết quả đến trình thu nhận tiếp theo hoặc có thể huỷ hoàn toàn truyền phát để không truyền tới đầu thu. Trình nhận đơn đặt hàng chạy vào có thể được kiểm soát bằng android:Priority của bộ lọc ý định phù hợp; các receiver có cùng mức độ ưu tiên sẽ được chạy theo thứ tự tuỳ ý.
  • Phương thức sendBroadcast(Intent) sẽ gửi truyền tin đến tất cả các receiver theo thứ tự không xác định. Đây gọi là Thông thường Truyền phát. Phương thức này hiệu quả hơn nhưng có nghĩa là các receiver không thể đọc kết quả từ các receiver khác, truyền dữ liệu nhận được từ thông báo truyền tin, hoặc huỷ truyền phát.

Đoạn mã sau đây minh hoạ cách gửi thông báo truyền tin bằng cách tạo một Ý định và gọi sendBroadcast(Intent).

Kotlin

Intent().also { intent ->
    intent.setAction("com.example.broadcast.MY_NOTIFICATION")
    intent.putExtra("data", "Nothing to see here, move along.")
    sendBroadcast(intent)
}

Java

Intent intent = new Intent();
intent.setAction("com.example.broadcast.MY_NOTIFICATION");
intent.putExtra("data", "Nothing to see here, move along.");
sendBroadcast(intent);

Thông báo truyền tin được gói trong một đối tượng Intent. Chuỗi hành động của ý định phải cung cấp cú pháp tên gói Java của ứng dụng và xác định duy nhất sự kiện phát sóng. Bạn có thể đính kèm thông tin bổ sung cho ý định bằng putExtra(String, Bundle). Bạn cũng có thể giới hạn việc truyền tin đến một nhóm ứng dụng trong cùng một tổ chức bằng cách gọi setPackage(String) trên ý định.

Hạn chế thông báo truyền tin bằng quyền

Quyền cho phép bạn hạn chế thông báo truyền tin cho nhóm ứng dụng chứa một số quyền nhất định. Bạn có thể thực thi các hạn chế đối với người gửi hoặc trình nhận tín hiệu truyền tin.

Gửi bằng quyền

Khi bạn gọi sendBroadcast(Intent, String) hoặc sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle), bạn có thể chỉ định một tham số quyền. Chỉ những người nhận đã yêu cầu quyền đó bằng trong tệp kê khai của họ (và sau đó được cấp nếu nội dung đó nguy hiểm) có thể nhận được thông báo truyền tin. Ví dụ: mã sau đây sẽ gửi một thông báo truyền tin:

Kotlin

sendBroadcast(Intent(BluetoothDevice.ACTION_FOUND),
              Manifest.permission.BLUETOOTH_CONNECT)

Java

sendBroadcast(new Intent(BluetoothDevice.ACTION_FOUND),
              Manifest.permission.BLUETOOTH_CONNECT)

Để nhận thông báo truyền tin, ứng dụng nhận phải yêu cầu quyền như được hiển thị bên dưới:

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

Bạn có thể chỉ định quyền hệ thống hiện có như BLUETOOTH_CONNECT hoặc định nghĩa một quyền tuỳ chỉnh bằng thuộc tính Phần tử <permission>. Cho về quyền và bảo mật nói chung, hãy xem phần Hệ thống Quyền.

Nhận bằng quyền

Nếu bạn chỉ định một tham số quyền khi đăng ký broadcast receiver (bằng registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) hoặc trong Thẻ <receiver> trong ), thì chỉ những đài phát đã yêu cầu cấp quyền bằng Thẻ <uses-permission> trong tệp kê khai (và sau đó được cấp quyền nếu nguy hiểm) có thể gửi Ý định cho dịch vụ nhận.

Ví dụ: giả sử ứng dụng nhận dữ liệu của bạn có một receiver đã khai báo trong tệp kê khai là được hiển thị bên dưới:

<receiver android:name=".MyBroadcastReceiver"
          android:permission="android.permission.BLUETOOTH_CONNECT">
    <intent-filter>
        <action android:name="android.intent.action.ACTION_FOUND"/>
    </intent-filter>
</receiver>

Hoặc ứng dụng nhận dữ liệu của bạn có bộ nhận đã đăng ký theo bối cảnh như dưới đây:

Kotlin

var filter = IntentFilter(Intent.ACTION_FOUND)
registerReceiver(receiver, filter, Manifest.permission.BLUETOOTH_CONNECT, null )

Java

IntentFilter filter = new IntentFilter(Intent.ACTION_FOUND);
registerReceiver(receiver, filter, Manifest.permission.BLUETOOTH_CONNECT, null );

Sau đó, để có thể gửi thông báo truyền tin đến các receiver đó, ứng dụng gửi phải hãy yêu cầu quyền như trình bày dưới đây:

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

Các phương pháp hay nhất và những điều cần cân nhắc về bảo mật

Dưới đây là một số điểm cần cân nhắc về bảo mật và các phương pháp hay nhất khi gửi thư đang nhận thông báo truyền phát:

  • Nếu nhiều ứng dụng đã đăng ký nhận cùng một nội dung truyền phát trong tệp kê khai, nó có thể khiến hệ thống khởi chạy nhiều ứng dụng, gây ra ảnh hưởng đáng kể đến cả hiệu suất thiết bị và trải nghiệm người dùng. Cần tránh ưu tiên sử dụng quy trình đăng ký theo bối cảnh hơn là khai báo tệp kê khai. Đôi khi, chính hệ thống Android thực thi việc sử dụng dữ liệu đã đăng ký theo bối cảnh đầu thu. Ví dụ: thông báo truyền tin CONNECTIVITY_ACTION được phân phối chỉ cho bộ thu đã đăng ký theo bối cảnh.

  • Không được truyền thông tin nhạy cảm bằng ý định ngầm ẩn. Chiến lược phát hành đĩa đơn bất kỳ ứng dụng nào đã đăng ký nhận thông báo truyền tin đều có thể đọc thông tin này. Có ba cách để kiểm soát những ai có thể nhận thông báo của bạn:

    • Bạn có thể chỉ định một quyền khi gửi thông báo truyền tin.
    • Trong Android 4.0 trở lên, bạn có thể chỉ định package bằng setPackage(String) khi gửi một truyền tin. Hệ thống chỉ cho phép phát đi thông báo ở một nhóm ứng dụng khớp với gói.
  • Khi bạn đăng ký bộ nhận, bất kỳ ứng dụng nào cũng có thể gửi phần mềm độc hại tiềm ẩn truyền tin đến bộ thu của ứng dụng. Có một số cách để hạn chế thông báo truyền tin mà ứng dụng của bạn nhận được:

    • Bạn có thể chỉ định một quyền khi đăng ký broadcast receiver.
    • Đối với các trình thu nhận được khai báo trong tệp kê khai, bạn có thể đặt android:exported thuộc tính "false" trong tệp kê khai. Người nhận không nhận được thông báo truyền phát từ các nguồn bên ngoài ứng dụng.
  • Không gian tên dành cho các thao tác truyền tin là không gian chung. Hãy đảm bảo rằng tên hành động và các chuỗi khác được viết trong không gian tên mà bạn sở hữu, nếu không bạn có thể vô tình xung đột với các ứng dụng khác.

  • Do phương thức onReceive(Context, Intent) của trình nhận chạy trên luồng chính, nó sẽ thực thi và trả về nhanh chóng. Nếu bạn cần thực hiện tác vụ lâu dài, cẩn thận về việc tạo luồng hoặc bắt đầu các dịch vụ nền vì hệ thống có thể dừng toàn bộ quá trình sau Trả lại hàng với mức phí onReceive(). Để biết thêm thông tin, hãy xem phần Ảnh hưởng đến quy trình trạng thái Để thực hiện công việc lâu dài, chúng ta đề xuất:

    • Đang gọi goAsync() trong phương thức onReceive() của receiver và truyền BroadcastReceiver.PendingResult đến luồng nền. Thao tác này sẽ duy trì hoạt động của nội dung truyền phát sau khi trở lại từ onReceive(). Tuy nhiên, ngay cả với phương pháp này, hệ thống vẫn mong muốn bạn kết thúc bằng truyền tin rất nhanh (dưới 10 giây). Ứng dụng này cho phép bạn di chuyển thao tác với một luồng khác để tránh sự cố luồng chính.
    • Lên lịch công việc bằng JobScheduler. Để biết thêm thông tin, hãy xem phần Công việc thông minh Lên lịch.
  • Không bắt đầu hoạt động từ broadcast receiver vì trải nghiệm người dùng gây khó chịu; đặc biệt nếu có nhiều hơn một receiver. Thay vào đó, hãy cân nhắc đang hiện một thông báo.