Broadcastreceiver组件不允许绑定到android中的服务

时间:2015-03-18 04:20:56

标签: android broadcastreceiver

这是我正在做的事情:

public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub

        ConnectivityManager conn = (ConnectivityManager) context
            .getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = conn.getActiveNetworkInfo();
    boolean isConnected = activeNetwork != null
            && activeNetwork.isConnectedOrConnecting();

    if (isConnected == true) {

        // initChatHub();
         Intent serviceIntent = new Intent(context, ChatService.class);
        Toast.makeText(context, "Connected", 1000).show();
        serviceIntent.putExtras(intent);
        context.startService(serviceIntent);
        context.bindService(serviceIntent, mServiceConnection,
                Context.BIND_AUTO_CREATE);

    } else {
        Toast.makeText(context, "Disconnected", 1000).show();
    }
}

当网络状态发生变化时,当数据连接断开时,应用程序就会崩溃,那么当数据连接打开然后应用程序崩溃时就会出现错误,此异常即将到来请建议我如何修复它。

enter image description here

4 个答案:

答案 0 :(得分:12)

Context.bindService

  

注意:无法从BroadcastReceiver调用此方法   部件....

因此,请使用BroadcastReceiver.peekService从运行Service:

返回IBinder
 Intent serviceIntent = new Intent(context, ChatService.class);
 context.startService(serviceIntent);
 if (isConnected == true) {
  IBinder binder = peekService(context, new Intent(context, ChatService.class));
  Toast.makeText(context, "Connected", 1000).show();
  if (binder != null){
    mChatService = ((LocalBinder) binder).getService();
        //.... other code here          
  }
} 

答案 1 :(得分:6)

Android返回此异常的原因是Receiver生命周期。它可能很短。如果接收者绑定服务,接收者可能不存在,直到结果返回。见Receiver lifecycle

解决方案正在启动另一项中间服务。让中间服务绑定目标服务。这个中间服务可以存在,直到结果返回。接收器可以在任何时候被杀死。

还有另一个黑客解决方案可以跳过Android NotAllowException。此异常检查上下文。如果此Context来自Receiver,则Android返回Exception。更改您的代码

context.bindService(serviceIntent, mServiceConnection,
            Context.BIND_AUTO_CREATE);

context.getApplicationContext.bindService(serviceIntent, mServiceConnection,
            Context.BIND_AUTO_CREATE);

这种黑客解决方案不会保持接收者的生命。如果您认为绑定服务的结果并不重要。您可以使用此hack解决方案跳过NotAllowException。

答案 2 :(得分:1)

您无法从BroadcastReceiver调用bindService。替代方案是:

  1. 创建一个Application类(通过扩展Application类)
  2. 创建一个函数,用于启动服务并将其绑定到您的应用程序类
  3. 在广播接收器中获取应用程序类的实例并调用启动服务的功能。
  4. 示例代码:

    
    public class MyApplication extends Application{
    
        public void startService(){
            Intent serviceIntent = new Intent(context, ChatService.class);
            Toast.makeText(context, "Connected", 1000).show();
            serviceIntent.putExtras(intent);
            context.startService(serviceIntent);
            context.bindService(serviceIntent, mServiceConnection,
                    Context.BIND_AUTO_CREATE);
       }
    }
    
    // inside onReceive function 
    public void onReceive(Context context, Intent intent) {
         ConnectivityManager conn = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = conn.getActiveNetworkInfo();
        boolean isConnected = activeNetwork != null
                && activeNetwork.isConnectedOrConnecting();
    
        if (isConnected == true) {
            MyApplication app=(MyApplication)context.getApplicationContext();
                app.initChatService();
        } else {
            Toast.makeText(context, "Disconnected", 1000).show();
        }
    }
    

答案 3 :(得分:1)

Service.bindService() can not be called from a BroadcastReceiver component. I use Application Context,it is OK