尽管在后台运行,服务仍返回null

时间:2015-10-10 20:42:12

标签: java android service

我正在尝试按照本指南在我的应用中实现Instant Messaging功能:https://www.sinch.com/tutorials/android-messaging-tutorial-using-sinch-and-parse/#start sinch客户端

我已经完全按照指南中的所有内容进行了操作,但是当我尝试发送消息时,我得到了NullPointerException。这是有罪的代码:

private void sendMessage() {
    messageBody = messageBodyField.getText().toString();
    if (messageBody.isEmpty()) {
        Toast.makeText(getApplicationContext(), "Enter a message", Toast.LENGTH_LONG).show();
        return;
    }
    Log.i(TAG, "messageService: " + messageService);
    Log.i(TAG, "recipientId: " + recipientId);
    Log.i(TAG, "messageBody: " + messageBody);
    messageService.sendMessage(recipientId, messageBody);
    messageBodyField.setText("");
}

从日志中,我看到正确分配了recipientId和messageBody,并且messageService对象为null。以下是活动的完整代码:

public class ChatActivity extends AppCompatActivity {
private static final String TAG = "ChatActivity";
private String recipientId;
private EditText messageBodyField;
private ListView messagesList;
private ChatAdapter chatAdapter;
private String messageBody;
private MessageService.MessageServiceInterface messageService;
private String currentUserId;
private ServiceConnection serviceConnection = new MyServiceConnection();
private MessageClientListener messageClientListener = new MyMessageClientListener();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.chat);

    bindService(new Intent(this, MessageService.class), serviceConnection, BIND_AUTO_CREATE);
    //Log.i("Tag", "bindService(): " + bindService(new Intent(this, MessageService.class), serviceConnection, BIND_AUTO_CREATE));

    Intent intent = getIntent();
    recipientId = intent.getStringExtra("RECIPIENT_ID");
    currentUserId = ParseUser.getCurrentUser().getObjectId();

    messagesList = (ListView) findViewById(R.id.listview_chat);
    chatAdapter = new ChatAdapter(this);
    messagesList.setAdapter(chatAdapter);

    loadMessageHistory();

    messageBodyField = (EditText) findViewById(R.id.edittext_messageBodyField);

    findViewById(R.id.button_send).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            sendMessage();
        }
    });
}

private void loadMessageHistory() {
    String[] userIds = {currentUserId, recipientId};
    ParseQuery<ParseObject> query = ParseQuery.getQuery("ParseMessage");
    query.whereContainedIn("senderId", Arrays.asList(userIds));
    query.whereContainedIn("recipientId", Arrays.asList(userIds));
    query.orderByAscending("createdAt");
    query.findInBackground(new FindCallback<ParseObject>() {
        @Override
        public void done(List<ParseObject> messageList, ParseException e) {
            if (e == null) {
                for (int i = 0; i < messageList.size(); i++) {
                    WritableMessage message = new WritableMessage(messageList.get(i).get("recipientId").toString(), messageList.get(i).get("messageText").toString());
                    if (messageList.get(i).get("senderId").toString().equals(currentUserId)) {
                        chatAdapter.addMessage(message, ChatAdapter.DIRECTION_OUTGOING);
                    } else {
                        chatAdapter.addMessage(message, ChatAdapter.DIRECTION_INCOMING);
                    }
                }
            }
        }
    });
}

private void sendMessage() {
    messageBody = messageBodyField.getText().toString();
    if (messageBody.isEmpty()) {
        Toast.makeText(getApplicationContext(), "Enter a message", Toast.LENGTH_LONG).show();
        return;
    }
    Log.i(TAG, "messageService: " + messageService);
    Log.i(TAG, "recipientId: " + recipientId);
    Log.i(TAG, "messageBody: " + messageBody);
    messageService.sendMessage(recipientId, messageBody);
    messageBodyField.setText("");
}

@Override
public void onDestroy() {
    messageService.removeMessageClientListener(messageClientListener);
    unbindService(serviceConnection);
    super.onDestroy();
}

private class MyServiceConnection implements ServiceConnection {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        messageService = (MessageService.MessageServiceInterface) iBinder;
        Log.i(TAG, "messageService::onServiceConnected: " + messageService);
        messageService.addMessageClientListener(messageClientListener);
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        messageService = null;
        Log.i(TAG, "messageService::onServiceDisconnected: " + messageService);
    }
}

private class MyMessageClientListener implements MessageClientListener {
    @Override
    public void onMessageFailed(MessageClient client, Message message, MessageFailureInfo failureInfo) {
        Toast.makeText(ChatActivity.this, "Failed to send message", Toast.LENGTH_LONG).show();
    }

    @Override
    public void onIncomingMessage(MessageClient client, final Message message) {
        if (message.getSenderId().equals(recipientId)) {
            final WritableMessage writableMessage = new WritableMessage(message.getRecipientIds().get(0), message.getTextBody());
            ParseQuery<ParseObject> query = ParseQuery.getQuery("ParseMessage");
            query.whereEqualTo("sinchId", message.getMessageId());
            query.findInBackground(new FindCallback<ParseObject>() {
                @Override
                public void done(List<ParseObject> messageList, ParseException e) {
                    if (e == null) {
                        if (messageList.size() == 0) {
                            ParseObject parseMessage = new ParseObject("ParseMessage");
                            parseMessage.put("senderId", currentUserId);
                            parseMessage.put("recipientId", writableMessage.getRecipientIds().get(0));
                            parseMessage.put("messageText", writableMessage.getTextBody());
                            parseMessage.put("sinchId", message.getMessageId());
                            parseMessage.saveInBackground();
                            chatAdapter.addMessage(writableMessage, chatAdapter.DIRECTION_INCOMING);
                        }
                    }
                }
            });
        }
    }

