java - 使用 Sinch 即时通讯系统

标签 java android android-layout android-activity sinch

我正在使用 Sinch 和 Parse 作为集成在我们应用程序中的即时消息系统,我有两个问题。

1) 由于某种原因,当显示消息传递 Activity 时,我收到以下错误:消息客户端未启动”。此外,该消息似乎没有在 Sinch 中传递,也没有在应用程序中直观地反射(reflect)。

下面是 Activity 代码(当用户单击“快速聊天”按钮时,会将他们带到消息传递 Activity 页面。

下面是消息传递 Activity 的 Activity 代码

public class MessagingActivity extends Activity implements ServiceConnection, MessageClientListener {

    private String recipientId;
    private Button sendButton;
    private EditText messageBodyField;
    private String messageBody;
    private MessageService.MessageServiceInterface messageService;
    private MessageAdapter messageAdapter;
    private ListView messagesList;

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

        doBind();


        messagesList = (ListView) findViewById(R.id.listMessages);
        messageAdapter = new MessageAdapter(this);
        messagesList.setAdapter(messageAdapter);

        Intent intent = getIntent();
        recipientId = intent.getStringExtra("Name");

        messageBodyField = (EditText) findViewById(R.id.messageBodyField);
        sendButton = (Button) findViewById(R.id.sendButton);

        sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendMessage();
            }
        });
    }

    private void sendMessage() {
        messageBodyField = (EditText) findViewById(R.id.messageBodyField);
        messageBody = messageBodyField.getText().toString();
        if (messageBody.isEmpty()) {
            Toast.makeText(this, "Please enter a message", Toast.LENGTH_LONG).show();
            return;
        }

        //Here is where you will actually send the message throught Sinch
        messageService.sendMessage(recipientId, messageBody);
        messageBodyField.setText("");
    }

    private void doBind() {
        Intent serviceIntent = new Intent(this, MessageService.class);
        bindService(serviceIntent, this, BIND_AUTO_CREATE);
    }

    @Override
    public void onDestroy() {
        unbindService(this);
        super.onDestroy();
    }

    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        //Define the messaging service and add a listener
        messageService = (MessageService.MessageServiceInterface) iBinder;
        messageService.addMessageClientListener(this);
        if (!messageService.isSinchClientStarted()) {
            Toast.makeText(this, "The message client did not start."
                ,Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        messageService = null;
    }

    @Override
    public void onMessageDelivered(MessageClient client, MessageDeliveryInfo deliveryInfo) {
        //Intentionally  left blank
    }

    @Override
    public void onMessageFailed(MessageClient client, Message message,
                                MessageFailureInfo failureInfo) {
        //Notify the user if message fails to send
        Toast.makeText(this, "Message failed to send.", Toast.LENGTH_LONG).show();
    }

    @Override
    public void onIncomingMessage(MessageClient client, Message message) {
        messageAdapter.addMessage(message, MessageAdapter.DIRECTION_INCOMING);
    }

    @Override
    public void onMessageSent(MessageClient client, Message message, String recipientId) {
        messageAdapter.addMessage(message, MessageAdapter.DIRECTION_OUTGOING);
    }

    @Override
    public void onShouldSendPushData(MessageClient client, Message message, List<PushPair> pushPairs) {
        //Intentionally left blank
    }
}

我已验证 APP_KEY、APP_SECRET 和 ENVIRONMENT 与 Sinch 上记录的内容相符。 我已经在模拟器和物理设备上尝试过此操作。

提前致谢

