【问题标题】:Binding service by BroadcastReceiverBroadcastReceiver 绑定服务
【发布时间】:2013-09-21 10:44:11
【问题描述】:

我的应用程序使用了一个由 BOOT_COMPLETE BroadcastReceiver 启动的服务,在运行中我遇到了一个错误

我的代码:

public class projet extends BroadcastReceiver { 
 public void onReceive(Context context, Intent intent) { 

  intent = new Intent(context, ScreenshotService.class);
  intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  context.bindService(intent, aslServiceConn, Context.BIND_AUTO_CREATE);
}
}

错误:

java.lang.RuntimeException: Unable to start receiver com.example.projet: android.content.ReceiverCallNotAllowedException: BroadcastReceiver components are not allowed to bind to services

【问题讨论】:

  • 很简单。我创建了一个空 Activity(非 UI,仅用于 Bind 服务的 onCreate())和 finish()。在 Broadcast > Start Activity with Bundle 中(如果需要)。问题已解决。

标签: android


【解决方案1】:

不应从广播接收器绑定服务。 原因是广播接收器是轻量级组件,它必须finish its functionality with in not more than 10 seconds maximum。否则 android 可能会强行杀死您的接收器。在某些最坏的情况下,绑定(建立连接)服务可能需要超过 10 秒,这就是为什么 android 不允许这样做。

广播接收器规则:

  1. 广播接收器(大部分)没有任何 UI,只有后台逻辑。
  2. 广播接收器将有 10 秒的最大时间限制来完成其功能,否则它将崩溃。
  3. 您不应在接收器中执行长时间运行的操作或异步操作。 示例:a。准备 SD 卡。 湾。从互联网上传/下载文件。 C。创建数据库文件。 d。绑定到服务
  4. 不要在广播接收器中向用户显示对话框。 (这是异步操作)
  5. 您可以使用“toast”或“Notifications”。
  6. 不要编写任何繁重的功能。

参考来自developer android

【讨论】:

  • 好答案!但是,您可以从广播接收器启动服务。
  • 很简单。我创建了一个空 Activity(非 UI,仅用于 Bind 服务的 onCreate())和 finish()。在 Broadcast > Start Activity with Bundle 中(如果需要)。问题已解决。
【解决方案2】:

如果您知道Service 正在运行,您可以使用BroadcastReceiver.peekService(Context, Intent) 方法获取其Binder(参见peekService docs)。

但是,正如其他答案中已经说过的那样,不允许在BroadcastReceiver 中绑定Service

【讨论】:

  • 请注意,peekService 似乎在服务未运行或服务尚未被其他东西绑定时返回 null
  • @Sam 这正是我写的。注意“如果你知道服务正在运行”这句话。
  • 不,不是;你没有提到它在失败时返回null,你也没有提到如果服务正在运行但还没有绑定到其他东西它会失败。
【解决方案3】:

最好的方法是首先从BroadcastReceiver.onReceive() 开始一个IntentService 使用:

context.StartService(new Intent(context, YourIntentService.class));

然后在IntentService.onHandleIntent()

@Override
protected void onHandleIntent(Intent intent) {
    mContext = getApplicationContext();
    mContext.bindService(new Intent("com.ServiceToBind.BIND"), yourConnection, Context.BIND_AUTO_CREATE);
}

【讨论】:

  • 让您的生活更轻松。 :-)
  • 嘿,对我的回复投反对票的人。你能解释一下,你不喜欢这个吗?这是我能想到的最好的方法,事实上我在我的应用程序中使用了这段代码。因此,代码甚至经过测试并被证明是有效的。
  • 我的错。是的,它是一个意图服务。谢谢@Eric
  • 在 IntentService 对服务进行任何操作后,您是否需要担心解除绑定?
  • 对我来说很有魅力。谢谢你。不幸的是,Google 决定在 API 级别 30 中弃用 IntentService。他们建议改用 WorkManager。但我不确定使用WorkManager 是否可以达到相同的结果。有什么想法吗?
【解决方案4】:

问题

BroadcastReceivers 不允许绑定到 Service,正如此处的其他答案所示。

解决方案

我使用的一个简单的解决方案是将BroadcastReceiver收到的Intent转发到您最初要绑定的服务,然后在该服务的onStartCommand()方法中实现一些代码来处理它。

【讨论】:

    【解决方案5】:

    【讨论】:

      【解决方案6】:

      根据 bindService 文档:

      注意:此方法不能从 BroadcastReceiver 调用 零件。一种可用于从 服务的广播接收器是调用 startService(Intent) 包含要发送的命令的参数,以及服务 执行完该命令后调用它的 stopSelf(int) 方法。

      我做了什么: (不确定它是否适用于所有情况) 您可以创建一个服务并在您的 BroadcastReceiver 中启动该服务。在您的服务 onCreate() 方法中,您可以调用另一个负责绑定的类的方法。您可以将上下文从服务传递给该类并像这样使用它:ctx.bindService(...)

      【讨论】:

        【解决方案7】:

        BroadcastReceiver 无法绑定服务。 您可以通过以下网址获得一个很好的解决方案:

        Android - Start service on boot

        【讨论】:

          【解决方案8】:

          很简单。 选项 1: 我创建了一个空 Activity(非 UI,仅用于 Bind 服务的 onCreate())和 finish()。 在 Broadcast > Start Activity with Bundle 中(如果需要)。问题已解决。

          选项 2: 与上述选项相同,但使用服务而不是活动。 获取事件广播 > 启动新服务 > 绑定到您要绑定的现有服务。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-06-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多