我正在尝试按照本指南在我的应用中实现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;
}
谢谢你!
答案 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