代码服务

 public class MessageService extends Service implements SinchClientListener {

        private static final String APP_KEY = "XXXXX";
        private static final String APP_SECRET = "YYYYY";
        private static final String ENVIRONMENT = "sandbox.sinch.com";
        private final MessageServiceInterface serviceInterface = new MessageServiceInterface();
        private SinchClient sinchClient = null;
        private MessageClient messageClient = null;
        private String currentUserId;

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {

            currentUserId = ParseUser.getCurrentUser().getObjectId().toString();

            if (currentUserId != null && !isSinchClientStarted()) {
                startSinchClient(currentUserId);
            }

            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 void onClientFailed(SinchClient client, SinchError error) {
            sinchClient = null;
        }

        @Override
        public void onClientStarted(SinchClient client) {
            client.startListeningOnActiveConnection();
            messageClient = client.getMessageClient();
        }

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

        public void stop() {
            if (isSinchClientStarted()) {
                sinchClient.stop();
                sinchClient.removeSinchClientListener(this);
            }
            sinchClient = null;
        }

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

        @Override
        public void onLogMessage(int level, String area, String message) {
            //Intentionally left blank
        }

        @Override
        public void onRegistrationCredentialsRequired(SinchClient client, ClientRegistration clientRegistration) {
            //Intentionally left blank
        }

        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);
            }
        }

        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();
            }
        }
    }

2) 限制:我想设置一个限制,即特定方之间只能发送 25 条消息。

提前致谢,如果您需要任何说明,请告诉我。

更新3 当用户单击此按钮时,他将与根据以下条件匹配的人一起进入 MessagingActivity

 final Button ibutton = (Button) this.findViewById(R.id.btnQuickChat);
        idrinks.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            openConversation();
        }

        private void openConversation() {
            // TODO Auto-generated method stub
              ParseQuery<ParseUser> query = ParseUser.getQuery();
                query.whereNotEqualTo("objectId", ParseUser.getCurrentUser()
                        .getObjectId());

                query.setLimit(1);

                query.findInBackground(new FindCallback<ParseUser>() {
                    public void done(List<ParseUser> user, ParseException e) {
                          if (e == null) {
                               Intent intent = new Intent(getApplicationContext(), MessagingActivity.class);
                               intent.putExtra("RECIPIENT_ID", user.get(0).getObjectId());
                               startActivity(intent);
                           } else {
                               Toast.makeText(getApplicationContext(),
                                   "Error finding that user",
                                       Toast.LENGTH_SHORT).show();
                           }
                       }
                    });
                }
    });

MessagingActivity(与教程中提供的几乎相同):

public class MessagingActivity extends Activity {

    private String recipientId;
    private EditText messageBodyField;
    private String messageBody;
    private MessageService.MessageServiceInterface messageService;
    private MessageAdapter messageAdapter;
    private ListView messagesList;
    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.messaging);

        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.listMessages);
        messageAdapter = new MessageAdapter(this);
        messagesList.setAdapter(messageAdapter);
        populateMessageHistory();

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

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

    //get previous messages from parse & display
    private void populateMessageHistory() {
        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, com.parse.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)) {
                            messageAdapter.addMessage(message, MessageAdapter.DIRECTION_OUTGOING);
                        } else {
                            messageAdapter.addMessage(message, MessageAdapter.DIRECTION_INCOMING);
                        }
                    }
                }
            }
        });
    }

    private void sendMessage() {
        messageBody = messageBodyField.getText().toString();
        if (messageBody.isEmpty()) {
            Toast.makeText(this, "Please enter a message", Toast.LENGTH_LONG).show();
            return;
        }

        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;
            messageService.addMessageClientListener(messageClientListener);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            messageService = null;
        }
    }

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

        @Override
        public void onIncomingMessage(MessageClient client, Message message) {
            if (message.getSenderId().equals(recipientId)) {
                WritableMessage writableMessage = new WritableMessage(message.getRecipientIds().get(0), message.getTextBody());
                messageAdapter.addMessage(writableMessage, MessageAdapter.DIRECTION_INCOMING);
            }
        }

        @Override
        public void onMessageSent(MessageClient client, Message message, String recipientId) {

            final WritableMessage writableMessage = new WritableMessage(message.getRecipientIds().get(0), message.getTextBody());

            //only add message to parse database if it doesn't already exist there
            ParseQuery<ParseObject> query = ParseQuery.getQuery("ParseMessage");
            query.whereEqualTo("sinchId", message.getMessageId());
            query.findInBackground(new FindCallback<ParseObject>() {
                @Override
                public void done(List<ParseObject> messageList, com.parse.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", writableMessage.getMessageId());
                            parseMessage.saveInBackground();

                            messageAdapter.addMessage(writableMessage, MessageAdapter.DIRECTION_OUTGOING);
                        }
                    }
                }
            });
        }

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

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

