服务未初始化,返回NullPointerException

时间:2012-06-11 15:07:45

标签: android service nullpointerexception

我正在尝试在我的服务和活动设置之间进行双向通信。为此,我像平常一样启动我的服务,发送一条消息,将replyTo设置为我的Activity中的Messenger,然后将其发送到我的服务。这样我就可以在两个方向上发送消息。以下是我的Activty中的一些相关代码:

private Messenger mService = null;
private final Messenger mMessenger = new Messenger(new IncomingHandler());

private ServiceConnection mConnection = new ServiceConnection()
{
    public void onServiceConnected(ComponentName className, IBinder service)
    {
        mService = new Messenger(service);
        mBound = true;
    }

    public void onServiceDisconnected(ComponentName className)
    {
        mService = null;
        mBound = false;
    }
};

private void initMessenger()
{
    Message messageHandler = Message.obtain(null, NetworkService.MSG_GET_HANDLER, 0, 0);
    messageHandler.replyTo = mMessenger; //Set the replyTo to give a reference
    try
    {
        mService.send(messageHandler);
    }
    catch(RemoteException e)
    {
        e.printStackTrade();
    }
    catch(NullPointerException e)
    {
        e.printStackTrace(); //Why!!!
    }
}

public void onCreate()
{
...
    //Create the intent to start the network service
    Intent iService = new Intent(this, NetworkService.class);
    int[] connectionConfig = {CONNECTION_BT};
    iService.putExtra(CONNECTION_CONFIG, connectionConfig);
    bindService(iService, mConnection, Context.BIND_ABOVE_CLIENT);
    startService(iService);
    initMessenger();
}

当我尝试调用mService.send()时抛出NullPointerException,这很可能是因为当时mService为null。如果我在一个Button的OnClickListener中移动initMessenger()代码就可以正常工作,这就是混乱的原因。我应该在启动服务后等待一段时间才能使用它吗?

3 个答案:

答案 0 :(得分:3)

为什么不在initMessenger()方法中拨打onServiceConnected()?那样mService肯定会被分配。

答案 1 :(得分:2)

在此阶段

mService null表示此时您的服务尚未(尚未)调用onServiceConnected()

不幸的是,documentation并未表示bindService()返回与ServiceConnection中的方法之间存在差距。

事实上,bindService()应该在服务启动时返回true,这意味着一旦代码通过此阶段,服务就应该启动。因此,我会在调用true之前检查bindService()是否已返回initMessenger(),因为服务可能无法正常启动。

onServiceConnected()中的代码也可能抛出异常(因为它可能在工作线程上被调用,不会导致您的应用程序崩溃),您可能需要重新检入你的日志检查是否是这种情况。

此外,startService(iService);在此上下文中是多余的,bindService() 启动服务,在服务上调用startService只需向其发送消息。

答案 2 :(得分:1)

是。只有在您知道自己受其约束后才能使用该服务。 因为您尝试绑定到服务后尝试立即使用您的服务,所以您无法保证将连接到该服务。有时服务可能会立即绑定,因此您不会崩溃。有时会花费更长时间,因此您对initMessenger()的调用将导致您的NPE,因为该服务尚未连接。

initMessenger()电话移动到您的按钮点击是允许您的服务时间绑定。此外,您应该检查以确保您受到约束(即使您给它时间),因为绑定可能会失败