- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
抱歉标题太长,但我不知道该怎么做。我正在开发一个 Android 项目,在该项目中我尝试使用名为 Cometd 的 PUSH 框架。 。现在Cometd使用Bayuex API/规范来实现PUSH服务。
当您考虑普通网站部分(用户登录或服务器端可扩展异步应用程序)时,Cometd 的工作效果简直棒极了,没有什么可提示的。我们面临的问题是在应用程序方面。没有可用的支持或文档。
经过一番努力,我能够编写代码在 Android 应用程序中使用 Cometd,不幸的是它有错误且不稳定。我将描述我如何构建它的结构,描述问题并显示代码。
有 2 个主要的 Activity 类:ConversationActivity
和 ChatMessagesActivity
。在 ConversationActivity 中,我启动一个 httpclient
并通过执行握手连接到 PUSH 服务。
在同一个类中,有一个 ClientSessionChannel 监听器,它不断监听新消息。在 ConversationActivity 类中,我从服务器数据库中检索登录用户的所有对话。完成后,用户可以决定他/她想与谁聊天。
现在,当点击对话时,我会在另一个 Activity 中打开这两个用户的聊天消息。
现在,不要忘记每条新消息都会到达 ConversationActivity 中的 ClientSessionChannel Listener 中,这就是为什么我必须维护 ConversationActivity 和 ChatMessagesActivity 之间的通信链接的原因,这会导致各种不稳定。
现在,我想做的是将监听器和 httpclient 推送到另一个线程/类/背景等中。完成后,如何保持聊天消息之间的开放通信已打开,因此消息会更新。我希望问题已经清楚了。我现在将发布代码。请看一下:
public class ConversationActivity extends ApplicationDrawerLoader {
static Context context;
List<PrivateChannel> privateChannelList = new ArrayList<>();
List<Long> groupAccountList = new ArrayList<>();
List<String> pushPrivateChannelList = new ArrayList<>();
ListView conversationsList;
ConversationAdapter conversationAdapter;
protected static volatile BayeuxClient client;
private ChatListener chatListener = new ChatListener();
HttpClient httpClient = StaticRestTemplate.getHttpClient();
String defaultURL = StaticRestTemplate.baseURL + "/cometd";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_conversations);
context = this;
try {
httpClient.start();
} catch (Exception e) {
e.printStackTrace();
}
if (isOnline()) {
new getConversationsForLoggedInUser(this).execute();
ClientTransport clientTransport = new LongPollingTransport(null, httpClient);
client = new BayeuxClient(defaultURL, clientTransport);
client.putCookie(new HttpCookie("JSESSIONID", StaticRestTemplate.getJsessionid()));
client.getChannel(Channel.META_HANDSHAKE).addListener(new InitializerListener());
client.getChannel(Channel.META_CONNECT).addListener(new ConnectionListener());
client.handshake();
boolean success = client.waitFor(2000, BayeuxClient.State.CONNECTED);
if (!success) {
Toast.makeText(getApplicationContext(), "Could not connect to PUSH service", Toast.LENGTH_LONG).show();
}
public class getConversationsForLoggedInUser extends AsyncTask<Void, Void, ResponseEntity<PrivateChannel[]>> {
client.getChannel("/person/"+privateChannel.getPrivateChannelName()).subscribe(chatListener);
// Here I get all conversations for user and load them in ListView using adapter
}
public void sendMessageToChatActivity(final String channelName, final Map<String,Object> outputData) {
// Here send the message to Chat activity.
Log.d("Msg",String.valueOf(outputData.toString()));
runOnUiThread(new Runnable() {
public void run() {
ChatMessagesActivity.recieveUpdatedMessage(channelName, outputData);
}
});
}
public static void recieveMessageFromChatActivity(String channelName, Map<String, Object> inputData){
//client.putCookie(new HttpCookie("JSESSIONID", StaticRestTemplate.getJsessionid()));
client.getChannel(channelName).publish(inputData);
}
private void initialize() {
}
private void connectionEstablished() {
System.err.printf("system: Connection to Server Opened%n");
}
private void connectionClosed() {
System.err.printf("system: Connection to Server Closed%n");
}
private void connectionBroken() {
System.err.printf("system: Connection to Server Broken%n");
}
private class InitializerListener implements ClientSessionChannel.MessageListener {
@Override
public void onMessage(ClientSessionChannel channel, Message message) {
if (message.isSuccessful()) {
initialize();
}
}
}
private class ConnectionListener implements ClientSessionChannel.MessageListener {
private boolean wasConnected;
private boolean connected;
public void onMessage(ClientSessionChannel channel, Message message) {
if (client.isDisconnected()) {
connected = false;
connectionClosed();
return;
}
wasConnected = connected;
connected = message.isSuccessful();
if (!wasConnected && connected) {
connectionEstablished();
} else if (wasConnected && !connected) {
connectionBroken();
}
}
}
// THe below method sends message to the ChatMessagesActivity.
public class ChatListener implements ClientSessionChannel.MessageListener {
public void onMessage(ClientSessionChannel channel, Message message) {
sendMessageToChatActivity(channel.toString(),message);
}
}
聊天消息 Activity :
public class ChatMessagesActivity extends ApplicationDrawerLoader {
Context context;
public ListView chatList;
protected static ChatMessagesAdapter chatMessagesAdapter = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat_messages);
chatList = (ListView) findViewById(R.id.chatList);
context = this;
sendMessageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Here I send message to ConversationActivity, which in turn sends it via CometdD.
sendMessageToConversationsActivity("/service/person/" + String.valueOf(conversationId), outputData);
}
public static void recieveUpdatedMessage(String channelName, Map<String, Object> input) {
// Here I recieve the new message and add it to adapter.
HashMap<String, String> insertMap = new HashMap<>();
// Add data to hashmap and add it to adapter
chatMessagesAdapter.add(insertMap);
chatMessagesAdapter.notifyDataSetChanged();
}
public void sendMessageToConversationsActivity(String channelName, Map<String, Object> output) {
ConversationActivity.recieveMessageFromChatActivity(channelName, output);
}
public class getPrivateChatsForUser extends AsyncTask<Void, Void, ResponseEntity<RestReplies[]>> {
ChatMessagesActivity chatMessagesActivity = null;
getPrivateChatsForUser(ChatMessagesActivity chatMessagesActivity) {
this.chatMessagesActivity = chatMessagesActivity;
}
// Here i get chat messages from network and load it in list-view using adapter.,
public class ChatMessagesAdapter extends BaseAdapter {
// Adapter code to display, nothing fancy.
}
}
我知道代码看起来有点长,但问题也是如此。我将不胜感激任何帮助。我不是 Android 专家,只是尝试集成它。谢谢。 :-)
编辑
public class CometdService extends Service {
protected static volatile BayeuxClient client;
String defaultURL = StaticRestTemplate.baseURL + "/cometd";
HttpClient httpClient = StaticRestTemplate.getHttpClient();
private ChatListener chatListener = new ChatListener();
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
httpClient.start();
} catch (Exception e) {
e.printStackTrace();
}
ClientTransport clientTransport = new LongPollingTransport(null, httpClient);
client = new BayeuxClient(defaultURL, clientTransport);
client.putCookie(new HttpCookie("JSESSIONID", StaticRestTemplate.getJsessionid()));
client.getChannel(Channel.META_HANDSHAKE).addListener(new InitializerListener());
client.getChannel(Channel.META_CONNECT).addListener(new ConnectionListener());
client.handshake();
boolean success = client.waitFor(2000, BayeuxClient.State.CONNECTED);
if (!success) {
Toast.makeText(getApplicationContext(), "Could not connect to PUSH service", Toast.LENGTH_LONG).show();
}
return Service.START_REDELIVER_INTENT;
}
@Override
public void onDestroy() {
}
private class InitializerListener implements ClientSessionChannel.MessageListener {
@Override
public void onMessage(ClientSessionChannel channel, Message message) {
if (message.isSuccessful()) {
initialize();
}
}
}
private class ConnectionListener implements ClientSessionChannel.MessageListener {
private boolean wasConnected;
private boolean connected;
public void onMessage(ClientSessionChannel channel, Message message) {
if (client.isDisconnected()) {
connected = false;
connectionClosed();
return;
}
wasConnected = connected;
connected = message.isSuccessful();
if (!wasConnected && connected) {
connectionEstablished();
} else if (wasConnected && !connected) {
connectionBroken();
}
}
}
private void initialize() {
}
private void connectionEstablished() {
System.err.printf("system: Connection to Server Opened%n");
}
private void connectionClosed() {
System.err.printf("system: Connection to Server Closed%n");
}
private void connectionBroken() {
System.err.printf("system: Connection to Server Broken%n");
}
public class ChatListener implements ClientSessionChannel.MessageListener {
public void onMessage(ClientSessionChannel channel, Message message) {
// sendMessageToChatActivity(channel.toString(), message);
}
}
}
新创建的服务,正在进行中。
最佳答案
看起来像 IntentService可能有助于与服务器的通信。
关于java - 安卓 : Keep httpclient running in background and communicate with activity when message recieved by httpclient,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34763922/
HTTP Keep Alive是如何实现的?它在内部使用 TCP Keep Alive 吗?如果不是,服务器如何检测客户端是死是活? 最佳答案 我知道这是一个老问题,但仍然: HTTP Keep-Al
我需要在每次连接到我的网站和获取数据时节省时间。 这是我的工作。 ESP 模块连接到家庭 WiFi。 AT+CIPMUX=0 --> 响应OK AT+CWMODE=1 --> 响应OK AT+CIPS
我尝试添加新标题的方法: request.Headers.GetType().InvokeMember("ChangeInternal", BindingFlags.Instance | Bi
我听说 Connection:Keep-Alive header 会告诉服务器将客户端和服务器之间的连接保持一段时间,以防止每次客户端向服务器建立请求时都要付出努力。我尝试将其添加到请求的 heade
我遇到了一种我一直在研究的垂直 slider 的问题。问题是,当我更改显示分辨率时,右侧缩略图的高度与左侧图片的高度不同。很难用文字来解释,所以我做了一个代码笔来帮助我更好地理解它。是这样的: htt
我在 apache 服务器上使用 http keep-alive, 比方说我要求它保持连接打开最多 2 分钟... 现在,如果连接被创建并闲置一分钟,php 持有的资源, 像 mysql 连接、文件句
我看到一些 proguard 配置有这样的行: -keep class a.b.** {} 我对 {} 的使用感到困惑。这个我知道 -keep class a.b.**表示保留包a.b及其子包中的所有
keep-alive的设计初衷 有些业务场景需要根据不同的判断条件,动态地在多个组件之间切换。频繁的组件切换会导致组件反复渲染,如果组件包含有大量的逻辑和dom节点,极易造成性能问题。其次,切换后组件
我知道有一个 DELETE FROM WHERE mysql 中的命令,如果表达式有效,则从指定表中删除元组。 然而,在取keep only表达式的补码时总是使用德摩根定律成为一种负担。 我的问题
我已经尝试了 2 个小时让我的页脚留在底部。 我一直在尝试“Matthew James Taylors”技术,但没有成功。 有人看到我遗漏了什么或做错了什么吗? 这是一个活生生的例子:http://g
是否有工具或流程可以让您的函数、选择器和“for 循环”方便且可搜索以供将来使用?我什么也没用,偶尔会重新学习我已经解决的类似问题。 背景:我正在学习 jQuery 和 Javascript,并开始看
所以根据haproxy作者的说法,谁知道关于http的一两件事: Keep-alive was invented to reduce CPU usage on servers when CPUs we
我正在尝试确定客户端是否已关闭来自 netty 的套接字连接。有办法做到这一点吗? 最佳答案 在客户端通过 close() 关闭套接字并且 TCP 关闭握手已成功完成的通常情况下,channelIna
我已经在本地主题分支 上工作了一段时间,偶尔只做一些更改。 与此同时,master 分支有了显着的发展。我决定将 master 分支中的新更改 merge 到我的本地主题分支中(与我从中分支出来的
1、作用 主要用于保留组件状态或避免重新渲染。 2、用法 <keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。 <ke
HTTP 长连接,也称为 HTTP 持久连接(HTTP Persistent Connection)或 HTTP 连接重用,是一种在 HTTP 协议中实现的机制。 在传统的 HTTP
我需要合并一些 dll,文件名和程序集名称都需要与我的主 dll (mydll.dll) 相同。我还需要 pdb 文件。我如何完成这项工作? 以下是我尝试过的一些方法: 只需使用 ILMerge my
我有一个在其他字段中具有FileField的表单。假设用户选择了一个文件,然后按Submit(提交),另一个字段触发了ValidationError。 当我取回表单时,页面上出现错误,用户为文件字段选
我正在学习 akka 流,在代码中遇到了 Keep.left 和 Keep.right: implicit val system = ActorSystem("KafkaProducer") impl
我正在一个项目中,有人检查了一些文件夹和文件,这些文件夹和文件不应该位于存储库中,并且应该位于我们本地,我尝试通过以下命令删除它们,这给了我这个错误 svn delete filename --kee
我是一名优秀的程序员,十分优秀!