消息服务 Activity

public class MessageService extends Service implements SinchClientListener {

    private static final String APP_KEY = "61b1bfc0-b82a-44f5-ab68-dedca69ead8c";
    private static final String APP_SECRET = "jrFrLr8Adkm0Na4nLdASDw==";
    private static final String ENVIRONMENT = "sandbox.sinch.com";
    private final MessageServiceInterface serviceInterface = new MessageServiceInterface();
    private SinchClient sinchClient = null;
    private MessageClient messageClient = null;
    private String currentUserId;
    private LocalBroadcastManager broadcaster;

    private Intent broadcastIntent = new Intent("com.dooba.beta.matchOptionActivity");

    @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 void onClientFailed(SinchClient client, SinchError error) {
        broadcastIntent.putExtra("success", false);
        broadcaster.sendBroadcast(broadcastIntent);

        sinchClient = 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) {
        sinchClient = null;
    }

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

    @Override
    public void onLogMessage(int level, String area, String message) {
    }

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

    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);
        }
    }

    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();
        }
    }

消息适配器 Activity :

public class MessageAdapter extends BaseAdapter {

    public static final int DIRECTION_INCOMING = 0;
    public static final int DIRECTION_OUTGOING = 1;

    private List<Pair<WritableMessage, Integer>> messages;
    private LayoutInflater layoutInflater;

    public MessageAdapter(Activity activity) {
        layoutInflater = activity.getLayoutInflater();
        messages = new ArrayList<Pair<WritableMessage, Integer>>();
    }

    public void addMessage(WritableMessage message, int direction) {
        messages.add(new Pair(message, direction));
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return messages.size();
    }

    @Override
    public Object getItem(int i) {
        return messages.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public int getViewTypeCount() {
        return 2;
    }

    @Override
    public int getItemViewType(int i) {
        return messages.get(i).second;
    }

    @Override
    public View getView(int i, View convertView, ViewGroup viewGroup) {
        int direction = getItemViewType(i);

        //show message on left or right, depending on if
        //it's incoming or outgoing
        if (convertView == null) {
            int res = 0;
            if (direction == DIRECTION_INCOMING) {
                res = R.layout.message_right;
            } else if (direction == DIRECTION_OUTGOING) {
                res = R.layout.message_left;
            }
            convertView = layoutInflater.inflate(res, viewGroup, false);
        }

        WritableMessage message = messages.get(i).first;

        TextView txtMessage = (TextView) convertView.findViewById(R.id.txtMessage);
        txtMessage.setText(message.getTextBody());

        return convertView;
    }
}

最佳答案

我编写了您正在关注的教程,实际上昨天刚刚更新它以解决您的第一个问题。查看http://tutorial.sinch.com/android-messaging-tutorial/#show-spinner查看更新。新版本不会在服务未启动时显示 toast 消息,而是会显示进度对话框(加载微调器),直到服务启动或启动失败。

你能澄清一下你的第二个问题吗?

关于java - 使用 Sinch 即时通讯系统,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25924508/

相关文章:

java - 访问 WEB-INF 之外的文件

android - 如何在 Android 上为 Catlog 授予 root 权限

java - 以编程方式更改区域设置在某些设备中不起作用

android - 如何使用 Mapview 设置布局

android - 编辑文本 : set number of characters programmatically

java - 了解 Pair of Sum 和 codaddict 的算法

java - android studio android.support.design.widget.CoordinatorLayout 中的渲染问题

java - Spring Cloud Kubernetes 重新加载时序问题

java - 在java中将字节数组转换为字符串

android - menu.findItem 返回 null