1

我正在尝试在我的服务和活动设置之间进行双向通信。为此,我像往常一样启动我的服务,在我的 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 为空。如果我将 initMessenger() 代码移动到按钮的 OnClickListener 中,它可以正常工作,这就是混淆的地方。我是否应该在启动服务后等待一段时间才能使用它?

4

3 回答 3

3

为什么不调用initMessenger()你的onServiceConnected()方法?这种方式mService肯定会被分配。

于 2012-06-11T15:12:47.020 回答
2

mService处于null此阶段表明此时您的 Service 尚未(尚未)调用onServiceConnected().

不幸的是,文档bindService()并没有暗示返回和ServiceConnection被调用的方法之间会有差距。

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

也可能是其中的代码onServiceConnected()引发了异常(由于它可能在工作线程上被调用,因此不会导致您的应用程序崩溃),您可能需要重新检查您的日志以检查这是否是案子。

此外,startService(iService);在这种情况下是多余的,bindService() 启动服务,调用startService服务只是向它发送一条消息。

于 2012-06-11T15:16:32.960 回答
1

是的。仅当您知道自己已绑定该服务时,才应使用该服务。因为您在尝试绑定后立即尝试使用您的服务,所以您不能保证您将连接到该服务。有时服务可能会立即绑定,因此您不会崩溃。有时需要更长的时间,因此您的调用initMessenger()将导致您的 NPE,因为该服务尚未连接。

将您的initMessenger()呼叫移动到您的按钮单击是允许您的服务时间绑定。此外,您应该检查以确保您已绑定(即使您给它时间),因为绑定可能会失败

于 2012-06-11T15:11:42.917 回答