Tổng quan về truyền tin

Ứ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ư mẫu thiết kế publish-subscribe. Những thông báo này được gửi khi có sự kiện quan tâm xảy ra. Ví dụ: hệ thống Android sẽ gửi thông báo khi có nhiều sự kiện hệ thống 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. Ứng dụng cũng có thể gửi thông báo tuỳ chỉnh, chẳng hạn như để thông báo cho các ứng dụng khác về nội dung mà họ có thể quan tâm (ví dụ: một số dữ liệu mới đã được tải xuống).

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

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

Nói chung, bạn có thể sử dụng thông báo truyền tin như một hệ thống thông báo trên các ứng dụng và bên 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ợi dụng cơ hội phản hồi thông báo truyền tin và chạy các công việc ở chế độ nền có thể góp phần làm chậm hiệu suất hệ thống.

Giới thiệu về tính năng truyền phát của hệ thống

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

Bản thân thông báo phát đi được gói trong một đối tượng Intent có chuỗi thao tác 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 gói vào trường bổ sung. Ví dụ: ý định ở chế độ trên máy bay bao gồm một giá trị boolean bổ sung cho biết liệu Chế độ trên máy bay có đang bật hay không.

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

Để biết danh sách đầy đủ các thao tác truyền tin của hệ thống, hãy xem tệp BROADCAST_ACTIONS.TXT trong SDK Android. Mỗi thao tác truyền tin đều liên kết với một trường hằng số. 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.

Các 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 hoạt động của các tin truyền của hệ thống. Hãy ghi nhớ những thay đổi sau để hỗ trợ tất cả phiên bản Android.

Android 14

