- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我将 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/
我有这个代码: System.err.print("number of terms = "); System.out.println(allTerms.size()); System.err
我有以下问题:在操作系统是 Linux 的情况下和在操作系统是 MacOs 的情况下,我必须执行不同的操作。 所以我创建了以下 Ant 脚本目标: /u
我正在调用 system("bash ../tools/bashScript\"This is an argument!\"&"),然后我正在调用 close(socketFD) 直接在 system
使用最初生成的随机元素来约束随机数组的连续元素是否有效。 例如:我想生成一组 10 个 addr、size 对来模拟典型的内存分配例程并具有如下类: class abc; rand bit[5:0
我正在创建一个必须使用system(const char*)函数来完成一些“繁重工作”的应用程序,并且我需要能够为用户提供粗略的进度百分比。例如,如果操作系统正在为您移动文件,它会为您提供一个进度条,
我即将编写一些项目经理、开发人员和业务分析师会使用的标准/指南和模板。目标是更好地理解正在开发或已经开发的解决方案。 其中一部分是提供有关记录解决方案的标准/指南。例如。记录解决/满足业务案例/用户需
在开发使用压缩磁盘索引或磁盘文件的应用程序时,其中部分索引或文件被重复访问(为了论证,让我们说一些类似于 Zipfian 分布的东西),我想知道什么时候足够/更好地依赖操作系统级缓存(例如,Debia
我们编写了一个 powershell 脚本,用于处理来自内部系统的图像并将其发送到另一个系统。现在,业务的另一部分希望加入其中,对数据进行自己的处理,并将其推送到另一个系统。打听了一下,公司周围有几个
我正在尝试朗姆酒我的应用程序,但我收到以下错误:System.Web.HttpUnhandledException:引发了“System.Web.HttpUnhandledException”类型的异
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
所以我在其他程序中没有收到此错误,但我在这个程序中收到了它。 这个程序是一个我没有收到错误的示例。 #include int main() { system("pause"); } // en
我在 c# System.URI.FormatExption 中遇到问题 为了清楚起见,我使用的是 Segseuil 的 Matlab 方法,并且它返回一个图片路径 result。我想为其他用户保存此
我正在尝试像这样设置文本框的背景色: txtCompanyName.BackColor = Drawing.Color.WhiteSmoke; 它不喜欢它,因为它要我在前面添加系统,例如: txtCo
请帮助我解决 System.StackOverflowException我想用 .aspx 将记录写入数据库我使用 4 层架构来实现这一切都正常但是当我编译页面然后它显示要插入数据的字段时,当我将数据
我使用了一些通常由系统调用的API。 因此,我将 android:sharedUserId="android.uid.system" 添加到 manifest.xml, 并使用来自 GIT 的 And
我正在尝试创建一个小型应用程序,它需要对/system 文件夹进行读/写访问(它正在尝试删除一个文件,并创建一个新文件来代替它)。我可以使用 adb 毫无问题地重新挂载该文件夹,如果我这样做,我的应用
我想从没有 su 的系统 priv-app 将/system 重新挂载为 RW。如何以编程方式执行此操作?只会用 Runtime.getruntime().exec() 执行一个 shell 命令吗
我正在尝试制作一个带有登录系统的程序我对此很陌生,但我已经连续工作 8 个小时试图解决这个问题。这是我得到的错误代码 + ServerVersion 'con.ServerVersion' threw
当我“构建并运行”Code::Blocks 中的程序时,它运行得非常好!但是当我从“/bin”文件夹手动运行它时,当它试图用 system() 调用“temp.bat”时,它会重置。这是为什么?它没有
我想使用 system/pipe 命令来执行具有特殊字符的命令。下面是示例代码。通过系统/管道执行命令后,它通过改变特殊字符来改变命令。我很惊讶地看到系统命令正在更改作为命令传递的文本。 run(ch
我是一名优秀的程序员,十分优秀!