如何为broadcastReceiver使用"goAsync"?

and*_*per 18 android asynchronous broadcastreceiver android-pendingintent

背景

从Honeycomb(API 11)开始,Android具有允许broadcastReceiver以异步方式运行的功能,在它假定它可以使用名为" goAsync " 的方法杀死其进程之前大约10秒:

这可以由onReceive(Context,Intent)中的应用程序调用,以允许它在从该函数返回后保持广播活动.这不会改变对广播相对响应的期望(在10秒内完成),但允许实现将与其相关的工作移到另一个线程,以避免因磁盘IO而导致主UI线程出现故障.

问题

我在很多地方搜索过,没有找到任何关于如何使用它的示例或教程.

不仅如此,该方法返回一个PendingIntent实例,我不知道该如何处理它:

返回表示活动广播结果的BroadcastReceiver.PendingResult.BroadcastRecord本身不再有效; 所有数据和其他交互必须通过BroadcastReceiver.PendingResult API.完成广播处理后,必须调用PendingResult.finish()方法.

这个问题

你是如何使用这种方法的?

什么是它返回的PendingIntent,我应该怎么做呢?

Bro*_*ian 35

你可以在这里找到简短的解释.

使用goAsync(),如果你想你的换手内的处理BroadcastReceiveronReceive()方法,另一个线程.onReceive()然后可以在那里完成该方法.PendingResult被传递给新线程,您必须调用PendingResult.finish()以实际通知系统该接收器可以被回收.

例如:

final PendingResult result = goAsync();
Thread thread = new Thread() {
   public void run() {
      int i;
      // Do processing
      result.setResultCode(i);
      result.finish();
   }
};
thread.start();
Run Code Online (Sandbox Code Playgroud)

  • 不需要setResult它只用于在有序广播期间在接收器之间传递数据.你可以把它留下来. (8认同)
  • 从onReceive方法返回的总时间是10秒.这意味着你的线程可以运行最多10秒减去你在启动线程之前在onReceive方法上花费的时间.但是没有尝试代码,因为它在那里 (3认同)
  • 有序广播按顺序通过每个注册的广播接收器。顺序由意图过滤器的优先级属性定义。然后,每个接收器都可以使用setResult()之类的方法将数据传递给下一个接收器,甚至完全停止广播。行动。ACTION_NEW_OUTGOING_CALL是有序广播。您可以使用setResult修改多余的EXTRA_PHONE_NUMBER,这将更改将要拨打的电话号码。 (2认同)

Mah*_*oud 5

kotlin 中,您可以在BroadcastReceiver上编写扩展函数:

/**
 * Run work asynchronously from a [BroadcastReceiver].
 */
fun BroadcastReceiver.goAsync(
    coroutineScope: CoroutineScope,
    dispatcher: CoroutineDispatcher,
    block: suspend () -> Unit
) {
    val pendingResult = goAsync()
    coroutineScope.launch(dispatcher) {
        block()
        pendingResult.finish()
    }
}
Run Code Online (Sandbox Code Playgroud)

在您的广播接收器中,您可以执行以下操作:

class AlarmBroadcastReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        // Code here runs on the main thread

        goAsync(GlobalScope, Dispatchers.Default) {
            // The code here will run on the background by the default dispatcher on the global scope
            // If your code here touches the IO, then you can use Dispatchers.IO instead
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 我建议将块包装在“tryfinally”中,以确保最终总是调用“finish()”。 (2认同)
  • 请注意未来的谷歌用户,Ian Lake 在 Muzei 应用程序中将其与“GlobalScope”一起使用,所以我认为这可能没问题 https://github.com/muzei/muzei/blob/b66437955dc71d544194170bb7cb710d123ca69c/extensions/src/main/java/com /google/android/apps/muzei/util/BroadcastReceiverExt.kt (2认同)