    @Override
    public void onMessageSent(MessageClient client, Message message, String recipientId) {
        final WritableMessage writableMessage = new WritableMessage(message.getRecipientIds().get(0), message.getTextBody());
        chatAdapter.addMessage(writableMessage, ChatAdapter.DIRECTION_OUTGOING);
    }

    @Override
    public void onMessageDelivered(MessageClient client, MessageDeliveryInfo deliveryInfo) {

    }

    @Override
    public void onShouldSendPushData(MessageClient client, Message message, List<PushPair> pushPairs) {

    }
}
}

MessageService类代码:

package com.example.aes.ctf;

public class MessageService extends Service implements SinchClientListener {
private static final String APP_KEY = "app-key";
private static final String APP_SECRET = "secret";
private static final String ENVIRONMENT = "";
private final MessageServiceInterface serviceInterface = new MessageServiceInterface();
private SinchClient sinchClient = null;
private MessageClient messageClient = null;
private String currentUserId;
//private Intent broadcastIntent = new Intent("com.example.aes.ctf.ListUsersActivity");
//private LocalBroadcastManager broadcaster;

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    currentUserId = ParseUser.getCurrentUser().getObjectId();
    if (currentUserId != null && !isSinchClientStarted()) {
        startSinchClient(currentUserId);
    }
    //broadcaster = LocalBroadcastManager.getInstance(this);
    return super.onStartCommand(intent, flags, startId);
}

public void startSinchClient(String username) {
    sinchClient = Sinch.getSinchClientBuilder().context(this).userId(username)
            .applicationKey(APP_KEY).applicationSecret(APP_SECRET)
            .environmentHost(ENVIRONMENT).build();
    sinchClient.addSinchClientListener(this);
    sinchClient.setSupportMessaging(true);
    sinchClient.setSupportActiveConnectionInBackground(true);
    sinchClient.checkManifest();
    sinchClient.start();
}

private boolean isSinchClientStarted() {
    return sinchClient != null && sinchClient.isStarted();
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onClientStarted(SinchClient client) {
    /*broadcastIntent.putExtra("success", true);
    broadcaster.sendBroadcast(broadcastIntent);*/
    client.startListeningOnActiveConnection();
    messageClient = client.getMessageClient();
}

@Override
public void onClientStopped(SinchClient client) {
    client = null;
}

@Override
public void onClientFailed(SinchClient client, SinchError sinchError) {
    /*broadcastIntent.putExtra("success", false);
    broadcaster.sendBroadcast(broadcastIntent);*/
    client = null;
}

@Override
public void onRegistrationCredentialsRequired(SinchClient sinchClient, ClientRegistration clientRegistration) {

}

@Override
public void onLogMessage(int i, String s, String s1) {

}

public void sendMessage(String recipientUserId, String textBody) {
    if (messageClient != null) {
        WritableMessage message = new WritableMessage(recipientUserId, textBody);
        messageClient.send(message);
    }
}

public void addMessageClientListener(MessageClientListener listener) {
    if (messageClient != null) {
        messageClient.addMessageClientListener(listener);
    }
}

public void removeMessageClientListener(MessageClientListener listener) {
    if (messageClient != null) {
        messageClient.removeMessageClientListener(listener);
    }
}

@Override
public void onDestroy() {
    sinchClient.stopListeningOnActiveConnection();
    sinchClient.terminate();
}

public class MessageServiceInterface extends Binder {
    public void sendMessage(String recipientUserId, String textBody) {
        MessageService.this.sendMessage(recipientUserId, textBody);
    }

    public void addMessageClientListener(MessageClientListener listener) {
        MessageService.this.addMessageClientListener(listener);
    }

    public void removeMessageClientListener(MessageClientListener listener) {
        MessageService.this.removeMessageClientListener(listener);
    }

    public boolean isSinchClientStarted() {
        return MessageService.this.isSinchClientStarted();
    }
}
}

如果需要,我可以发布更多相关代码。我有一段时间以来一直坚持这个错误。

编辑: 我能够通过改变

来解决这个问题
@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public IBinder onBind(Intent intent) {
    return serviceInterface;
}

谢谢你!

2 个答案:

答案 0 :(得分:0)

你的问题在这里:

@Override
public IBinder onBind(Intent intent) {
return null;
}

您应该为服务实现一个绑定器并将其返回到服务的onBind方法中,因此在MessageServiceInterface类中声明以下方法:

    public MessageService getService() {
        Log.v("Serivce Bind", "Bind");
        return MessageService.this;
    }
}

并在MessageService class:

中声明一个字段
  IBinder binder = new MessageSeviceInterface();

onBind方法中返回binder实例,最后使用以下代码获取已分配的MessageService实例:

替换

messageService = (MessageService.MessageServiceInterface) iBinder;

使用:

MessageService.MessageServiceInterface binder = (MessageService.MessageServiceInterface) iBinder;
messageService = binder.getService()`

答案 1 :(得分:0)

好吧,这是因为您从未初始化 messageService 对象。

似乎您希望启动服务然后 - 从您的活动中控制它...您确定要从服务发送消息而不是从AsyncTask发送消息吗?

AsyncTask 也在后台运行,为此目的更容易控制......

尝试查询此链接:http://developer.android.com/reference/android/os/AsyncTask.html