Khi ứng dụng ở trạng thái lưu vào bộ nhớ đệm, tính năng phân phối thông báo truyền tin sẽ được tối ưu hoá cho tình trạng của hệ thống. Ví dụ: các thông báo truyền tin của hệ thống ít quan trọng hơn (chẳng hạn như 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ừ trạng thái đã lưu vào bộ nhớ đệm sang vòng đời của quy trình đang hoạt động, hệ thống sẽ phân phối mọi tin truyền bị trì hoãn.

Các thông báo quan trọng được khai báo trong tệp kê khai sẽ tạm thời xoá các ứng dụng khỏi trạng thái đã lưu vào bộ nhớ đệm để phân phối.

Android 9

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

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

Android 8.0

Kể từ Android 8.0 (API cấp 26), hệ thống sẽ áp dụng thêm các quy định hạn chế đối với các receiver được khai báo trong tệp kê khai.

Nếu ứng dụng của bạn nhắm mục tiêu đến Android 8.0 trở lên, bạn không thể sử dụng tệp kê khai để khai báo dịch vụ nhận cho hầu hết các thông báo truyền phát ngầm (thông báo truyền tin không nhắm mục tiêu cụ thể đến ứng dụng của bạn). Bạn vẫn có thể sử dụng bộ nhận đã đăng ký theo ngữ cảnh khi người dùng đang 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 các thông báo sau đây của hệ thống:

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 bằng registerReceiver(BroadcastReceiver, IntentFilter). Bạn không thể khai báo dịch vụ nhận trong tệp kê khai.

Đang nhận thông báo

Các ứng dụng có thể nhận thông báo theo hai cách: thông qua trình thu nhận được khai báo theo tệp kê khai và trình thu nhận đã đăng ký theo bối cảnh.

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

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

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

  1. Chỉ định phần tử <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à receiver đăng ký.

  2. Lớp con BroadcastReceiver và triển khai onReceive(Context, Intent). Broadcast receiver trong nhật ký ví dụ sau đây và hiển thị nội dung của thông báo truyền tin:

    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 khung hiển thị, hãy định cấu hình viewBinding trong tệp build.gradle ở cấp độ mô-đun.

Trình quản lý gói hệ thống đăng ký dịch vụ 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 biệt vào ứng dụng của bạn, nghĩa 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 hiện không chạy.

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

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

Các receiver đã đăng ký theo bối cảnh sẽ nhận được thông báo miễn là ngữ cảnh đăng ký của các receiver đó hợp lệ. Ví dụ: nếu đăng ký trong ngữ cảnh Activity, bạn sẽ nhận được thông báo miễn là hoạt động không bị huỷ. Nếu đăng ký bằng ngữ cảnh ứng dụng, bạn sẽ nhận được thông báo miễn là ứng dụng đang chạy.

Để đăng ký dịch vụ nhận với 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 đưa thư viện AndroidX Core phiên bản 1.9.0 trở lên vào:

    Groovy

    dependencies {
        def core_version = "1.9.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.0.0"
    
        // To use the Animator APIs
        implementation "androidx.core:core-animation:1.0.0-beta01"
        // To test the Animator APIs
        androidTestImplementation "androidx.core:core-animation-testing:1.0.0-beta01"
    
        // Optional - To enable APIs that query the performance characteristics of GMS devices.
        implementation "androidx.core:core-performance:1.0.0-alpha02"
    
        // 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.0.0-beta03"
    
        // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12
        implementation "androidx.core:core-splashscreen:1.1.0-alpha01"
    }
    

    Kotlin

    dependencies {
        val core_version = "1.9.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.0.0")
    
        // To use the Animator APIs
        implementation("androidx.core:core-animation:1.0.0-beta01")
        // To test the Animator APIs
        androidTestImplementation("androidx.core:core-animation-testing:1.0.0-beta01")
    
        // Optional - To enable APIs that query the performance characteristics of GMS devices.
        implementation("androidx.core:core-performance:1.0.0-alpha02")
    
        // 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.0.0-beta03")
    
        // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12
        implementation("androidx.core:core-splashscreen:1.1.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 có cho phép xuất broadcast receiver và hiển thị cho các ứng dụng khác trên thiết bị hay không. Nếu receiver này đang theo dõi các thông báo được gửi từ hệ thống hoặc từ các ứng dụng khác (kể cả các ứng dụng khác mà bạn sở hữu), hãy sử dụng cờ RECEIVER_EXPORTED. Thay vào đó, nếu receiver này chỉ lắng nghe thông báo 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 nữa hoặc ngữ cảnh không còn hợp lệ.

    Hãy lưu ý đến nơi bạn đăng ký và huỷ đăng ký receiver, ví dụ: nếu bạn đăng ký một receiver trong onCreate(Bundle) bằng ngữ cảnh của hoạt động, bạn nên huỷ đăng ký trong onDestroy() để ngăn chặn việc rò rỉ receiver khỏi ngữ cảnh hoạt động. Nếu đăng ký receiver trong onResume(), bạn nên huỷ đăng ký receiver trong onPause() để tránh việc đăng ký nhiều lần (Nếu bạn không muốn nhận thông báo khi bị tạm dừng thì việc này có thể giúp giảm hao tổn không cần thiết đối với hệ thống). Đừng huỷ đăng ký trong onSaveInstanceState(Bundle) vì thao tác này sẽ 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 của quy trình

Việc BroadcastReceiver có đang hoạt động hay không ảnh hưởng đến quy trình bên trong. Điều này có thể làm thay đổi khả năng hệ thống buộc tắt. Quy trình trên nền trước sẽ thực thi phương thức onReceive() của trình nhận. Hệ thống sẽ chạy quy trình này trừ phi chịu áp lực quá lớn về bộ nhớ.

BroadcastReceiver bị huỷ kích hoạt sau onReceive(). Quy trình lưu trữ của receiver chỉ quan trọng như các thành phần ứng dụng. Nếu quy trình đó chỉ lưu trữ một dịch vụ nhận được khai báo bởi tệp kê khai (thường xuyên xảy ra với các ứng dụng mà người dùng chưa hoặc chưa tương tác gần đây), thì hệ thống có thể loại bỏ nó sau onReceive() để cung cấp tài nguyên cho các quy trình quan trọng hơn khác.

Do đó, broadcast receiver không nên bắt đầu các luồng trong nền chạy 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 onReceive() để lấy lại bộ nhớ, chấm dứt luồng đã tạo. Để duy trì quá trình hoạt động, hãy lên lịch JobService từ receiver bằng cách sử dụng JobScheduler để hệ thống biết rằng quy trình này 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

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

  • Phương thức sendOrderedBroadcast(Intent, String) gửi thông báo đến một dịch vụ nhận tại một thời điểm. Khi đến lượt trình thu nhận 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 quá trình truyền tin để không được truyền đến các trình thu nhận khác. Bạn có thể kiểm soát các trình thu nhận thứ tự chạy bằng thuộc tính android:Priority của bộ lọc ý định trùng khớp; các trình thu nhận có cùng mức độ ưu tiên sẽ chạy theo thứ tự tuỳ ý.
  • Phương thức sendBroadcast(Intent) gửi thông báo đến tất cả các receiver theo thứ tự không xác định. Đây được gọi là Phát sóng thông thường. Cách này hiệu quả hơn, nhưng receiver không thể đọc kết quả từ các receiver khác, truyền dữ liệu đã nhận được từ tin truyền hoặc huỷ việc truyền tin.

Đoạn mã sau đây minh hoạ cách gửi một 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 phát đi được gói trong đối tượng Intent. Chuỗi thao tác 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 truyền tin. Bạn có thể đính kèm thông tin bổ sung vào ý định bằng putExtra(String, Bundle). Bạn cũng có thể giới hạn việc truyền tin cho một nhóm ứng dụng trong cùng tổ chức bằng cách gọi setPackage(String) trên ý định.

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

Các quyền cho phép bạn hạn chế thông báo truyền tin đến nhóm ứng dụng có các 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 người nhận thông báo truyền tin.

Gửi có quyền

Khi 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 trình thu nhận đã yêu cầu quyền đó bằng thẻ trong tệp kê khai (và sau đó được cấp quyền nếu nguy hiểm) mới có thể nhận 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ư sau:

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

Bạn có thể chỉ định một quyền hệ thống hiện có như BLUETOOTH_CONNECT hoặc xác định một quyền tuỳ chỉnh bằng phần tử <permission>. Để biết thông tin về các quyền và tính bảo mật nói chung, hãy xem bài viết Quyền của hệ thống.

Nhận tệp có quyền

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

Ví dụ: giả sử ứng dụng nhận của bạn có trình nhận được khai báo theo tệp kê khai như minh hoạ dưới đây:

<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 của bạn có bộ thu đã đăng ký theo bối cảnh như minh hoạ 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 đến những trình thu nhận đó, ứng dụng gửi phải yêu cầu cấp quyền như sau:

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

Các phương pháp hay nhất và 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 để gửi và nhận thông báo truyền tin:

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

  • Không truyền phát thông tin nhạy cảm bằng cách sử dụng ý định ngầm ẩ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 đó. Có ba cách để kiểm soát người có thể nhận thông báo của bạn:

    • Bạn có thể chỉ định quyền khi gửi thông báo truyền tin.
    • Trên Android 4.0 trở lên, bạn có thể chỉ định một gói bằng setPackage(String) khi gửi một thông báo truyền tin. Hệ thống sẽ hạn chế thông báo truyền tin cho nhóm ứng dụng khớp với gói đó.
  • Khi bạn đăng ký receiver, bất kỳ ứng dụng nào cũng có thể gửi các thông báo độc hại đến receiver của ứng dụng. Có một số cách để hạn chế thông báo 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 receiver được khai báo bởi tệp kê khai, bạn có thể đặt thuộc tính android:exported thành "false" trong tệp kê khai. Trình thu nhận không nhận được thông báo truyền tin từ các nguồn bên ngoài ứng dụng.
  • Không gian tên cho các hành động 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 của bạn, nếu không bạn có thể vô tình xung đột với các ứng dụng khác.

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

    • Gọi goAsync() trong phương thức onReceive() của trình nhận và truyền BroadcastReceiver.PendingResult đến một luồng trong nền. Điều này giúp duy trì thông báo truyền tin sau khi trở về từ onReceive(). Tuy nhiên, ngay cả với phương pháp này, hệ thống vẫn mong bạn kết thúc thông báo truyền tin thật nhanh (dưới 10 giây). Thư viện này cho phép bạn di chuyển tác vụ sang một luồng khác để tránh gây sự cố cho 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 Lên lịch công việc thông minh.
  • 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 là khi có nhiều broadcast receiver. Thay vào đó, hãy cân nhắc hiển thị một thông báo.