mirror of
https://gitee.com/farsunset/cim.git
synced 2025-07-26 18:10:35 +08:00
1.修改netty版本,更新到netty5.0
2.优化netty版本代码结构 3.提升netty版本服务端连接管理,以及长连接心跳优化。
This commit is contained in:
parent
e49d5ea415
commit
16afed7b2b
BIN
CIM客户端文档.doc
BIN
CIM客户端文档.doc
Binary file not shown.
BIN
CIM服务端及辅助文档.doc
BIN
CIM服务端及辅助文档.doc
Binary file not shown.
@ -61,10 +61,10 @@ CIMPushManager.init(context,"125.12.35.231",28888);
|
|||||||
* 设置一个账号登录到服务端
|
* 设置一个账号登录到服务端
|
||||||
* @param account 用户唯一ID
|
* @param account 用户唯一ID
|
||||||
*/
|
*/
|
||||||
public static void setAccount(Context context,String account)
|
public static void bindAccount(Context context,String account)
|
||||||
|
|
||||||
示例
|
示例
|
||||||
CIMPushManager.setAccount(context,"xiyang");
|
CIMPushManager.bindAccount(context,"xiyang");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
8
cim_for_netty/cim-android-sdk/.classpath
Normal file
8
cim_for_netty/cim-android-sdk/.classpath
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
|
<classpathentry kind="lib" path="C:/dev/Android-SDK-Windows/platforms/android-19/android.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/cim-server/WebRoot/WEB-INF/lib/netty-all-5.0.0.Alpha2.jar" sourcepath="C:/Users/Administrator/Desktop/netty-all-5.0.0.Alpha2-sources.jar"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
17
cim_for_netty/cim-android-sdk/.project
Normal file
17
cim_for_netty/cim-android-sdk/.project
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>cim-android-sdk</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
@ -1,12 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* probject:cim-android-sdk
|
||||||
|
* @version 2.0.0
|
||||||
|
*
|
||||||
|
* @author 3979434@qq.com
|
||||||
|
*/
|
||||||
package com.farsunset.cim.client.android;
|
package com.farsunset.cim.client.android;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
/**
|
|
||||||
*
|
class CIMCacheTools {
|
||||||
* @author 3979434
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class CIMDataConfig {
|
|
||||||
|
|
||||||
|
|
||||||
public static String CIM_CONFIG_INFO = "CIM_CONFIG_INFO";
|
public static String CIM_CONFIG_INFO = "CIM_CONFIG_INFO";
|
@ -1,310 +1,306 @@
|
|||||||
package com.farsunset.cim.client.android;
|
package com.farsunset.cim.client.android;
|
||||||
import java.net.InetSocketAddress;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import java.util.concurrent.ExecutorService;
|
import io.netty.channel.Channel;
|
||||||
import java.util.concurrent.Executors;
|
import io.netty.channel.ChannelFuture;
|
||||||
import java.util.concurrent.Future;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import org.jboss.netty.bootstrap.ClientBootstrap;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import org.jboss.netty.channel.Channel;
|
import io.netty.channel.ChannelOption;
|
||||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import org.jboss.netty.channel.ChannelPipeline;
|
import io.netty.channel.EventLoopGroup;
|
||||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
import org.jboss.netty.channel.ChannelStateEvent;
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
import org.jboss.netty.channel.Channels;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import org.jboss.netty.channel.ExceptionEvent;
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
import org.jboss.netty.channel.MessageEvent;
|
import io.netty.handler.codec.serialization.ClassResolvers;
|
||||||
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
import org.jboss.netty.channel.WriteCompletionEvent;
|
import java.net.InetSocketAddress;
|
||||||
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
import android.content.Context;
|
import java.util.concurrent.Future;
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.ConnectivityManager;
|
import android.content.Context;
|
||||||
import android.net.NetworkInfo;
|
import android.content.Intent;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
import com.farsunset.cim.nio.filter.ClientMessageDecoder;
|
import android.net.NetworkInfo;
|
||||||
import com.farsunset.cim.nio.filter.ClientMessageEncoder;
|
|
||||||
import com.farsunset.cim.nio.mutual.Message;
|
import com.farsunset.cim.client.constant.CIMConstant;
|
||||||
import com.farsunset.cim.nio.mutual.ReplyBody;
|
import com.farsunset.cim.client.exception.CIMSessionDisableException;
|
||||||
import com.farsunset.cim.nio.mutual.SentBody;
|
import com.farsunset.cim.client.exception.NetWorkDisableException;
|
||||||
|
import com.farsunset.cim.client.exception.WriteToClosedSessionException;
|
||||||
/**
|
import com.farsunset.cim.client.filter.ClientMessageDecoder;
|
||||||
* 连接服务端管理,cim核心处理类,管理连接,以及消息处理
|
import com.farsunset.cim.client.filter.ClientMessageEncoder;
|
||||||
*
|
import com.farsunset.cim.client.model.Message;
|
||||||
* @author 3979434@qq.com
|
import com.farsunset.cim.client.model.ReplyBody;
|
||||||
*/
|
import com.farsunset.cim.client.model.SentBody;
|
||||||
class CIMConnectorManager {
|
|
||||||
|
/**
|
||||||
private Channel channel;;
|
* 连接服务端管理,cim核心处理类,管理连接,以及消息处理
|
||||||
|
*
|
||||||
Context context;
|
* @author 3979434@qq.com
|
||||||
|
*/
|
||||||
ClientBootstrap bootstrap;
|
@io.netty.channel.ChannelHandler.Sharable
|
||||||
|
class CIMConnectorManager extends SimpleChannelInboundHandler<Object> {
|
||||||
static CIMConnectorManager manager;
|
|
||||||
|
private Channel channel;;
|
||||||
// 消息广播action
|
|
||||||
public static final String ACTION_MESSAGE_RECEIVED = "com.farsunset.cim.MESSAGE_RECEIVED";
|
Context context;
|
||||||
|
|
||||||
// 发送sendbody失败广播
|
Bootstrap bootstrap;
|
||||||
public static final String ACTION_SENT_FAILED = "com.farsunset.cim.SENT_FAILED";
|
EventLoopGroup loopGroup ;
|
||||||
|
static CIMConnectorManager manager;
|
||||||
// 发送sendbody成功广播
|
|
||||||
public static final String ACTION_SENT_SUCCESS = "com.farsunset.cim.SENT_SUCCESS";
|
// 消息广播action
|
||||||
// 链接意外关闭广播
|
public static final String ACTION_MESSAGE_RECEIVED = "com.farsunset.cim.MESSAGE_RECEIVED";
|
||||||
public static final String ACTION_CONNECTION_CLOSED = "com.farsunset.cim.CONNECTION_CLOSED";
|
|
||||||
// 链接失败广播
|
// 发送sendbody失败广播
|
||||||
public static final String ACTION_CONNECTION_FAILED = "com.farsunset.cim.CONNECTION_FAILED";
|
public static final String ACTION_SENT_FAILED = "com.farsunset.cim.SENT_FAILED";
|
||||||
// 链接成功广播
|
|
||||||
public static final String ACTION_CONNECTION_SUCCESS = "com.farsunset.cim.CONNECTION_SUCCESS";
|
// 发送sendbody成功广播
|
||||||
// 发送sendbody成功后获得replaybody回应广播
|
public static final String ACTION_SENT_SUCCESS = "com.farsunset.cim.SENT_SUCCESS";
|
||||||
public static final String ACTION_REPLY_RECEIVED = "com.farsunset.cim.REPLY_RECEIVED";
|
// 链接意外关闭广播
|
||||||
// 网络变化广播
|
public static final String ACTION_CONNECTION_CLOSED = "com.farsunset.cim.CONNECTION_CLOSED";
|
||||||
public static final String ACTION_NETWORK_CHANGED = "android.net.conn.CONNECTIVITY_CHANGE";
|
// 链接失败广播
|
||||||
|
public static final String ACTION_CONNECTION_FAILED = "com.farsunset.cim.CONNECTION_FAILED";
|
||||||
// 未知异常
|
// 链接成功广播
|
||||||
public static final String ACTION_UNCAUGHT_EXCEPTION = "com.farsunset.cim.UNCAUGHT_EXCEPTION";
|
public static final String ACTION_CONNECTION_SUCCESS = "com.farsunset.cim.CONNECTION_SUCCESS";
|
||||||
|
// 发送sendbody成功后获得replaybody回应广播
|
||||||
// CIM连接状态
|
public static final String ACTION_REPLY_RECEIVED = "com.farsunset.cim.REPLY_RECEIVED";
|
||||||
public static final String ACTION_CONNECTION_STATUS = "com.farsunset.cim.CONNECTION_STATUS";
|
// 网络变化广播
|
||||||
|
public static final String ACTION_NETWORK_CHANGED = "android.net.conn.CONNECTIVITY_CHANGE";
|
||||||
|
|
||||||
private ExecutorService executor;
|
// 未知异常
|
||||||
|
public static final String ACTION_UNCAUGHT_EXCEPTION = "com.farsunset.cim.UNCAUGHT_EXCEPTION";
|
||||||
|
|
||||||
private CIMConnectorManager(Context ctx) {
|
// CIM连接状态
|
||||||
context = ctx;
|
public static final String ACTION_CONNECTION_STATUS = "com.farsunset.cim.CONNECTION_STATUS";
|
||||||
executor = Executors.newFixedThreadPool(3);
|
|
||||||
|
|
||||||
|
private ExecutorService executor;
|
||||||
bootstrap = new ClientBootstrap(
|
|
||||||
new NioClientSocketChannelFactory(
|
|
||||||
Executors.newCachedThreadPool(),
|
private CIMConnectorManager(Context ctx) {
|
||||||
Executors.newCachedThreadPool()));
|
context = ctx;
|
||||||
|
executor = Executors.newFixedThreadPool(3);
|
||||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
bootstrap = new Bootstrap();
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
loopGroup = new NioEventLoopGroup();
|
||||||
return Channels.pipeline(
|
bootstrap.group(loopGroup);
|
||||||
new ClientMessageDecoder(),
|
bootstrap.channel(NioSocketChannel.class);
|
||||||
new ClientMessageEncoder(),
|
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
|
||||||
channelUpstreamHandler);
|
@Override
|
||||||
}
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
});
|
ChannelPipeline pipeline = ch.pipeline();
|
||||||
|
pipeline.addLast(new ClientMessageDecoder(ClassResolvers.cacheDisabled(null)));
|
||||||
|
pipeline.addLast(new ClientMessageEncoder());
|
||||||
}
|
pipeline.addLast(CIMConnectorManager.this);
|
||||||
|
|
||||||
public synchronized static CIMConnectorManager getManager(Context context) {
|
}
|
||||||
if (manager == null) {
|
});
|
||||||
manager = new CIMConnectorManager(context);
|
bootstrap.option(ChannelOption.TCP_NODELAY, true);
|
||||||
}
|
|
||||||
return manager;
|
}
|
||||||
|
|
||||||
}
|
public synchronized static CIMConnectorManager getManager(Context context) {
|
||||||
|
if (manager == null) {
|
||||||
private synchronized void syncConnection(final String cimServerHost,final int cimServerPort) {
|
manager = new CIMConnectorManager(context);
|
||||||
try {
|
}
|
||||||
|
return manager;
|
||||||
if(isConnected()){
|
|
||||||
return ;
|
}
|
||||||
}
|
|
||||||
|
private synchronized void syncConnection(final String cimServerHost,final int cimServerPort) {
|
||||||
channel = bootstrap.connect(new InetSocketAddress(cimServerHost, cimServerPort)).getChannel(); //这里的IP和端口,根据自己情况修改
|
try {
|
||||||
|
|
||||||
} catch (Exception e) {
|
if(isConnected()){
|
||||||
|
return ;
|
||||||
Intent intent = new Intent();
|
}
|
||||||
intent.setAction(ACTION_CONNECTION_FAILED);
|
ChannelFuture channelFuture = bootstrap.connect(new InetSocketAddress(cimServerHost, cimServerPort)).sync(); //这里的IP和端口,根据自己情况修改
|
||||||
intent.putExtra("exception", e);
|
channel = channelFuture.channel();
|
||||||
context.sendBroadcast(intent);
|
} catch (Exception e) {
|
||||||
|
|
||||||
System.out.println("******************CIM连接服务器失败 "+cimServerHost+":"+cimServerPort);
|
Intent intent = new Intent();
|
||||||
|
intent.setAction(ACTION_CONNECTION_FAILED);
|
||||||
}
|
intent.putExtra("exception", e);
|
||||||
|
context.sendBroadcast(intent);
|
||||||
}
|
|
||||||
|
System.out.println("******************CIM连接服务器失败 "+cimServerHost+":"+cimServerPort);
|
||||||
public void connect(final String cimServerHost, final int cimServerPort) {
|
|
||||||
|
}
|
||||||
|
|
||||||
if (!netWorkAvailable(context)) {
|
}
|
||||||
|
|
||||||
Intent intent = new Intent();
|
public void connect(final String cimServerHost, final int cimServerPort) {
|
||||||
intent.setAction(ACTION_CONNECTION_FAILED);
|
|
||||||
intent.putExtra("exception", new NetWorkDisableException());
|
|
||||||
context.sendBroadcast(intent);
|
if (!netWorkAvailable(context)) {
|
||||||
|
|
||||||
return;
|
Intent intent = new Intent();
|
||||||
}
|
intent.setAction(ACTION_CONNECTION_FAILED);
|
||||||
|
intent.putExtra("exception", new NetWorkDisableException());
|
||||||
Future<?> future = executor.submit(new Runnable() {
|
context.sendBroadcast(intent);
|
||||||
@Override
|
|
||||||
public void run() {
|
return;
|
||||||
syncConnection(cimServerHost, cimServerPort);
|
}
|
||||||
}
|
|
||||||
});
|
Future<?> future = executor.submit(new Runnable() {
|
||||||
try {
|
@Override
|
||||||
if(future.get()!=null)
|
public void run() {
|
||||||
{
|
syncConnection(cimServerHost, cimServerPort);
|
||||||
connect(cimServerHost,cimServerPort);
|
}
|
||||||
}
|
});
|
||||||
} catch (Exception e) {
|
try {
|
||||||
|
if(future.get()!=null)
|
||||||
connect(cimServerHost,cimServerPort);
|
{
|
||||||
e.printStackTrace();
|
connect(cimServerHost,cimServerPort);
|
||||||
}
|
}
|
||||||
}
|
} catch (Exception e) {
|
||||||
|
|
||||||
public void send(final SentBody body) {
|
connect(cimServerHost,cimServerPort);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
executor.execute(new Runnable() {
|
}
|
||||||
@Override
|
|
||||||
public void run() {
|
public void send(final SentBody body) {
|
||||||
|
|
||||||
android.os.Message msg = new android.os.Message();
|
|
||||||
msg.getData().putSerializable("body", body);
|
executor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
if(channel!=null && channel.isConnected())
|
public void run() {
|
||||||
{
|
|
||||||
boolean isDone = channel.write(body).awaitUninterruptibly(5000);
|
android.os.Message msg = new android.os.Message();
|
||||||
if (!isDone) {
|
msg.getData().putSerializable("body", body);
|
||||||
|
|
||||||
Intent intent = new Intent();
|
if(channel!=null && channel.isActive())
|
||||||
intent.setAction(ACTION_SENT_FAILED);
|
{
|
||||||
intent.putExtra("exception", new WriteToClosedSessionException());
|
boolean isDone = channel.writeAndFlush(body).awaitUninterruptibly(5000);
|
||||||
intent.putExtra("sentBody", body);
|
if (!isDone) {
|
||||||
context.sendBroadcast(intent);
|
|
||||||
}
|
Intent intent = new Intent();
|
||||||
}else
|
intent.setAction(ACTION_SENT_FAILED);
|
||||||
{
|
intent.putExtra("exception", new WriteToClosedSessionException());
|
||||||
|
intent.putExtra("sentBody", body);
|
||||||
Intent intent = new Intent();
|
context.sendBroadcast(intent);
|
||||||
intent.setAction(ACTION_SENT_FAILED);
|
}else
|
||||||
intent.putExtra("exception", new CIMSessionDisableException());
|
{
|
||||||
intent.putExtra("sentBody", body);
|
Intent intent = new Intent();
|
||||||
context.sendBroadcast(intent);
|
intent.setAction(ACTION_SENT_SUCCESS);
|
||||||
}
|
intent.putExtra("sentBody", body);
|
||||||
}
|
context.sendBroadcast(intent);
|
||||||
});
|
}
|
||||||
}
|
}else
|
||||||
|
{
|
||||||
public void destroy() {
|
|
||||||
if (manager.channel != null) {
|
Intent intent = new Intent();
|
||||||
manager.channel.close();
|
intent.setAction(ACTION_SENT_FAILED);
|
||||||
}
|
intent.putExtra("exception", new CIMSessionDisableException());
|
||||||
bootstrap.shutdown();
|
intent.putExtra("sentBody", body);
|
||||||
bootstrap.releaseExternalResources();
|
context.sendBroadcast(intent);
|
||||||
manager = null;
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
public boolean isConnected() {
|
}
|
||||||
if (channel == null) {
|
|
||||||
return false;
|
public void destroy() {
|
||||||
}
|
if (manager.channel != null) {
|
||||||
return channel.isConnected() ;
|
manager.channel.close();
|
||||||
}
|
}
|
||||||
|
loopGroup.shutdownGracefully();
|
||||||
public void deliverIsConnected() {
|
manager = null;
|
||||||
Intent intent = new Intent();
|
}
|
||||||
intent.setAction(ACTION_CONNECTION_STATUS);
|
|
||||||
intent.putExtra(CIMPushManager.KEY_CIM_CONNECTION_STATUS, isConnected());
|
public boolean isConnected() {
|
||||||
context.sendBroadcast(intent);
|
if (channel == null) {
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
return channel.isActive() ;
|
||||||
|
}
|
||||||
public void closeSession()
|
|
||||||
{
|
public void deliverIsConnected() {
|
||||||
if(channel!=null)
|
Intent intent = new Intent();
|
||||||
{
|
intent.setAction(ACTION_CONNECTION_STATUS);
|
||||||
channel.close();
|
intent.putExtra(CIMPushManager.KEY_CIM_CONNECTION_STATUS, isConnected());
|
||||||
}
|
context.sendBroadcast(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SimpleChannelUpstreamHandler channelUpstreamHandler = new SimpleChannelUpstreamHandler() {
|
|
||||||
|
public void closeSession()
|
||||||
@Override
|
{
|
||||||
public void channelConnected( ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
if(channel!=null)
|
||||||
|
{
|
||||||
System.out.println("******************CIM连接服务器成功:"+ctx.getChannel().getLocalAddress());
|
channel.close();
|
||||||
|
}
|
||||||
Intent intent = new Intent();
|
}
|
||||||
intent.setAction(ACTION_CONNECTION_SUCCESS);
|
|
||||||
context.sendBroadcast(intent);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
public void channelActive( ChannelHandlerContext ctx) throws Exception {
|
||||||
@Override
|
|
||||||
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent event) throws Exception {
|
System.out.println("******************CIM连接服务器成功:"+ctx.channel().localAddress());
|
||||||
|
|
||||||
System.out.println("******************CIM与服务器断开连接:"+ctx.getChannel().getLocalAddress());
|
Intent intent = new Intent();
|
||||||
if(channel.getId()==ctx.getChannel().getId())
|
intent.setAction(ACTION_CONNECTION_SUCCESS);
|
||||||
{
|
context.sendBroadcast(intent);
|
||||||
Intent intent = new Intent();
|
}
|
||||||
intent.setAction(ACTION_CONNECTION_CLOSED);
|
|
||||||
context.sendBroadcast(intent);
|
|
||||||
|
@Override
|
||||||
}
|
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||||
}
|
|
||||||
|
System.out.println("******************closeCIM与服务器断开连接:"+ctx.channel().localAddress());
|
||||||
|
if(channel.id().asLongText().equals(ctx.channel().id().asLongText()))
|
||||||
|
{
|
||||||
@Override
|
Intent intent = new Intent();
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
|
intent.setAction(ACTION_CONNECTION_CLOSED);
|
||||||
throws Exception {
|
context.sendBroadcast(intent);
|
||||||
|
|
||||||
Intent intent = new Intent();
|
}
|
||||||
intent.setAction(ACTION_UNCAUGHT_EXCEPTION);
|
}
|
||||||
intent.putExtra("exception", e.getCause());
|
|
||||||
context.sendBroadcast(intent);
|
|
||||||
}
|
@Override
|
||||||
|
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||||
@Override
|
|
||||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent event)
|
Intent intent = new Intent();
|
||||||
throws Exception {
|
intent.setAction(ACTION_UNCAUGHT_EXCEPTION);
|
||||||
|
intent.putExtra("exception", cause.getCause());
|
||||||
if (event.getMessage() instanceof Message) {
|
context.sendBroadcast(intent);
|
||||||
|
}
|
||||||
Intent intent = new Intent();
|
|
||||||
intent.setAction(ACTION_MESSAGE_RECEIVED);
|
@Override
|
||||||
intent.putExtra("message", (Message) event.getMessage());
|
protected void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||||
context.sendBroadcast(intent);
|
|
||||||
|
if (msg instanceof Message) {
|
||||||
}
|
Intent intent = new Intent();
|
||||||
if (event.getMessage() instanceof ReplyBody) {
|
intent.setAction(ACTION_MESSAGE_RECEIVED);
|
||||||
|
intent.putExtra("message", (Message) msg);
|
||||||
|
context.sendBroadcast(intent);
|
||||||
Intent intent = new Intent();
|
|
||||||
intent.setAction(ACTION_REPLY_RECEIVED);
|
}
|
||||||
intent.putExtra("replyBody", (ReplyBody) event.getMessage());
|
if (msg instanceof ReplyBody) {
|
||||||
context.sendBroadcast(intent);
|
Intent intent = new Intent();
|
||||||
}
|
intent.setAction(ACTION_REPLY_RECEIVED);
|
||||||
}
|
intent.putExtra("replyBody", (ReplyBody) msg);
|
||||||
|
context.sendBroadcast(intent);
|
||||||
@Override
|
}
|
||||||
public void writeComplete(ChannelHandlerContext ctx, WriteCompletionEvent event)
|
|
||||||
throws Exception {
|
//收到服务端发来的心跳请求命令,则马上回应服务器
|
||||||
|
if (msg.equals(CIMConstant.CMD_HEARTBEAT_REQUEST)) {
|
||||||
Intent intent = new Intent();
|
ctx.writeAndFlush(CIMConstant.CMD_HEARTBEAT_RESPONSE);
|
||||||
intent.setAction(ACTION_SENT_SUCCESS);
|
}
|
||||||
//intent.putExtra("sentBody", null);
|
}
|
||||||
context.sendBroadcast(intent);
|
|
||||||
|
public static boolean netWorkAvailable(Context context) {
|
||||||
|
try {
|
||||||
}
|
ConnectivityManager nw = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
};
|
NetworkInfo networkInfo = nw.getActiveNetworkInfo();
|
||||||
|
return networkInfo != null;
|
||||||
public static boolean netWorkAvailable(Context context) {
|
} catch (Exception e) {}
|
||||||
try {
|
|
||||||
ConnectivityManager nw = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
return false;
|
||||||
NetworkInfo networkInfo = nw.getActiveNetworkInfo();
|
}
|
||||||
return networkInfo != null;
|
|
||||||
} catch (Exception e) {}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,188 +1,239 @@
|
|||||||
package com.farsunset.cim.client.android;
|
/**
|
||||||
|
* probject:cim-android-sdk
|
||||||
import java.util.List;
|
* @version 2.0.0
|
||||||
|
*
|
||||||
import android.app.ActivityManager;
|
* @author 3979434@qq.com
|
||||||
import android.app.ActivityManager.RunningTaskInfo;
|
*/
|
||||||
import android.content.BroadcastReceiver;
|
package com.farsunset.cim.client.android;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
import java.util.List;
|
||||||
import android.net.ConnectivityManager;
|
|
||||||
import android.net.NetworkInfo;
|
import android.app.ActivityManager;
|
||||||
import android.os.Handler;
|
import android.app.ActivityManager.RunningTaskInfo;
|
||||||
import com.farsunset.cim.nio.constant.CIMConstant;
|
import android.content.BroadcastReceiver;
|
||||||
import com.farsunset.cim.nio.mutual.Message;
|
import android.content.Context;
|
||||||
import com.farsunset.cim.nio.mutual.ReplyBody;
|
import android.content.Intent;
|
||||||
import com.farsunset.cim.nio.mutual.SentBody;
|
import android.net.ConnectivityManager;
|
||||||
/**
|
import android.net.NetworkInfo;
|
||||||
* 消息入口,所有消息都会经过这里
|
import android.os.Handler;
|
||||||
* @author 3979434
|
|
||||||
*
|
import com.farsunset.cim.client.constant.CIMConstant;
|
||||||
*/
|
import com.farsunset.cim.client.exception.CIMSessionDisableException;
|
||||||
public abstract class CIMEnventListenerReceiver extends BroadcastReceiver implements OnCIMMessageListener {
|
import com.farsunset.cim.client.model.Message;
|
||||||
|
import com.farsunset.cim.client.model.ReplyBody;
|
||||||
|
import com.farsunset.cim.client.model.SentBody;
|
||||||
public Context context;
|
/**
|
||||||
@Override
|
* 消息入口,所有消息都会经过这里
|
||||||
public void onReceive(Context ctx, Intent it) {
|
*/
|
||||||
|
public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver implements CIMEventListener {
|
||||||
context = ctx;
|
|
||||||
|
|
||||||
if(it.getAction().equals(CIMConnectorManager.ACTION_NETWORK_CHANGED))
|
public Context context;
|
||||||
{
|
@Override
|
||||||
ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService("connectivity");
|
public void onReceive(Context ctx, Intent it) {
|
||||||
android.net.NetworkInfo info = connectivityManager.getActiveNetworkInfo();
|
|
||||||
|
context = ctx;
|
||||||
onDevicesNetworkChanged(info);
|
|
||||||
}
|
/*
|
||||||
|
* 操作事件广播,用于提高service存活率
|
||||||
if(it.getAction().equals(CIMConnectorManager.ACTION_CONNECTION_CLOSED))
|
*/
|
||||||
{
|
if(it.getAction().equals(Intent.ACTION_USER_PRESENT)
|
||||||
dispatchConnectionClosed();
|
||it.getAction().equals(Intent.ACTION_POWER_CONNECTED)
|
||||||
}
|
||it.getAction().equals(Intent.ACTION_POWER_DISCONNECTED)
|
||||||
|
)
|
||||||
if(it.getAction().equals(CIMConnectorManager.ACTION_CONNECTION_FAILED))
|
{
|
||||||
{
|
startPushService();
|
||||||
onConnectionFailed((Exception) it.getSerializableExtra("exception"));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(it.getAction().equals(CIMConnectorManager.ACTION_CONNECTION_SUCCESS))
|
/*
|
||||||
{
|
* 设备网络状态变化事件
|
||||||
dispatchConnectionSucceed();
|
*/
|
||||||
}
|
if(it.getAction().equals(CIMConnectorManager.ACTION_NETWORK_CHANGED))
|
||||||
|
{
|
||||||
if(it.getAction().equals(CIMConnectorManager.ACTION_MESSAGE_RECEIVED))
|
ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
{
|
android.net.NetworkInfo info = connectivityManager.getActiveNetworkInfo();
|
||||||
filterType999Message((Message)it.getSerializableExtra("message"));
|
onDevicesNetworkChanged(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(it.getAction().equals(CIMConnectorManager.ACTION_REPLY_RECEIVED))
|
/*
|
||||||
{
|
* cim断开服务器事件
|
||||||
onReplyReceived((ReplyBody)it.getSerializableExtra("replyBody"));
|
*/
|
||||||
}
|
if(it.getAction().equals(CIMConnectorManager.ACTION_CONNECTION_CLOSED))
|
||||||
|
{
|
||||||
if(it.getAction().equals(CIMConnectorManager.ACTION_SENT_FAILED))
|
if(CIMConnectorManager.netWorkAvailable(context))
|
||||||
{
|
{
|
||||||
onSentFailed((Exception) it.getSerializableExtra("exception"),(SentBody)it.getSerializableExtra("sentBody"));
|
CIMPushManager.init(context);
|
||||||
}
|
}
|
||||||
|
onCIMConnectionClosed();
|
||||||
if(it.getAction().equals(CIMConnectorManager.ACTION_SENT_SUCCESS))
|
}
|
||||||
{
|
|
||||||
onSentSucceed((SentBody)it.getSerializableExtra("sentBody"));
|
/*
|
||||||
}
|
* cim连接服务器失败事件
|
||||||
|
*/
|
||||||
if(it.getAction().equals(CIMConnectorManager.ACTION_UNCAUGHT_EXCEPTION))
|
if(it.getAction().equals(CIMConnectorManager.ACTION_CONNECTION_FAILED))
|
||||||
{
|
{
|
||||||
onUncaughtException((Exception)it.getSerializableExtra("exception"));
|
onConnectionFailed((Exception) it.getSerializableExtra("exception"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(it.getAction().equals(CIMConnectorManager.ACTION_CONNECTION_STATUS))
|
/*
|
||||||
{
|
* cim连接服务器成功事件
|
||||||
onConnectionStatus(it.getBooleanExtra(CIMPushManager.KEY_CIM_CONNECTION_STATUS, false));
|
*/
|
||||||
}
|
if(it.getAction().equals(CIMConnectorManager.ACTION_CONNECTION_SUCCESS))
|
||||||
|
{
|
||||||
|
|
||||||
}
|
|
||||||
|
CIMPushManager.bindAccount(context);
|
||||||
|
|
||||||
private void dispatchConnectionClosed() {
|
onCIMConnectionSucceed();
|
||||||
|
}
|
||||||
if(CIMConnectorManager.netWorkAvailable(context))
|
|
||||||
{
|
/*
|
||||||
CIMPushManager.init(context);
|
* 收到推送消息事件
|
||||||
}
|
*/
|
||||||
|
if(it.getAction().equals(CIMConnectorManager.ACTION_MESSAGE_RECEIVED))
|
||||||
onConnectionClosed();
|
{
|
||||||
}
|
filterType999Message((Message)it.getSerializableExtra("message"));
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean isInBackground(Context context) {
|
|
||||||
List<RunningTaskInfo> tasksInfo = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getRunningTasks(1);
|
/*
|
||||||
if (tasksInfo.size() > 0) {
|
* 获取收到replybody成功事件
|
||||||
|
*/
|
||||||
if (context.getPackageName().equals(
|
if(it.getAction().equals(CIMConnectorManager.ACTION_REPLY_RECEIVED))
|
||||||
tasksInfo.get(0).topActivity.getPackageName())) {
|
{
|
||||||
|
onReplyReceived((ReplyBody)it.getSerializableExtra("replyBody"));
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
/*
|
||||||
}
|
* 获取sendbody发送失败事件
|
||||||
|
*/
|
||||||
private void onConnectionFailed(Exception e){
|
if(it.getAction().equals(CIMConnectorManager.ACTION_SENT_FAILED))
|
||||||
|
{
|
||||||
if(CIMConnectorManager.netWorkAvailable(context))
|
onSentFailed((Exception) it.getSerializableExtra("exception"),(SentBody)it.getSerializableExtra("sentBody"));
|
||||||
{
|
}
|
||||||
//间隔30秒后重连
|
|
||||||
connectionHandler.sendMessageDelayed(connectionHandler.obtainMessage(), 30*1000);
|
/*
|
||||||
}
|
* 获取sendbody发送成功事件
|
||||||
}
|
*/
|
||||||
|
if(it.getAction().equals(CIMConnectorManager.ACTION_SENT_SUCCESS))
|
||||||
|
{
|
||||||
Handler connectionHandler = new Handler()
|
onSentSucceed((SentBody)it.getSerializableExtra("sentBody"));
|
||||||
{
|
}
|
||||||
@Override
|
|
||||||
public void handleMessage(android.os.Message message){
|
|
||||||
|
/*
|
||||||
CIMPushManager.init(context);
|
* 获取cim数据传输异常事件
|
||||||
}
|
*/
|
||||||
|
if(it.getAction().equals(CIMConnectorManager.ACTION_UNCAUGHT_EXCEPTION))
|
||||||
};
|
{
|
||||||
|
onUncaughtException((Exception)it.getSerializableExtra("exception"));
|
||||||
private void dispatchConnectionSucceed() {
|
}
|
||||||
|
|
||||||
CIMPushManager.setAccount(context);
|
/*
|
||||||
onConnectionSucceed();
|
* 获取cim连接状态事件
|
||||||
|
*/
|
||||||
}
|
if(it.getAction().equals(CIMConnectorManager.ACTION_CONNECTION_STATUS))
|
||||||
|
{
|
||||||
|
onConnectionStatus(it.getBooleanExtra(CIMPushManager.KEY_CIM_CONNECTION_STATUS, false));
|
||||||
|
}
|
||||||
private void onUncaughtException(Throwable arg0) {}
|
}
|
||||||
|
|
||||||
|
protected boolean isInBackground(Context context) {
|
||||||
|
List<RunningTaskInfo> tasksInfo = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getRunningTasks(1);
|
||||||
private void onDevicesNetworkChanged(NetworkInfo info) {
|
if (tasksInfo.size() > 0) {
|
||||||
|
|
||||||
if(info !=null)
|
if (context.getPackageName().equals(
|
||||||
{
|
tasksInfo.get(0).topActivity.getPackageName())) {
|
||||||
CIMPushManager.init(context);
|
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
onNetworkChanged(info);
|
}
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
private void filterType999Message(com.farsunset.cim.nio.mutual.Message message)
|
|
||||||
{
|
|
||||||
if(CIMConstant.MessageType.TYPE_999.equals(message.getType()))
|
private void startPushService()
|
||||||
{
|
{
|
||||||
CIMDataConfig.putBoolean(context,CIMDataConfig.KEY_MANUAL_STOP,true);
|
Intent intent = new Intent(context, CIMPushService.class);
|
||||||
}
|
intent.putExtra(CIMPushManager.SERVICE_ACTION, CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE);
|
||||||
|
context.startService(intent);
|
||||||
onMessageReceived(message);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void onSentFailed(Exception e, SentBody body){
|
|
||||||
|
|
||||||
//与服务端端开链接,重新连接
|
private void onConnectionFailed(Exception e){
|
||||||
if(e instanceof CIMSessionDisableException)
|
|
||||||
{
|
if(CIMConnectorManager.netWorkAvailable(context))
|
||||||
CIMPushManager.init(context);
|
{
|
||||||
}else
|
//间隔30秒后重连
|
||||||
{
|
connectionHandler.sendMessageDelayed(connectionHandler.obtainMessage(), 30*1000);
|
||||||
//发送失败 重新发送
|
}
|
||||||
CIMPushManager.sendRequest(context, body);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
Handler connectionHandler = new Handler()
|
||||||
|
{
|
||||||
private void onSentSucceed(SentBody body){}
|
@Override
|
||||||
|
public void handleMessage(android.os.Message message){
|
||||||
@Override
|
|
||||||
public abstract void onMessageReceived(com.farsunset.cim.nio.mutual.Message message);
|
CIMPushManager.init(context);
|
||||||
@Override
|
}
|
||||||
public abstract void onReplyReceived(ReplyBody body);
|
|
||||||
|
};
|
||||||
public abstract void onNetworkChanged(NetworkInfo info);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
private void onUncaughtException(Throwable arg0) {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void onDevicesNetworkChanged(NetworkInfo info) {
|
||||||
|
|
||||||
|
if(info !=null)
|
||||||
|
{
|
||||||
|
CIMPushManager.init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
onNetworkChanged(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void filterType999Message(com.farsunset.cim.client.model.Message message)
|
||||||
|
{
|
||||||
|
if(CIMConstant.MessageType.TYPE_999.equals(message.getType()))
|
||||||
|
{
|
||||||
|
CIMCacheTools.putBoolean(context,CIMCacheTools.KEY_MANUAL_STOP,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMessageReceived(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSentFailed(Exception e, SentBody body){
|
||||||
|
|
||||||
|
//与服务端端开链接,重新连接
|
||||||
|
if(e instanceof CIMSessionDisableException)
|
||||||
|
{
|
||||||
|
CIMPushManager.init(context);
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
//发送失败 重新发送
|
||||||
|
CIMPushManager.sendRequest(context, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSentSucceed(SentBody body){}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract void onMessageReceived(com.farsunset.cim.client.model.Message message);
|
||||||
|
@Override
|
||||||
|
public abstract void onReplyReceived(ReplyBody body);
|
||||||
|
|
||||||
|
public abstract void onNetworkChanged(NetworkInfo info);
|
||||||
|
|
||||||
|
public abstract void onCIMConnectionSucceed();
|
||||||
|
|
||||||
|
public abstract void onCIMConnectionClosed();
|
||||||
|
}
|
@ -1,23 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* probject:cim-android-sdk
|
||||||
|
* @version 2.0.0
|
||||||
|
*
|
||||||
|
* @author 3979434@qq.com
|
||||||
|
*/
|
||||||
package com.farsunset.cim.client.android;
|
package com.farsunset.cim.client.android;
|
||||||
|
|
||||||
import android.net.NetworkInfo;
|
import android.net.NetworkInfo;
|
||||||
|
|
||||||
import com.farsunset.cim.nio.mutual.Message;
|
import com.farsunset.cim.client.model.Message;
|
||||||
import com.farsunset.cim.nio.mutual.ReplyBody;
|
import com.farsunset.cim.client.model.ReplyBody;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*CIM 主要事件接口
|
*CIM 主要事件接口
|
||||||
* 类名称:OnCIMMessageListener
|
|
||||||
* 类描述:
|
|
||||||
* 创建人: 3979434
|
|
||||||
* 修改人: 3979434
|
|
||||||
* 修改时间: 2014-4-28 下午5:07:47
|
|
||||||
* 修改备注:
|
|
||||||
* @version 1.0.0
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface OnCIMMessageListener
|
public interface CIMEventListener
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
@ -25,36 +22,36 @@ public interface OnCIMMessageListener
|
|||||||
* 当收到服务端推送过来的消息时调用
|
* 当收到服务端推送过来的消息时调用
|
||||||
* @param message
|
* @param message
|
||||||
*/
|
*/
|
||||||
public abstract void onMessageReceived(Message message);
|
public void onMessageReceived(Message message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当调用CIMPushManager.sendRequest()向服务端发送请求,获得相应时调用
|
* 当调用CIMPushManager.sendRequest()向服务端发送请求,获得相应时调用
|
||||||
* @param replybody
|
* @param replybody
|
||||||
*/
|
*/
|
||||||
public abstract void onReplyReceived(ReplyBody replybody);
|
public void onReplyReceived(ReplyBody replybody);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当手机网络发生变化时调用
|
* 当手机网络发生变化时调用
|
||||||
* @param networkinfo
|
* @param networkinfo
|
||||||
*/
|
*/
|
||||||
public abstract void onNetworkChanged(NetworkInfo networkinfo);
|
public void onNetworkChanged(NetworkInfo networkinfo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取到是否连接到服务端
|
* 获取到是否连接到服务端
|
||||||
* 通过调用CIMPushManager.detectIsConnected()来异步获取
|
* 通过调用CIMPushManager.detectIsConnected()来异步获取
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract void onConnectionStatus(boolean isConnected);
|
public void onConnectionStatus(boolean isConnected);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 连接服务端成功
|
* 连接服务端成功
|
||||||
*/
|
*/
|
||||||
public abstract void onConnectionSucceed();
|
public void onCIMConnectionSucceed();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 连接断开
|
* 连接断开
|
||||||
*/
|
*/
|
||||||
public abstract void onConnectionClosed();
|
public void onCIMConnectionClosed();
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,101 @@
|
|||||||
|
/**
|
||||||
|
* probject:cim-android-sdk
|
||||||
|
* @version 2.0.0
|
||||||
|
*
|
||||||
|
* @author 3979434@qq.com
|
||||||
|
*/
|
||||||
|
package com.farsunset.cim.client.android;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import com.farsunset.cim.client.constant.CIMConstant;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CIM 消息监听器管理
|
||||||
|
*/
|
||||||
|
public class CIMListenerManager {
|
||||||
|
|
||||||
|
private static ArrayList<CIMEventListener> cimListeners = new ArrayList<CIMEventListener>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void registerMessageListener(CIMEventListener listener,Context mcontext) {
|
||||||
|
|
||||||
|
if (!cimListeners.contains(listener)) {
|
||||||
|
cimListeners.add(listener);
|
||||||
|
// 按照接收顺序倒序
|
||||||
|
Collections.sort(cimListeners, new CIMMessageReceiveComparator(mcontext));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void removeMessageListener(CIMEventListener listener) {
|
||||||
|
for (int i = 0; i < cimListeners.size(); i++) {
|
||||||
|
if (listener.getClass() == cimListeners.get(i).getClass()) {
|
||||||
|
cimListeners.remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ArrayList<CIMEventListener> getCIMListeners() {
|
||||||
|
return cimListeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息接收activity的接收顺序排序,CIM_RECEIVE_ORDER倒序
|
||||||
|
*/
|
||||||
|
static class CIMMessageReceiveComparator implements Comparator<CIMEventListener>{
|
||||||
|
|
||||||
|
Context mcontext;
|
||||||
|
public CIMMessageReceiveComparator(Context ctx)
|
||||||
|
{
|
||||||
|
mcontext = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(CIMEventListener arg1, CIMEventListener arg2) {
|
||||||
|
|
||||||
|
Integer order1 = CIMConstant.CIM_DEFAULT_MESSAGE_ORDER;
|
||||||
|
Integer order2 = CIMConstant.CIM_DEFAULT_MESSAGE_ORDER;
|
||||||
|
ActivityInfo info;
|
||||||
|
if (arg1 instanceof Activity ) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
info = mcontext.getPackageManager() .getActivityInfo(((Activity)(arg1)).getComponentName(), PackageManager.GET_META_DATA);
|
||||||
|
if(info.metaData!=null)
|
||||||
|
{
|
||||||
|
order1 = info.metaData.getInt("CIM_RECEIVE_ORDER");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg1 instanceof Activity ) {
|
||||||
|
try {
|
||||||
|
info = mcontext.getPackageManager() .getActivityInfo(((Activity)(arg2)).getComponentName(), PackageManager.GET_META_DATA);
|
||||||
|
if(info.metaData!=null)
|
||||||
|
{
|
||||||
|
order2 = info.metaData.getInt("CIM_RECEIVE_ORDER");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return order2.compareTo(order1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,191 +1,215 @@
|
|||||||
package com.farsunset.cim.client.android;
|
/**
|
||||||
import android.content.Context;
|
* probject:cim-android-sdk
|
||||||
import android.content.Intent;
|
* @version 2.0.0
|
||||||
import android.telephony.TelephonyManager;
|
*
|
||||||
import java.util.UUID;
|
* @author 3979434@qq.com
|
||||||
import com.farsunset.cim.nio.constant.CIMConstant;
|
*/
|
||||||
import com.farsunset.cim.nio.mutual.SentBody;
|
package com.farsunset.cim.client.android;
|
||||||
|
import java.util.UUID;
|
||||||
/**
|
|
||||||
* CIM 功能接口
|
import android.content.Context;
|
||||||
*
|
import android.content.Intent;
|
||||||
* @author 3979434@qq.com
|
import android.content.pm.PackageInfo;
|
||||||
*/
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
public class CIMPushManager {
|
import android.telephony.TelephonyManager;
|
||||||
|
|
||||||
static String ACTION_CONNECTION_KEEPALIVE ="ACTION_CONNECTION_KEEPALIVE";
|
import com.farsunset.cim.client.constant.CIMConstant;
|
||||||
|
import com.farsunset.cim.client.model.SentBody;
|
||||||
static String ACTION_CONNECTION ="ACTION_CONNECTION";
|
|
||||||
|
/**
|
||||||
static String ACTION_CONNECTION_STATUS ="ACTION_CONNECTION_STATUS";
|
* CIM 功能接口
|
||||||
|
*/
|
||||||
static String ACTION_SENDREQUEST ="ACTION_SENDREQUEST";
|
public class CIMPushManager {
|
||||||
|
|
||||||
static String ACTION_DISCONNECTION ="ACTION_DISSENDREQUEST";
|
static String ACTION_ACTIVATE_PUSH_SERVICE ="ACTION_ACTIVATE_PUSH_SERVICE";
|
||||||
|
|
||||||
static String ACTION_DESTORY ="ACTION_DESTORY";
|
static String ACTION_CONNECTION ="ACTION_CONNECTION";
|
||||||
|
|
||||||
static String SERVICE_ACTION ="SERVICE_ACTION";
|
static String ACTION_CONNECTION_STATUS ="ACTION_CONNECTION_STATUS";
|
||||||
|
|
||||||
static String KEY_SEND_BODY ="KEY_SEND_BODY";
|
static String ACTION_SENDREQUEST ="ACTION_SENDREQUEST";
|
||||||
|
|
||||||
static String KEY_CIM_CONNECTION_STATUS ="KEY_CIM_CONNECTION_STATUS";
|
static String ACTION_DISCONNECTION ="ACTION_DISSENDREQUEST";
|
||||||
|
|
||||||
/**
|
static String ACTION_DESTORY ="ACTION_DESTORY";
|
||||||
* 初始化,连接服务端,在程序启动页或者 在Application里调用
|
|
||||||
* @param context
|
static String SERVICE_ACTION ="SERVICE_ACTION";
|
||||||
* @param ip
|
|
||||||
* @param port
|
static String KEY_SEND_BODY ="KEY_SEND_BODY";
|
||||||
*/
|
|
||||||
public static void init(Context context,String ip,int port){
|
static String KEY_CIM_CONNECTION_STATUS ="KEY_CIM_CONNECTION_STATUS";
|
||||||
|
|
||||||
CIMDataConfig.putBoolean(context,CIMDataConfig.KEY_CIM_DESTORYED, false);
|
/**
|
||||||
CIMDataConfig.putBoolean(context,CIMDataConfig.KEY_MANUAL_STOP, false);
|
* 初始化,连接服务端,在程序启动页或者 在Application里调用
|
||||||
|
* @param context
|
||||||
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
* @param ip
|
||||||
serviceIntent.putExtra(CIMDataConfig.KEY_CIM_SERVIER_HOST, ip);
|
* @param port
|
||||||
serviceIntent.putExtra(CIMDataConfig.KEY_CIM_SERVIER_PORT, port);
|
*/
|
||||||
serviceIntent.putExtra(SERVICE_ACTION, ACTION_CONNECTION);
|
public static void init(Context context,String ip,int port){
|
||||||
context.startService(serviceIntent);
|
|
||||||
CIMDataConfig.putString(context, CIMDataConfig.KEY_CIM_SERVIER_HOST, ip);
|
CIMCacheTools.putBoolean(context,CIMCacheTools.KEY_CIM_DESTORYED, false);
|
||||||
CIMDataConfig.putInt(context, CIMDataConfig.KEY_CIM_SERVIER_PORT, port);
|
CIMCacheTools.putBoolean(context,CIMCacheTools.KEY_MANUAL_STOP, false);
|
||||||
}
|
|
||||||
|
CIMCacheTools.putString(context, CIMCacheTools.KEY_CIM_SERVIER_HOST, ip);
|
||||||
protected static void init(Context context){
|
CIMCacheTools.putInt(context, CIMCacheTools.KEY_CIM_SERVIER_PORT, port);
|
||||||
|
|
||||||
boolean isManualStop = CIMDataConfig.getBoolean(context,CIMDataConfig.KEY_MANUAL_STOP);
|
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
||||||
boolean isManualDestory = CIMDataConfig.getBoolean(context,CIMDataConfig.KEY_CIM_DESTORYED);
|
serviceIntent.putExtra(CIMCacheTools.KEY_CIM_SERVIER_HOST, ip);
|
||||||
|
serviceIntent.putExtra(CIMCacheTools.KEY_CIM_SERVIER_PORT, port);
|
||||||
if(isManualStop || isManualDestory)
|
serviceIntent.putExtra(SERVICE_ACTION, ACTION_CONNECTION);
|
||||||
{
|
context.startService(serviceIntent);
|
||||||
return ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String host = CIMDataConfig.getString(context, CIMDataConfig.KEY_CIM_SERVIER_HOST);
|
protected static void init(Context context){
|
||||||
int port =CIMDataConfig.getInt(context, CIMDataConfig.KEY_CIM_SERVIER_PORT);
|
|
||||||
|
boolean isManualStop = CIMCacheTools.getBoolean(context,CIMCacheTools.KEY_MANUAL_STOP);
|
||||||
init(context,host,port);
|
boolean isManualDestory = CIMCacheTools.getBoolean(context,CIMCacheTools.KEY_CIM_DESTORYED);
|
||||||
|
|
||||||
}
|
if(isManualStop || isManualDestory)
|
||||||
|
{
|
||||||
|
return ;
|
||||||
/**
|
}
|
||||||
* 设置一个账号登录到服务端
|
|
||||||
* @param account 用户唯一ID
|
String host = CIMCacheTools.getString(context, CIMCacheTools.KEY_CIM_SERVIER_HOST);
|
||||||
*/
|
int port =CIMCacheTools.getInt(context, CIMCacheTools.KEY_CIM_SERVIER_PORT);
|
||||||
public static void setAccount(Context context,String account){
|
|
||||||
|
init(context,host,port);
|
||||||
|
|
||||||
boolean isManualDestory = CIMDataConfig.getBoolean(context,CIMDataConfig.KEY_CIM_DESTORYED);
|
}
|
||||||
if(isManualDestory || account==null || account.trim().length()==0)
|
|
||||||
{
|
|
||||||
return ;
|
/**
|
||||||
}
|
* 设置一个账号登录到服务端
|
||||||
|
* @param account 用户唯一ID
|
||||||
CIMDataConfig.putBoolean(context,CIMDataConfig.KEY_MANUAL_STOP, false);
|
*/
|
||||||
CIMDataConfig.putString(context,CIMDataConfig.KEY_ACCOUNT, account);
|
public static void bindAccount(Context context,String account){
|
||||||
|
|
||||||
String imei = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId();
|
|
||||||
imei += context.getPackageName();
|
boolean isManualDestory = CIMCacheTools.getBoolean(context,CIMCacheTools.KEY_CIM_DESTORYED);
|
||||||
SentBody sent = new SentBody();
|
if(isManualDestory || account==null || account.trim().length()==0)
|
||||||
sent.setKey(CIMConstant.RequestKey.CLIENT_BIND);
|
{
|
||||||
sent.put("account", account);
|
return ;
|
||||||
sent.put("deviceId",UUID.nameUUIDFromBytes(imei.getBytes()).toString().replaceAll("-", ""));
|
}
|
||||||
sent.put("channel", "android");
|
|
||||||
sent.put("device",android.os.Build.MODEL);
|
CIMCacheTools.putBoolean(context,CIMCacheTools.KEY_MANUAL_STOP, false);
|
||||||
|
CIMCacheTools.putString(context,CIMCacheTools.KEY_ACCOUNT, account);
|
||||||
sendRequest(context,sent);
|
|
||||||
|
String imei = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId();
|
||||||
|
imei += context.getPackageName();
|
||||||
}
|
SentBody sent = new SentBody();
|
||||||
|
sent.setKey(CIMConstant.RequestKey.CLIENT_BIND);
|
||||||
protected static void setAccount(Context context){
|
sent.put("account", account);
|
||||||
|
sent.put("deviceId",UUID.nameUUIDFromBytes(imei.getBytes()).toString().replaceAll("-", ""));
|
||||||
|
sent.put("channel", "android");
|
||||||
|
sent.put("device",android.os.Build.MODEL);
|
||||||
String account = CIMDataConfig.getString(context,CIMDataConfig.KEY_ACCOUNT);
|
sent.put("appVersion",getVersionName(context));
|
||||||
setAccount(context,account);
|
sent.put("osVersion",android.os.Build.VERSION.RELEASE);
|
||||||
}
|
sendRequest(context,sent);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
/**
|
|
||||||
* 发送一个CIM请求
|
|
||||||
* @param context
|
protected static void bindAccount(Context context){
|
||||||
* @body
|
|
||||||
*/
|
|
||||||
public static void sendRequest(Context context,SentBody body){
|
|
||||||
|
String account = CIMCacheTools.getString(context,CIMCacheTools.KEY_ACCOUNT);
|
||||||
boolean isManualStop = CIMDataConfig.getBoolean(context,CIMDataConfig.KEY_MANUAL_STOP);
|
bindAccount(context,account);
|
||||||
boolean isManualDestory = CIMDataConfig.getBoolean(context,CIMDataConfig.KEY_CIM_DESTORYED);
|
}
|
||||||
|
|
||||||
if(isManualStop || isManualDestory)
|
|
||||||
{
|
|
||||||
return ;
|
/**
|
||||||
}
|
* 发送一个CIM请求
|
||||||
|
* @param context
|
||||||
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
* @body
|
||||||
serviceIntent.putExtra(KEY_SEND_BODY, body);
|
*/
|
||||||
serviceIntent.putExtra(SERVICE_ACTION, ACTION_SENDREQUEST);
|
public static void sendRequest(Context context,SentBody body){
|
||||||
context.startService(serviceIntent);
|
|
||||||
|
boolean isManualStop = CIMCacheTools.getBoolean(context,CIMCacheTools.KEY_MANUAL_STOP);
|
||||||
}
|
boolean isManualDestory = CIMCacheTools.getBoolean(context,CIMCacheTools.KEY_CIM_DESTORYED);
|
||||||
|
|
||||||
/**
|
if(isManualStop || isManualDestory)
|
||||||
* 停止接受推送,将会退出当前账号登录,端口与服务端的连接
|
{
|
||||||
* @param context
|
return ;
|
||||||
*/
|
}
|
||||||
public static void stop(Context context){
|
|
||||||
|
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
||||||
boolean isManualDestory = CIMDataConfig.getBoolean(context,CIMDataConfig.KEY_CIM_DESTORYED);
|
serviceIntent.putExtra(KEY_SEND_BODY, body);
|
||||||
if(isManualDestory){
|
serviceIntent.putExtra(SERVICE_ACTION, ACTION_SENDREQUEST);
|
||||||
return ;
|
context.startService(serviceIntent);
|
||||||
}
|
|
||||||
|
}
|
||||||
CIMDataConfig.putBoolean(context,CIMDataConfig.KEY_MANUAL_STOP, true);
|
|
||||||
|
/**
|
||||||
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
* 停止接受推送,将会退出当前账号登录,端口与服务端的连接
|
||||||
serviceIntent.putExtra(SERVICE_ACTION, ACTION_DISCONNECTION);
|
* @param context
|
||||||
context.startService(serviceIntent);
|
*/
|
||||||
|
public static void stop(Context context){
|
||||||
}
|
|
||||||
|
boolean isManualDestory = CIMCacheTools.getBoolean(context,CIMCacheTools.KEY_CIM_DESTORYED);
|
||||||
|
if(isManualDestory){
|
||||||
/**
|
return ;
|
||||||
* 完全销毁CIM,一般用于完全退出程序,调用resume将不能恢复
|
}
|
||||||
* @param context
|
|
||||||
*/
|
CIMCacheTools.putBoolean(context,CIMCacheTools.KEY_MANUAL_STOP, true);
|
||||||
public static void destory(Context context){
|
|
||||||
|
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
||||||
|
serviceIntent.putExtra(SERVICE_ACTION, ACTION_DISCONNECTION);
|
||||||
CIMDataConfig.putBoolean(context,CIMDataConfig.KEY_CIM_DESTORYED, true);
|
context.startService(serviceIntent);
|
||||||
CIMDataConfig.putString(context,CIMDataConfig.KEY_ACCOUNT, null);
|
|
||||||
|
}
|
||||||
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
|
||||||
serviceIntent.putExtra(SERVICE_ACTION, ACTION_DESTORY);
|
|
||||||
context.startService(serviceIntent);
|
/**
|
||||||
|
* 完全销毁CIM,一般用于完全退出程序,调用resume将不能恢复
|
||||||
}
|
* @param context
|
||||||
|
*/
|
||||||
|
public static void destory(Context context){
|
||||||
/**
|
|
||||||
* 重新恢复接收推送,重新连接服务端,并登录当前账号
|
|
||||||
* @param context
|
CIMCacheTools.putBoolean(context,CIMCacheTools.KEY_CIM_DESTORYED, true);
|
||||||
*/
|
CIMCacheTools.putString(context,CIMCacheTools.KEY_ACCOUNT, null);
|
||||||
public static void resume(Context context){
|
|
||||||
|
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
||||||
boolean isManualDestory = CIMDataConfig.getBoolean(context,CIMDataConfig.KEY_CIM_DESTORYED);
|
serviceIntent.putExtra(SERVICE_ACTION, ACTION_DESTORY);
|
||||||
if(isManualDestory){
|
context.startService(serviceIntent);
|
||||||
return ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setAccount(context);
|
|
||||||
}
|
/**
|
||||||
|
* 重新恢复接收推送,重新连接服务端,并登录当前账号
|
||||||
public void detectIsConnected(Context context){
|
* @param context
|
||||||
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
*/
|
||||||
serviceIntent.putExtra(SERVICE_ACTION, ACTION_CONNECTION_STATUS);
|
public static void resume(Context context){
|
||||||
context.startService(serviceIntent);
|
|
||||||
}
|
boolean isManualDestory = CIMCacheTools.getBoolean(context,CIMCacheTools.KEY_CIM_DESTORYED);
|
||||||
|
if(isManualDestory){
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
bindAccount(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void detectIsConnected(Context context){
|
||||||
|
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
||||||
|
serviceIntent.putExtra(SERVICE_ACTION, ACTION_CONNECTION_STATUS);
|
||||||
|
context.startService(serviceIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static String getVersionName(Context context) {
|
||||||
|
String versionName = null;
|
||||||
|
try {
|
||||||
|
PackageInfo mPackageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
|
||||||
|
versionName = mPackageInfo.versionName;
|
||||||
|
} catch (NameNotFoundException e) {
|
||||||
|
}
|
||||||
|
return versionName;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,15 +1,11 @@
|
|||||||
|
|
||||||
package com.farsunset.cim.client.android;
|
package com.farsunset.cim.client.android;
|
||||||
|
|
||||||
import android.app.AlarmManager;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Binder;
|
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.farsunset.cim.nio.mutual.SentBody;
|
import com.farsunset.cim.client.model.SentBody;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,18 +15,12 @@ import com.farsunset.cim.nio.mutual.SentBody;
|
|||||||
*/
|
*/
|
||||||
public class CIMPushService extends Service {
|
public class CIMPushService extends Service {
|
||||||
|
|
||||||
|
protected final static int DEF_CIM_PORT = 28888;
|
||||||
CIMConnectorManager manager;
|
CIMConnectorManager manager;
|
||||||
AlarmManager localAlarmManager;
|
|
||||||
private IBinder binder=new CIMPushService.LocalBinder();
|
|
||||||
PendingIntent localPendingIntent;
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate()
|
public void onCreate()
|
||||||
{
|
{
|
||||||
manager = CIMConnectorManager.getManager(this.getApplicationContext());
|
manager = CIMConnectorManager.getManager(this.getApplicationContext());
|
||||||
localPendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, KeepAliveReceiver.class), PendingIntent.FLAG_CANCEL_CURRENT);
|
|
||||||
localAlarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
|
|
||||||
localAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 300000L + System.currentTimeMillis(),300000L, localPendingIntent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -41,18 +31,18 @@ import com.farsunset.cim.nio.mutual.SentBody;
|
|||||||
if(intent==null)
|
if(intent==null)
|
||||||
{
|
{
|
||||||
intent = new Intent(CIMPushManager.ACTION_CONNECTION);
|
intent = new Intent(CIMPushManager.ACTION_CONNECTION);
|
||||||
String host = CIMDataConfig.getString(this, CIMDataConfig.KEY_CIM_SERVIER_HOST);
|
String host = CIMCacheTools.getString(this, CIMCacheTools.KEY_CIM_SERVIER_HOST);
|
||||||
int port =CIMDataConfig.getInt(this, CIMDataConfig.KEY_CIM_SERVIER_PORT);
|
int port =CIMCacheTools.getInt(this, CIMCacheTools.KEY_CIM_SERVIER_PORT);
|
||||||
intent.putExtra(CIMDataConfig.KEY_CIM_SERVIER_HOST, host);
|
intent.putExtra(CIMCacheTools.KEY_CIM_SERVIER_HOST, host);
|
||||||
intent.putExtra(CIMDataConfig.KEY_CIM_SERVIER_PORT, port);
|
intent.putExtra(CIMCacheTools.KEY_CIM_SERVIER_PORT, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
action = intent.getStringExtra(CIMPushManager.SERVICE_ACTION);
|
action = intent.getStringExtra(CIMPushManager.SERVICE_ACTION);
|
||||||
|
|
||||||
if(CIMPushManager.ACTION_CONNECTION.equals(action))
|
if(CIMPushManager.ACTION_CONNECTION.equals(action))
|
||||||
{
|
{
|
||||||
String host = intent.getStringExtra(CIMDataConfig.KEY_CIM_SERVIER_HOST);
|
String host = intent.getStringExtra(CIMCacheTools.KEY_CIM_SERVIER_HOST);
|
||||||
int port = intent.getIntExtra(CIMDataConfig.KEY_CIM_SERVIER_PORT, 28888);
|
int port = intent.getIntExtra(CIMCacheTools.KEY_CIM_SERVIER_PORT, DEF_CIM_PORT);
|
||||||
manager.connect(host,port);
|
manager.connect(host,port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,8 +58,6 @@ import com.farsunset.cim.nio.mutual.SentBody;
|
|||||||
|
|
||||||
if(CIMPushManager.ACTION_DESTORY.equals(action))
|
if(CIMPushManager.ACTION_DESTORY.equals(action))
|
||||||
{
|
{
|
||||||
localAlarmManager.cancel(localPendingIntent);
|
|
||||||
localPendingIntent.cancel();
|
|
||||||
manager.destroy();
|
manager.destroy();
|
||||||
this.stopSelf();
|
this.stopSelf();
|
||||||
android.os.Process.killProcess(android.os.Process.myPid());
|
android.os.Process.killProcess(android.os.Process.myPid());
|
||||||
@ -80,14 +68,14 @@ import com.farsunset.cim.nio.mutual.SentBody;
|
|||||||
manager.deliverIsConnected();
|
manager.deliverIsConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(CIMPushManager.ACTION_CONNECTION_KEEPALIVE.equals(action))
|
if(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE.equals(action))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(!manager.isConnected())
|
if(!manager.isConnected())
|
||||||
{
|
{
|
||||||
Log.d(CIMPushService.class.getSimpleName(), "isConnected() = false ");
|
Log.d(CIMPushService.class.getSimpleName(), "cimpush isConnected() = false ");
|
||||||
String host = intent.getStringExtra(CIMDataConfig.KEY_CIM_SERVIER_HOST);
|
String host = intent.getStringExtra(CIMCacheTools.KEY_CIM_SERVIER_HOST);
|
||||||
int port = intent.getIntExtra(CIMDataConfig.KEY_CIM_SERVIER_PORT, 28888);
|
int port = intent.getIntExtra(CIMCacheTools.KEY_CIM_SERVIER_PORT, DEF_CIM_PORT);
|
||||||
manager.connect(host,port);
|
manager.connect(host,port);
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
@ -98,18 +86,12 @@ import com.farsunset.cim.nio.mutual.SentBody;
|
|||||||
|
|
||||||
return Service.START_REDELIVER_INTENT;
|
return Service.START_REDELIVER_INTENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent arg0) {
|
public IBinder onBind(Intent arg0) {
|
||||||
return binder;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LocalBinder extends Binder{
|
|
||||||
|
|
||||||
public CIMPushService getService()
|
|
||||||
{
|
|
||||||
return CIMPushService.this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
* probject:cim-android-sdk
|
||||||
|
* @version 2.0.0
|
||||||
|
*
|
||||||
|
* @author 3979434@qq.com
|
||||||
|
*/
|
||||||
|
package com.farsunset.cim.client.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 常量
|
||||||
|
*/
|
||||||
|
public interface CIMConstant {
|
||||||
|
|
||||||
|
|
||||||
|
public static String UTF8="UTF-8";
|
||||||
|
|
||||||
|
public static byte MESSAGE_SEPARATE='\b';
|
||||||
|
|
||||||
|
|
||||||
|
public static int CIM_DEFAULT_MESSAGE_ORDER=1;
|
||||||
|
|
||||||
|
public static class ReturnCode{
|
||||||
|
|
||||||
|
public static String CODE_404 ="404";
|
||||||
|
|
||||||
|
public static String CODE_403 ="403";
|
||||||
|
|
||||||
|
public static String CODE_405 ="405";
|
||||||
|
|
||||||
|
public static String CODE_200 ="200";
|
||||||
|
|
||||||
|
public static String CODE_206 ="206";
|
||||||
|
|
||||||
|
public static String CODE_500 ="500";
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务端心跳请求命令
|
||||||
|
*/
|
||||||
|
public static final String CMD_HEARTBEAT_REQUEST="cmd_server_hb_request";
|
||||||
|
/**
|
||||||
|
* 客户端心跳响应命令
|
||||||
|
*/
|
||||||
|
public static final String CMD_HEARTBEAT_RESPONSE ="cmd_client_hb_response";
|
||||||
|
|
||||||
|
|
||||||
|
public static class RequestKey{
|
||||||
|
|
||||||
|
|
||||||
|
public static String CLIENT_BIND ="client_bind";
|
||||||
|
|
||||||
|
public static String CLIENT_LOGOUT ="client_logout";
|
||||||
|
|
||||||
|
public static String CLIENT_OFFLINE_MESSAGE ="client_get_offline_message";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class MessageType{
|
||||||
|
|
||||||
|
//用户会 踢出下线消息类型
|
||||||
|
public static String TYPE_999 ="999";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,10 @@
|
|||||||
package com.farsunset.cim.client.android;
|
/**
|
||||||
|
* probject:cim-android-sdk
|
||||||
|
* @version 2.0.0
|
||||||
|
*
|
||||||
|
* @author 3979434@qq.com
|
||||||
|
*/
|
||||||
|
package com.farsunset.cim.client.exception;
|
||||||
|
|
||||||
|
|
||||||
public class CIMSessionDisableException extends Exception {
|
public class CIMSessionDisableException extends Exception {
|
@ -1,4 +1,10 @@
|
|||||||
package com.farsunset.cim.client.android;
|
/**
|
||||||
|
* probject:cim-android-sdk
|
||||||
|
* @version 2.0.0
|
||||||
|
*
|
||||||
|
* @author 3979434@qq.com
|
||||||
|
*/
|
||||||
|
package com.farsunset.cim.client.exception;
|
||||||
|
|
||||||
|
|
||||||
public class NetWorkDisableException extends Exception {
|
public class NetWorkDisableException extends Exception {
|
@ -1,4 +1,10 @@
|
|||||||
package com.farsunset.cim.client.android;
|
/**
|
||||||
|
* probject:cim-android-sdk
|
||||||
|
* @version 2.0.0
|
||||||
|
*
|
||||||
|
* @author 3979434@qq.com
|
||||||
|
*/
|
||||||
|
package com.farsunset.cim.client.exception;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
@ -1,45 +1,50 @@
|
|||||||
package com.farsunset.cim.nio.filter;
|
package com.farsunset.cim.client.filter;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.serialization.ClassResolver;
|
||||||
|
import io.netty.handler.codec.serialization.ObjectDecoder;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
|
||||||
import org.jboss.netty.buffer.ChannelBuffer;
|
|
||||||
import org.jboss.netty.channel.Channel;
|
|
||||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
|
||||||
import org.jboss.netty.handler.codec.frame.FrameDecoder;
|
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
import com.farsunset.cim.nio.constant.CIMConstant;
|
import android.util.Log;
|
||||||
import com.farsunset.cim.nio.mutual.Message;
|
|
||||||
import com.farsunset.cim.nio.mutual.ReplyBody;
|
import com.farsunset.cim.client.constant.CIMConstant;
|
||||||
|
import com.farsunset.cim.client.model.Message;
|
||||||
|
import com.farsunset.cim.client.model.ReplyBody;
|
||||||
/**
|
/**
|
||||||
* 客户端消息解码
|
* 客户端消息解码
|
||||||
* @author 3979434@qq.com
|
* @author 3979434@qq.com
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ClientMessageDecoder extends FrameDecoder {
|
public class ClientMessageDecoder extends ObjectDecoder {
|
||||||
|
|
||||||
|
|
||||||
|
public ClientMessageDecoder(ClassResolver classResolver) {
|
||||||
|
super(classResolver);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object decode(ChannelHandlerContext arg0, Channel channel,ChannelBuffer buffer) throws Exception {
|
public Object decode(ChannelHandlerContext arg0, ByteBuf buffer) throws Exception {
|
||||||
|
|
||||||
int length = buffer.readableBytes();
|
int length = buffer.readableBytes();
|
||||||
/**
|
/**
|
||||||
* CIMConstant.MESSAGE_SEPARATE 为消息界限
|
* CIMConstant.MESSAGE_SEPARATE 为消息界限
|
||||||
* 当一次收到多个消息时,以此分隔解析多个消息
|
* 当一次收到多个消息时,以此分隔解析多个消息
|
||||||
*/
|
*/
|
||||||
if (buffer.readable()&& length > 0 && CIMConstant.MESSAGE_SEPARATE == buffer.getByte(length-1)) {
|
if (buffer.isReadable()&& length > 0 && CIMConstant.MESSAGE_SEPARATE == buffer.getByte(length-1)) {
|
||||||
|
|
||||||
byte[] data = new byte[length-1];
|
byte[] data = new byte[length-1];
|
||||||
buffer.readBytes(data);
|
buffer.readBytes(data);
|
||||||
String message = new String(new String(data,CIMConstant.ENCODE_UTF8));
|
String message = new String(new String(data,CIMConstant.UTF8));
|
||||||
|
Log.i(ClientMessageDecoder.class.getSimpleName(), message.toString());
|
||||||
System.out.println("ClientMessageDecoder:" + message);
|
|
||||||
|
|
||||||
//将末尾的消息分隔符读取掉
|
//将末尾的消息分隔符读取掉
|
||||||
buffer.readByte();
|
buffer.readByte();
|
||||||
|
|
||||||
@ -55,10 +60,13 @@ public class ClientMessageDecoder extends FrameDecoder {
|
|||||||
|
|
||||||
private Object mappingMessageObject(String message) throws Exception {
|
private Object mappingMessageObject(String message) throws Exception {
|
||||||
|
|
||||||
|
if(message.equals(CIMConstant.CMD_HEARTBEAT_REQUEST))//如果是心跳请求命令则直接返回
|
||||||
|
{
|
||||||
|
return CIMConstant.CMD_HEARTBEAT_REQUEST;
|
||||||
|
}
|
||||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||||
Document doc = (Document) builder.parse(new ByteArrayInputStream(message.getBytes(CIMConstant.ENCODE_UTF8)));
|
Document doc = (Document) builder.parse(new ByteArrayInputStream(message.getBytes(CIMConstant.UTF8)));
|
||||||
|
|
||||||
String name = doc.getDocumentElement().getTagName();
|
String name = doc.getDocumentElement().getTagName();
|
||||||
if (name.equals("reply")) {
|
if (name.equals("reply")) {
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.farsunset.cim.client.filter;
|
||||||
|
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.MessageToByteEncoder;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.farsunset.cim.client.constant.CIMConstant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端消息发送前进行编码,可在此加密消息
|
||||||
|
* @author 3979434@qq.com
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ClientMessageEncoder extends MessageToByteEncoder<Object> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void encode(ChannelHandlerContext ctx, Object message, ByteBuf out) throws Exception {
|
||||||
|
out.writeBytes(message.toString().getBytes(CIMConstant.UTF8));
|
||||||
|
out.writeByte(CIMConstant.MESSAGE_SEPARATE);
|
||||||
|
Log.i(ClientMessageEncoder.class.getSimpleName(), message.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,174 @@
|
|||||||
|
/**
|
||||||
|
* probject:cim-android-sdk
|
||||||
|
* @version 2.0.0
|
||||||
|
*
|
||||||
|
* @author 3979434@qq.com
|
||||||
|
*/
|
||||||
|
package com.farsunset.cim.client.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
/**
|
||||||
|
* 消息对象
|
||||||
|
*/
|
||||||
|
public class Message implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型,用户自定义消息类别
|
||||||
|
*/
|
||||||
|
private String mid;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型,用户自定义消息类别
|
||||||
|
*/
|
||||||
|
private String type;
|
||||||
|
/**
|
||||||
|
* 消息标题
|
||||||
|
*/
|
||||||
|
private String title;
|
||||||
|
/**
|
||||||
|
* 消息类容,于type 组合为任何类型消息,content 根据 format 可表示为 text,json ,xml数据格式
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息发送者账号
|
||||||
|
*/
|
||||||
|
private String sender;
|
||||||
|
/**
|
||||||
|
* 消息发送者接收者
|
||||||
|
*/
|
||||||
|
private String receiver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件 url
|
||||||
|
*/
|
||||||
|
private String file;
|
||||||
|
/**
|
||||||
|
* 文件类型
|
||||||
|
*/
|
||||||
|
private String fileType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* content 内容格式
|
||||||
|
*/
|
||||||
|
private String format = "txt";
|
||||||
|
|
||||||
|
|
||||||
|
private long timestamp;
|
||||||
|
|
||||||
|
|
||||||
|
public Message()
|
||||||
|
{
|
||||||
|
timestamp = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
public long getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimestamp(long timestamp) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSender() {
|
||||||
|
return sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSender(String sender) {
|
||||||
|
this.sender = sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReceiver() {
|
||||||
|
return receiver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReceiver(String receiver) {
|
||||||
|
this.receiver = receiver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFile() {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFile(String file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileType() {
|
||||||
|
return fileType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileType(String fileType) {
|
||||||
|
this.fileType = fileType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFormat() {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFormat(String format) {
|
||||||
|
this.format = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||||
|
buffer.append("<message>");
|
||||||
|
buffer.append("<mid>").append(mid).append("</mid>");
|
||||||
|
buffer.append("<type>").append(type).append("</type>");
|
||||||
|
buffer.append("<title>").append(this.getTitle()==null?"":this.getTitle()).append("</title>");
|
||||||
|
buffer.append("<content><![CDATA[").append(this.getContent()==null?"":this.getContent()).append("]]></content>");
|
||||||
|
buffer.append("<file>").append(this.getFile()==null?"":this.getFile()).append("</file>");
|
||||||
|
buffer.append("<fileType>").append(this.getFileType()==null?"":this.getFileType()).append("</fileType>");
|
||||||
|
buffer.append("<sender>").append(this.getSender()==null?"":this.getSender()).append("</sender>");
|
||||||
|
buffer.append("<receiver>").append(this.getReceiver()==null?"":this.getReceiver()).append("</receiver>");
|
||||||
|
buffer.append("<format>").append(this.getFormat()==null?"":this.getFormat()).append("</format>");
|
||||||
|
buffer.append("<timestamp>").append(timestamp).append("</timestamp>");
|
||||||
|
buffer.append("</message>");
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
public String toXmlString()
|
||||||
|
{
|
||||||
|
|
||||||
|
return toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMid() {
|
||||||
|
return mid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMid(String mid) {
|
||||||
|
this.mid = mid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,18 +1,19 @@
|
|||||||
package com.farsunset.cim.nio.mutual;
|
/**
|
||||||
|
* probject:cim-android-sdk
|
||||||
|
* @version 2.0.0
|
||||||
|
*
|
||||||
|
* @author 3979434@qq.com
|
||||||
|
*/
|
||||||
|
package com.farsunset.cim.client.model;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
/**
|
/**
|
||||||
* 请求应答对象
|
* 请求应答对象
|
||||||
* @author 3979434@qq.com
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ReplyBody implements Serializable {
|
public class ReplyBody implements Serializable {
|
||||||
|
|
||||||
/**
|
|
||||||
* @author 3979434@qq.com
|
|
||||||
* 服务端返回消息对象
|
|
||||||
*/
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
/**
|
@ -0,0 +1,84 @@
|
|||||||
|
/**
|
||||||
|
* probject:cim-android-sdk
|
||||||
|
* @version 2.0.0
|
||||||
|
*
|
||||||
|
* @author 3979434@qq.com
|
||||||
|
*/
|
||||||
|
package com.farsunset.cim.client.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
/**
|
||||||
|
* java |android 客户端请求结构
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SentBody implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
private HashMap<String, String> data;
|
||||||
|
|
||||||
|
private long timestamp;
|
||||||
|
|
||||||
|
public SentBody() {
|
||||||
|
|
||||||
|
data = new HashMap<String, String>();
|
||||||
|
timestamp = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get(String k) {
|
||||||
|
return data.get(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimestamp(long timestamp) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(String k, String v) {
|
||||||
|
data.put(k, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(String k) {
|
||||||
|
data.remove(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMap<String, String> getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||||
|
buffer.append("<sent>");
|
||||||
|
buffer.append("<key>").append(key).append("</key>");
|
||||||
|
buffer.append("<timestamp>").append(timestamp).append("</timestamp>");
|
||||||
|
buffer.append("<data>");
|
||||||
|
for (String key : data.keySet()) {
|
||||||
|
buffer.append("<" + key + ">").append(data.get(key)).append(
|
||||||
|
"</" + key + ">");
|
||||||
|
}
|
||||||
|
buffer.append("</data>");
|
||||||
|
buffer.append("</sent>");
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toXmlString() {
|
||||||
|
|
||||||
|
return toString();
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<classpath>
|
|
||||||
<classpathentry kind="src" path="src"/>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
|
||||||
<classpathentry kind="lib" path="/ichat-server/WebRoot/WEB-INF/lib/commons-lang3-3.1.jar"/>
|
|
||||||
<classpathentry kind="lib" path="/ichat-server/WebRoot/WEB-INF/lib/log4j.jar"/>
|
|
||||||
<classpathentry kind="lib" path="/ichat-server/WebRoot/WEB-INF/lib/netty-3.6.5.Final.jar"/>
|
|
||||||
<classpathentry kind="lib" path="D:/android-eclipse/adt-bundle-windows-x86_64-20131030/sdk/platforms/android-19/android.jar"/>
|
|
||||||
<classpathentry kind="output" path="bin"/>
|
|
||||||
</classpath>
|
|
Binary file not shown.
@ -1,40 +0,0 @@
|
|||||||
package com.farsunset.cim.client.android;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CIM 消息监听器管理
|
|
||||||
*
|
|
||||||
* @author 3979434@qq.com
|
|
||||||
*/
|
|
||||||
public class CIMListenerManager {
|
|
||||||
|
|
||||||
private static ArrayList<OnCIMMessageListener> cimListeners = new ArrayList<OnCIMMessageListener>();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static void registerMessageListener(OnCIMMessageListener listener,Context mcontext) {
|
|
||||||
|
|
||||||
if (!cimListeners.contains(listener)) {
|
|
||||||
cimListeners.add(listener);
|
|
||||||
// 按照接收顺序倒序
|
|
||||||
Collections.sort(cimListeners, new CIMMessageReceiveComparator(mcontext));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void removeMessageListener(OnCIMMessageListener listener) {
|
|
||||||
for (int i = 0; i < cimListeners.size(); i++) {
|
|
||||||
if (listener.getClass() == cimListeners.get(i).getClass()) {
|
|
||||||
cimListeners.remove(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ArrayList<OnCIMMessageListener> getCIMListeners() {
|
|
||||||
return cimListeners;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
package com.farsunset.cim.client.android;
|
|
||||||
|
|
||||||
import java.util.Comparator;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.pm.ActivityInfo;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
|
|
||||||
import com.farsunset.cim.nio.constant.CIMConstant;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 消息接收activity的接收顺序排序,CIM_RECEIVE_ORDER倒序
|
|
||||||
* @author 3979434
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class CIMMessageReceiveComparator implements Comparator<OnCIMMessageListener>{
|
|
||||||
|
|
||||||
Context mcontext;
|
|
||||||
public CIMMessageReceiveComparator(Context ctx)
|
|
||||||
{
|
|
||||||
mcontext = ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(OnCIMMessageListener arg1, OnCIMMessageListener arg2) {
|
|
||||||
|
|
||||||
Integer order1 = CIMConstant.CIM_DEFAULT_MESSAGE_ORDER;
|
|
||||||
Integer order2 = CIMConstant.CIM_DEFAULT_MESSAGE_ORDER;
|
|
||||||
ActivityInfo info;
|
|
||||||
if (arg1 instanceof Activity ) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
info = mcontext.getPackageManager() .getActivityInfo(((Activity)(arg1)).getComponentName(), PackageManager.GET_META_DATA);
|
|
||||||
if(info.metaData!=null)
|
|
||||||
{
|
|
||||||
order1 = info.metaData.getInt("CIM_RECEIVE_ORDER");
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg1 instanceof Activity ) {
|
|
||||||
try {
|
|
||||||
info = mcontext.getPackageManager() .getActivityInfo(((Activity)(arg2)).getComponentName(), PackageManager.GET_META_DATA);
|
|
||||||
if(info.metaData!=null)
|
|
||||||
{
|
|
||||||
order2 = info.metaData.getInt("CIM_RECEIVE_ORDER");
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
return order2.compareTo(order1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
package com.farsunset.cim.client.android;
|
|
||||||
|
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.util.Log;
|
|
||||||
/**
|
|
||||||
* @author 3979434
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class KeepAliveReceiver extends BroadcastReceiver {
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent it) {
|
|
||||||
Log.d(KeepAliveReceiver.class.getSimpleName(), "onReceive()");
|
|
||||||
|
|
||||||
Intent intent = new Intent(context, CIMPushService.class);
|
|
||||||
intent.putExtra(CIMPushManager.SERVICE_ACTION, CIMPushManager.ACTION_CONNECTION_KEEPALIVE);
|
|
||||||
context.startService(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package com.farsunset.cim.nio.filter;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import org.jboss.netty.buffer.ChannelBuffer;
|
|
||||||
import org.jboss.netty.buffer.ChannelBuffers;
|
|
||||||
import org.jboss.netty.channel.Channel;
|
|
||||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
|
||||||
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
|
|
||||||
|
|
||||||
import com.farsunset.cim.nio.constant.CIMConstant;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 客户端消息发送前进行编码,可在此加密消息
|
|
||||||
* @author 3979434@qq.com
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ClientMessageEncoder extends OneToOneEncoder {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object encode(ChannelHandlerContext arg0, Channel arg1,Object message) throws Exception {
|
|
||||||
ChannelBuffer buf = ChannelBuffers.dynamicBuffer();//(2)
|
|
||||||
buf.writeBytes(message.toString().getBytes());
|
|
||||||
buf.writeByte(CIMConstant.MESSAGE_SEPARATE);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
package com.farsunset.cim.nio.filter;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
|
|
||||||
import org.jboss.netty.buffer.ChannelBuffer;
|
|
||||||
import org.jboss.netty.channel.Channel;
|
|
||||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
|
||||||
import org.jboss.netty.handler.codec.frame.FrameDecoder;
|
|
||||||
import org.w3c.dom.Document;
|
|
||||||
import org.w3c.dom.Node;
|
|
||||||
import org.w3c.dom.NodeList;
|
|
||||||
|
|
||||||
import com.farsunset.cim.nio.constant.CIMConstant;
|
|
||||||
import com.farsunset.cim.nio.mutual.SentBody;
|
|
||||||
/**
|
|
||||||
* 服务端接收消息解码,可在此解密消息
|
|
||||||
* @author 3979434@qq.com
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ServerMessageDecoder extends FrameDecoder {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object decode(ChannelHandlerContext arg0, Channel channel,ChannelBuffer buffer) throws Exception {
|
|
||||||
|
|
||||||
|
|
||||||
int length = buffer.readableBytes();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CIMConstant.MESSAGE_SEPARATE 为消息界限
|
|
||||||
* 当一次收到多个消息时,以此分隔解析多个消息
|
|
||||||
*/
|
|
||||||
if (buffer.readable()&&length > 0 && CIMConstant.MESSAGE_SEPARATE == buffer.getByte(length-1)) {
|
|
||||||
|
|
||||||
byte[] data = new byte[length-1];
|
|
||||||
buffer.readBytes(data);
|
|
||||||
String message = new String(new String(data,CIMConstant.ENCODE_UTF8));
|
|
||||||
System.out.println("[ServerMessageDecoder]:"+message);
|
|
||||||
buffer.readByte();
|
|
||||||
|
|
||||||
SentBody body = new SentBody();
|
|
||||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
|
||||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
|
||||||
Document doc = builder.parse(new ByteArrayInputStream(message.toString().getBytes()));
|
|
||||||
body.setKey(doc.getElementsByTagName("key").item(0).getTextContent());
|
|
||||||
NodeList dataNodeList = doc.getElementsByTagName("data");
|
|
||||||
if(dataNodeList!=null && dataNodeList.getLength()>0)
|
|
||||||
{
|
|
||||||
NodeList items = dataNodeList.item(0).getChildNodes();
|
|
||||||
for (int i = 0; i < items.getLength(); i++) {
|
|
||||||
Node node = items.item(i);
|
|
||||||
body.getData().put(node.getNodeName(), node.getTextContent());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data = null;
|
|
||||||
message = null;
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CIMConstant.FLEX_DATA_SEPARATE 为FLEX客户端socket验证消息界限
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
if (buffer.readable()&& length > 0 && CIMConstant.FLEX_DATA_SEPARATE == buffer.getByte(length-1)) {
|
|
||||||
|
|
||||||
byte[] data = new byte[length-1];
|
|
||||||
buffer.readBytes(data);
|
|
||||||
String message = new String(new String(data,CIMConstant.ENCODE_UTF8));
|
|
||||||
|
|
||||||
System.out.println("[ServerMessageDecoder]:"+message);
|
|
||||||
|
|
||||||
//将末尾的消息分隔符读取掉
|
|
||||||
buffer.readByte();
|
|
||||||
data = null;
|
|
||||||
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
package com.farsunset.cim.nio.filter;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import org.jboss.netty.buffer.ChannelBuffer;
|
|
||||||
import org.jboss.netty.buffer.ChannelBuffers;
|
|
||||||
import org.jboss.netty.channel.Channel;
|
|
||||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
|
||||||
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
|
|
||||||
|
|
||||||
import com.farsunset.cim.nio.constant.CIMConstant;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 服务端发送消息前编码,可在此加密消息
|
|
||||||
* @author 3979434@qq.com
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ServerMessageEncoder extends OneToOneEncoder {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object encode(ChannelHandlerContext arg0, Channel arg1, Object message) throws Exception {
|
|
||||||
ChannelBuffer buf = ChannelBuffers.dynamicBuffer();//(2)
|
|
||||||
buf.writeBytes(message.toString().getBytes(CIMConstant.ENCODE_UTF8));
|
|
||||||
buf.writeByte(CIMConstant.MESSAGE_SEPARATE);
|
|
||||||
System.out.println("[ServerMessageEncoder]:"+message);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
|
|
||||||
package com.farsunset.cim.nio.handler;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
import com.farsunset.cim.nio.constant.CIMConstant;
|
|
||||||
import com.farsunset.cim.nio.mutual.ReplyBody;
|
|
||||||
import com.farsunset.cim.nio.mutual.SentBody;
|
|
||||||
import com.farsunset.cim.nio.session.CIMSession;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*客户端心跳实现
|
|
||||||
*
|
|
||||||
* @author
|
|
||||||
*/
|
|
||||||
public class HeartbeatHandler implements CIMRequestHandler {
|
|
||||||
|
|
||||||
protected final Logger logger = Logger.getLogger(HeartbeatHandler.class);
|
|
||||||
|
|
||||||
public ReplyBody process(CIMSession session, SentBody message) {
|
|
||||||
|
|
||||||
logger.warn("heartbeat... from "+session.getRemoteAddress().toString());
|
|
||||||
ReplyBody reply = new ReplyBody();
|
|
||||||
reply.setKey(CIMConstant.RequestKey.CLIENT_HEARTBEAT);
|
|
||||||
reply.setCode(CIMConstant.ReturnCode.CODE_200);
|
|
||||||
session.setHeartbeat(System.currentTimeMillis());
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,158 +0,0 @@
|
|||||||
|
|
||||||
package com.farsunset.cim.nio.handler;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
|
||||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
|
||||||
import org.jboss.netty.channel.ChannelPipeline;
|
|
||||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
|
||||||
import org.jboss.netty.channel.ChannelStateEvent;
|
|
||||||
import org.jboss.netty.channel.Channels;
|
|
||||||
import org.jboss.netty.channel.MessageEvent;
|
|
||||||
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
|
||||||
|
|
||||||
import com.farsunset.cim.nio.constant.CIMConstant;
|
|
||||||
import com.farsunset.cim.nio.filter.ServerMessageDecoder;
|
|
||||||
import com.farsunset.cim.nio.filter.ServerMessageEncoder;
|
|
||||||
import com.farsunset.cim.nio.mutual.ReplyBody;
|
|
||||||
import com.farsunset.cim.nio.mutual.SentBody;
|
|
||||||
import com.farsunset.cim.nio.session.CIMSession;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* 客户端请求的入口,所有请求都首先经过它分发处理
|
|
||||||
* @author farsunset (3979434@qq.com)
|
|
||||||
*/
|
|
||||||
public class MainIOHandler extends SimpleChannelUpstreamHandler {
|
|
||||||
|
|
||||||
protected final Logger logger = Logger.getLogger(MainIOHandler.class);
|
|
||||||
|
|
||||||
private HashMap<String, CIMRequestHandler> handlers = new HashMap<String, CIMRequestHandler>();
|
|
||||||
|
|
||||||
|
|
||||||
private int port;
|
|
||||||
|
|
||||||
public void init()
|
|
||||||
{
|
|
||||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
|
||||||
new NioServerSocketChannelFactory(
|
|
||||||
Executors.newCachedThreadPool(),
|
|
||||||
Executors.newCachedThreadPool()));
|
|
||||||
|
|
||||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory()
|
|
||||||
{
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ChannelPipeline getPipeline() throws Exception
|
|
||||||
{
|
|
||||||
return Channels.pipeline(
|
|
||||||
new ServerMessageDecoder(),
|
|
||||||
new ServerMessageEncoder(),
|
|
||||||
MainIOHandler.this);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
bootstrap.bind(new InetSocketAddress(port));
|
|
||||||
logger.warn("netty 启动成功" + port);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent event)
|
|
||||||
{
|
|
||||||
logger.warn("sessionCreated()... from "+ctx.getChannel().getRemoteAddress().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
|
|
||||||
throws Exception {
|
|
||||||
logger.debug("message: " + e.getMessage().toString());
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* flex 客户端安全策略请求,需要返回特定报文
|
|
||||||
*/
|
|
||||||
if(CIMConstant.FLEX_POLICY_REQUEST.equals(e.getMessage()))
|
|
||||||
{
|
|
||||||
ctx.getChannel().write(CIMConstant.FLEX_POLICY_RESPONSE);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
CIMSession cimSession =new CIMSession(ctx.getChannel());
|
|
||||||
ReplyBody reply = new ReplyBody();
|
|
||||||
SentBody body = (SentBody) e.getMessage();
|
|
||||||
String key = body.getKey();
|
|
||||||
|
|
||||||
CIMRequestHandler handler = handlers.get(key);
|
|
||||||
if (handler == null) {
|
|
||||||
reply.setCode(CIMConstant.ReturnCode.CODE_405);
|
|
||||||
reply.setCode("KEY ["+key+"] 服务端未定义");
|
|
||||||
} else {
|
|
||||||
reply = handler.process(cimSession, body);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(reply!=null)
|
|
||||||
{
|
|
||||||
reply.setKey(key);
|
|
||||||
cimSession.write(reply);
|
|
||||||
logger.debug("-----------------------process done. reply: " + reply.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
//设置心跳时间
|
|
||||||
cimSession.setAttribute(CIMConstant.HEARTBEAT_KEY, System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent event) {
|
|
||||||
CIMSession cimSession =new CIMSession(ctx.getChannel());
|
|
||||||
try{
|
|
||||||
logger.warn("sessionClosed()... from "+cimSession.getRemoteAddress());
|
|
||||||
CIMRequestHandler handler = handlers.get("sessionClosedHander");
|
|
||||||
if(handler!=null && cimSession.containsAttribute(CIMConstant.SESSION_KEY))
|
|
||||||
{
|
|
||||||
handler.process(cimSession, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*//*
|
|
||||||
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent event) {
|
|
||||||
CIMSession cimSession =new CIMSession(ctx.getChannel());
|
|
||||||
try{
|
|
||||||
logger.warn("sessionClosed()... from "+cimSession.getRemoteAddress());
|
|
||||||
CIMRequestHandler handler = handlers.get("sessionClosedHander");
|
|
||||||
if(handler!=null && cimSession.containsAttribute(CIMConstant.SESSION_KEY))
|
|
||||||
{
|
|
||||||
handler.process(cimSession, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public void setHandlers(HashMap<String, CIMRequestHandler> handlers) {
|
|
||||||
this.handlers = handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPort(int port) {
|
|
||||||
this.port = port;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
9
cim_for_netty/cim-server-sdk/.classpath
Normal file
9
cim_for_netty/cim-server-sdk/.classpath
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="lib" path="/cim-server/WebRoot/WEB-INF/lib/commons-lang3-3.1.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/cim-server/WebRoot/WEB-INF/lib/log4j.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/cim-server/WebRoot/WEB-INF/lib/netty-all-5.0.0.Alpha2.jar" sourcepath="C:/Users/Administrator/Desktop/netty-all-5.0.0.Alpha2-sources.jar"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk1.7.0_80"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<projectDescription>
|
<projectDescription>
|
||||||
<name>cim-core</name>
|
<name>cim-server-sdk</name>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
<projects>
|
<projects>
|
||||||
</projects>
|
</projects>
|
@ -0,0 +1,167 @@
|
|||||||
|
package com.farsunset.cim.launcher;
|
||||||
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
import io.netty.channel.ChannelPipeline;
|
||||||
|
import io.netty.channel.EventLoopGroup;
|
||||||
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
|
import io.netty.channel.socket.SocketChannel;
|
||||||
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
|
import io.netty.handler.codec.serialization.ClassResolvers;
|
||||||
|
import io.netty.handler.timeout.IdleState;
|
||||||
|
import io.netty.handler.timeout.IdleStateEvent;
|
||||||
|
import io.netty.handler.timeout.IdleStateHandler;
|
||||||
|
import io.netty.util.AttributeKey;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.farsunset.cim.server.constant.CIMConstant;
|
||||||
|
import com.farsunset.cim.server.filter.ServerMessageDecoder;
|
||||||
|
import com.farsunset.cim.server.filter.ServerMessageEncoder;
|
||||||
|
import com.farsunset.cim.server.handler.CIMRequestHandler;
|
||||||
|
import com.farsunset.cim.server.mutual.ReplyBody;
|
||||||
|
import com.farsunset.cim.server.mutual.SentBody;
|
||||||
|
import com.farsunset.cim.server.session.CIMSession;
|
||||||
|
|
||||||
|
@io.netty.channel.ChannelHandler.Sharable
|
||||||
|
public class CIMNioSocketAcceptor extends SimpleChannelInboundHandler<Object>{
|
||||||
|
|
||||||
|
protected final Logger logger = Logger.getLogger(CIMNioSocketAcceptor.class.getSimpleName());
|
||||||
|
public final static String KEY_CLIENT_CIMSESSION_CLOSED = "client_cimsession_closed";
|
||||||
|
private HashMap<String, CIMRequestHandler> handlers = new HashMap<String, CIMRequestHandler>();
|
||||||
|
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void bind()
|
||||||
|
{
|
||||||
|
new Thread(new Runnable(){
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
EventLoopGroup bossGroup = new NioEventLoopGroup();
|
||||||
|
EventLoopGroup workerGroup = new NioEventLoopGroup();
|
||||||
|
try{
|
||||||
|
ServerBootstrap bootstrap = new ServerBootstrap();
|
||||||
|
bootstrap.group(bossGroup, workerGroup);
|
||||||
|
bootstrap.channel(NioServerSocketChannel.class);
|
||||||
|
bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
|
||||||
|
@Override
|
||||||
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
|
ChannelPipeline pipeline = ch.pipeline();
|
||||||
|
|
||||||
|
pipeline.addLast(new ServerMessageDecoder(ClassResolvers.cacheDisabled(null)));
|
||||||
|
pipeline.addLast(new ServerMessageEncoder());
|
||||||
|
pipeline.addLast(new IdleStateHandler(CIMConstant.IDLE_TIME/2,0,CIMConstant.IDLE_TIME));
|
||||||
|
pipeline.addLast(CIMNioSocketAcceptor.this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
bootstrap.bind(port).sync().channel().closeFuture().sync();
|
||||||
|
}catch(Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
workerGroup.shutdownGracefully();
|
||||||
|
bossGroup.shutdownGracefully();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelRegistered( ChannelHandlerContext ctx) throws Exception {
|
||||||
|
|
||||||
|
logger.debug("channelRegistered()... from "+ctx.channel().remoteAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测到连接空闲事件,发送心跳请求命令
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
||||||
|
if (evt instanceof IdleStateEvent && ((IdleStateEvent) evt).state().equals(IdleState.ALL_IDLE)) {
|
||||||
|
ctx.channel().attr(AttributeKey.valueOf(CIMConstant.HEARTBEAT_PINGED)).set(System.currentTimeMillis());
|
||||||
|
ctx.channel().writeAndFlush(CIMConstant.CMD_HEARTBEAT_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
//如果心跳请求发出30秒内没收到响应,则关闭连接
|
||||||
|
if (evt instanceof IdleStateEvent
|
||||||
|
&& ((IdleStateEvent) evt).state().equals(IdleState.READER_IDLE)
|
||||||
|
&& ctx.channel().attr(AttributeKey.valueOf(CIMConstant.HEARTBEAT_PINGED)).get()!=null)
|
||||||
|
{
|
||||||
|
long t = (Long) ctx.channel().attr(AttributeKey.valueOf(CIMConstant.HEARTBEAT_PINGED)).get();
|
||||||
|
if(System.currentTimeMillis() - t >= CIMConstant.PING_TIME_OUT)
|
||||||
|
{
|
||||||
|
ctx.channel().close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.userEventTriggered(ctx, evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* flex 客户端安全策略请求,需要返回特定报文
|
||||||
|
*/
|
||||||
|
if(CIMConstant.FLEX_POLICY_REQUEST.equals(msg))
|
||||||
|
{
|
||||||
|
ctx.writeAndFlush(CIMConstant.FLEX_POLICY_RESPONSE);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
CIMSession cimSession =new CIMSession(ctx.channel());
|
||||||
|
ReplyBody reply = new ReplyBody();
|
||||||
|
SentBody body = (SentBody)msg;
|
||||||
|
String key = body.getKey();
|
||||||
|
|
||||||
|
CIMRequestHandler handler = handlers.get(key);
|
||||||
|
if (handler == null) {
|
||||||
|
reply.setCode(CIMConstant.ReturnCode.CODE_405);
|
||||||
|
reply.setCode("KEY ["+key+"] 服务端未定义");
|
||||||
|
} else {
|
||||||
|
reply = handler.process(cimSession, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(reply!=null)
|
||||||
|
{
|
||||||
|
reply.setKey(key);
|
||||||
|
cimSession.write(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||||
|
|
||||||
|
CIMSession cimSession =new CIMSession(ctx.channel());
|
||||||
|
try{
|
||||||
|
logger.debug("channelInactive()... from "+cimSession.getRemoteAddress());
|
||||||
|
CIMRequestHandler handler = handlers.get(KEY_CLIENT_CIMSESSION_CLOSED);
|
||||||
|
if(handler!=null && cimSession.hasTag(CIMConstant.SESSION_KEY))
|
||||||
|
{
|
||||||
|
handler.process(cimSession, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setHandlers(HashMap<String, CIMRequestHandler> handlers) {
|
||||||
|
this.handlers = handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPort(int port) {
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
package com.farsunset.cim.nio.constant;
|
package com.farsunset.cim.server.constant;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
@ -27,6 +27,11 @@ public interface CIMConstant {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//连接空闲时间
|
||||||
|
public static final int IDLE_TIME = 60;//秒
|
||||||
|
|
||||||
|
public static final int PING_TIME_OUT = 30;//心跳响应 超时为30秒
|
||||||
|
|
||||||
|
|
||||||
public static final Charset ENCODE_UTF8 = Charset.forName("UTF-8");
|
public static final Charset ENCODE_UTF8 = Charset.forName("UTF-8");
|
||||||
|
|
||||||
@ -41,7 +46,16 @@ public interface CIMConstant {
|
|||||||
|
|
||||||
public static final String HEARTBEAT_KEY ="heartbeat";
|
public static final String HEARTBEAT_KEY ="heartbeat";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务端心跳请求命令
|
||||||
|
*/
|
||||||
|
public static final String CMD_HEARTBEAT_REQUEST="cmd_server_hb_request";
|
||||||
|
/**
|
||||||
|
* 客户端心跳响应命令
|
||||||
|
*/
|
||||||
|
public static final String CMD_HEARTBEAT_RESPONSE ="cmd_client_hb_response";
|
||||||
|
|
||||||
|
public static final String HEARTBEAT_PINGED ="HEARTBEAT_PINGED";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FLEX 客户端socket请求发的安全策略请求,需要特殊处理,返回安全验证报文
|
* FLEX 客户端socket请求发的安全策略请求,需要特殊处理,返回安全验证报文
|
||||||
@ -54,8 +68,8 @@ public interface CIMConstant {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对应ichat 中 spring-cim.xml > bean:mainIoHandler >handlers
|
* 对应cim-server 中 spring-cim.xml > bean:mainIoHandler >handlers
|
||||||
* 为 服务端处理对应的handlers,应该继承与com.farsunset.cim.nio.handle.AbstractHandler
|
* 为 服务端处理对应的handlers,应该继承与com.farsunset.cim.nio.handle.CIMRequestHandler
|
||||||
* @author xiajun
|
* @author xiajun
|
||||||
*
|
*
|
||||||
*/
|
*/
|
@ -0,0 +1,99 @@
|
|||||||
|
package com.farsunset.cim.server.filter;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.serialization.ClassResolver;
|
||||||
|
import io.netty.handler.codec.serialization.ObjectDecoder;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
import com.farsunset.cim.server.constant.CIMConstant;
|
||||||
|
import com.farsunset.cim.server.mutual.SentBody;
|
||||||
|
/**
|
||||||
|
* 服务端接收消息解码,可在此解密消息
|
||||||
|
* @author 3979434@qq.com
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ServerMessageDecoder extends ObjectDecoder {
|
||||||
|
protected final Logger logger = Logger.getLogger(ServerMessageDecoder.class.getSimpleName());
|
||||||
|
public ServerMessageDecoder(ClassResolver classResolver) {
|
||||||
|
super(classResolver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object decode(ChannelHandlerContext arg0, ByteBuf buffer) throws Exception {
|
||||||
|
|
||||||
|
|
||||||
|
int length = buffer.readableBytes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CIMConstant.MESSAGE_SEPARATE 为消息界限
|
||||||
|
* 当一次收到多个消息时,以此分隔解析多个消息
|
||||||
|
*/
|
||||||
|
if (buffer.isReadable()&&length > 0 && CIMConstant.MESSAGE_SEPARATE == buffer.getByte(length-1)) {
|
||||||
|
|
||||||
|
byte[] data = new byte[length-1];
|
||||||
|
buffer.readBytes(data);
|
||||||
|
String message = new String(new String(data,CIMConstant.ENCODE_UTF8));
|
||||||
|
logger.debug(message);
|
||||||
|
buffer.readByte();
|
||||||
|
|
||||||
|
SentBody body = parserMessageToSentBody(message);
|
||||||
|
data = null;
|
||||||
|
message = null;
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CIMConstant.FLEX_DATA_SEPARATE 为FLEX客户端socket验证消息界限
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
if (buffer.isReadable()&& length > 0 && CIMConstant.FLEX_DATA_SEPARATE == buffer.getByte(length-1)) {
|
||||||
|
|
||||||
|
byte[] data = new byte[length-1];
|
||||||
|
buffer.readBytes(data);
|
||||||
|
String message = new String(new String(data,CIMConstant.ENCODE_UTF8));
|
||||||
|
System.out.println("[ServerMessageDecoder]:"+message);
|
||||||
|
|
||||||
|
//将末尾的消息分隔符读取掉
|
||||||
|
buffer.readByte();
|
||||||
|
data = null;
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SentBody parserMessageToSentBody(String message) throws Exception
|
||||||
|
{
|
||||||
|
SentBody body = new SentBody();
|
||||||
|
if(message.equals(CIMConstant.CMD_HEARTBEAT_RESPONSE))//如果是心跳响应,则让HeartbeatHandler去处理
|
||||||
|
{
|
||||||
|
body.setKey(CIMConstant.RequestKey.CLIENT_HEARTBEAT);
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||||
|
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||||
|
Document doc = builder.parse(new ByteArrayInputStream(message.toString().getBytes(CIMConstant.ENCODE_UTF8)));
|
||||||
|
body.setKey(doc.getElementsByTagName("key").item(0).getTextContent());
|
||||||
|
NodeList dataNodeList = doc.getElementsByTagName("data");
|
||||||
|
if(dataNodeList!=null && dataNodeList.getLength()>0)
|
||||||
|
{
|
||||||
|
NodeList items = dataNodeList.item(0).getChildNodes();
|
||||||
|
for (int i = 0; i < items.getLength(); i++) {
|
||||||
|
Node node = items.item(i);
|
||||||
|
body.getData().put(node.getNodeName(), node.getTextContent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package com.farsunset.cim.server.filter;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.MessageToByteEncoder;
|
||||||
|
|
||||||
|
|
||||||
|
import com.farsunset.cim.server.constant.CIMConstant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务端发送消息前编码,可在此加密消息
|
||||||
|
* @author 3979434@qq.com
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ServerMessageEncoder extends MessageToByteEncoder<Object> {
|
||||||
|
protected final Logger logger = Logger.getLogger(ServerMessageEncoder.class.getSimpleName());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void encode(ChannelHandlerContext ctx, Object message, ByteBuf out) throws Exception {
|
||||||
|
out.writeBytes(message.toString().getBytes(CIMConstant.ENCODE_UTF8));
|
||||||
|
out.writeByte(CIMConstant.MESSAGE_SEPARATE);
|
||||||
|
logger.debug(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,13 +1,13 @@
|
|||||||
|
|
||||||
package com.farsunset.cim.nio.handler;
|
package com.farsunset.cim.server.handler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求处理接口,所有的请求实现必须实现此接口
|
* 请求处理接口,所有的请求实现必须实现此接口
|
||||||
* @author 3979434@qq.com
|
* @author 3979434@qq.com
|
||||||
*/
|
*/
|
||||||
import com.farsunset.cim.nio.mutual.ReplyBody;
|
import com.farsunset.cim.server.mutual.ReplyBody;
|
||||||
import com.farsunset.cim.nio.mutual.SentBody;
|
import com.farsunset.cim.server.mutual.SentBody;
|
||||||
import com.farsunset.cim.nio.session.CIMSession;
|
import com.farsunset.cim.server.session.CIMSession;
|
||||||
|
|
||||||
public interface CIMRequestHandler {
|
public interface CIMRequestHandler {
|
||||||
|
|
@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
package com.farsunset.cim.server.handler;
|
||||||
|
|
||||||
|
import com.farsunset.cim.server.constant.CIMConstant;
|
||||||
|
import com.farsunset.cim.server.mutual.ReplyBody;
|
||||||
|
import com.farsunset.cim.server.mutual.SentBody;
|
||||||
|
import com.farsunset.cim.server.session.CIMSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*客户端心跳实现
|
||||||
|
*
|
||||||
|
* @author
|
||||||
|
*/
|
||||||
|
public class HeartbeatHandler implements CIMRequestHandler {
|
||||||
|
|
||||||
|
|
||||||
|
public ReplyBody process(CIMSession session, SentBody message) {
|
||||||
|
|
||||||
|
//收到心跳响应,清除发送心跳请求标记
|
||||||
|
session.removeTag(CIMConstant.HEARTBEAT_PINGED);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.farsunset.cim.nio.mutual;
|
package com.farsunset.cim.server.mutual;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
/**
|
/**
|
||||||
@ -152,7 +152,7 @@ public class Message implements Serializable {
|
|||||||
buffer.append("<sender>").append(this.getSender()==null?"":this.getSender()).append("</sender>");
|
buffer.append("<sender>").append(this.getSender()==null?"":this.getSender()).append("</sender>");
|
||||||
buffer.append("<receiver>").append(this.getReceiver()==null?"":this.getReceiver()).append("</receiver>");
|
buffer.append("<receiver>").append(this.getReceiver()==null?"":this.getReceiver()).append("</receiver>");
|
||||||
buffer.append("<format>").append(this.getFormat()==null?"":this.getFormat()).append("</format>");
|
buffer.append("<format>").append(this.getFormat()==null?"":this.getFormat()).append("</format>");
|
||||||
buffer.append("<timestamp>").append(timestamp).append("</timestamp>");
|
buffer.append("<timestamp>").append(String.valueOf(timestamp)).append("</timestamp>");
|
||||||
buffer.append("</message>");
|
buffer.append("</message>");
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
@ -0,0 +1,122 @@
|
|||||||
|
package com.farsunset.cim.server.mutual;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
/**
|
||||||
|
* 请求应答对象
|
||||||
|
* @author 3979434@qq.com
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ReplyBody implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 3979434@qq.com
|
||||||
|
* 服务端返回消息对象
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求key
|
||||||
|
*/
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回码
|
||||||
|
*/
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回说明
|
||||||
|
*/
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回数据集合
|
||||||
|
*/
|
||||||
|
private HashMap<String, String> data;
|
||||||
|
|
||||||
|
|
||||||
|
private long timestamp;
|
||||||
|
|
||||||
|
public ReplyBody()
|
||||||
|
{
|
||||||
|
data = new HashMap<String, String>();
|
||||||
|
timestamp = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
public long getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimestamp(long timestamp) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(String k, String v) {
|
||||||
|
data.put(k, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get(String k) {
|
||||||
|
return data.get(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(String k) {
|
||||||
|
data.remove(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMap<String, String> getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCode(String code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||||
|
buffer.append("<reply>");
|
||||||
|
buffer.append("<key>").append(this.getKey()).append("</key>");
|
||||||
|
buffer.append("<timestamp>").append(String.valueOf(timestamp)).append("</timestamp>");
|
||||||
|
buffer.append("<code>").append(code).append("</code>");
|
||||||
|
buffer.append("<data>");
|
||||||
|
for(String key:this.getData().keySet())
|
||||||
|
{
|
||||||
|
buffer.append("<"+key+">").append(this.get(key)).append("</"+key+">");
|
||||||
|
}
|
||||||
|
buffer.append("</data>");
|
||||||
|
buffer.append("</reply>");
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String toXmlString()
|
||||||
|
{
|
||||||
|
|
||||||
|
return toString();
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.farsunset.cim.nio.mutual;
|
package com.farsunset.cim.server.mutual;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -64,7 +64,7 @@ public class SentBody implements Serializable {
|
|||||||
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||||
buffer.append("<sent>");
|
buffer.append("<sent>");
|
||||||
buffer.append("<key>").append(key).append("</key>");
|
buffer.append("<key>").append(key).append("</key>");
|
||||||
buffer.append("<timestamp>").append(timestamp).append("</timestamp>");
|
buffer.append("<timestamp>").append(String.valueOf(timestamp)).append("</timestamp>");
|
||||||
buffer.append("<data>");
|
buffer.append("<data>");
|
||||||
for (String key : data.keySet()) {
|
for (String key : data.keySet()) {
|
||||||
buffer.append("<" + key + ">").append(data.get(key)).append(
|
buffer.append("<" + key + ">").append(data.get(key)).append(
|
@ -1,15 +1,14 @@
|
|||||||
package com.farsunset.cim.nio.session;
|
package com.farsunset.cim.server.session;
|
||||||
|
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.util.AttributeKey;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.jboss.netty.channel.Channel;
|
import com.farsunset.cim.server.constant.CIMConstant;
|
||||||
|
|
||||||
import com.farsunset.cim.nio.constant.CIMConstant;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IoSession包装类,集群时 将此对象存入表中
|
* IoSession包装类,集群时 将此对象存入表中
|
||||||
@ -29,26 +28,20 @@ public class CIMSession implements Serializable{
|
|||||||
private Channel session;
|
private Channel session;
|
||||||
|
|
||||||
private String gid;//session全局ID
|
private String gid;//session全局ID
|
||||||
private int nid;//session在本台服务器上的ID
|
private String nid;//session在本台服务器上的ID
|
||||||
private String deviceId;//客户端设备ID
|
private String deviceId;//客户端设备ID
|
||||||
private String host;//session绑定的服务器IP
|
private String host;//session绑定的服务器IP
|
||||||
private String account;//session绑定的账号
|
private String account;//session绑定的账号
|
||||||
private String channel;//终端设备类型
|
private String channel;//终端设备类型
|
||||||
private String deviceModel;//终端设备型号
|
private String deviceModel;//终端设备型号
|
||||||
|
private String appVersion;//客户端应用版本
|
||||||
private Long bindTime;//登录时间
|
private Long bindTime;//登录时间
|
||||||
|
|
||||||
private Long heartbeat;//心跳时间
|
private Long heartbeat;//心跳时间
|
||||||
|
|
||||||
public CIMSession(Channel session) {
|
public CIMSession(Channel session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.nid = session.getId();
|
this.nid = session.id().asLongText();
|
||||||
if(session.getAttachment()==null)
|
|
||||||
{
|
|
||||||
HashMap<String,Object> params= new HashMap<String,Object>();
|
|
||||||
session.setAttachment(params);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -61,14 +54,24 @@ public class CIMSession implements Serializable{
|
|||||||
public void setAccount(String account) {
|
public void setAccount(String account) {
|
||||||
if(session!=null)
|
if(session!=null)
|
||||||
{
|
{
|
||||||
((Map<String,Object>)session.getAttachment()).put(CIMConstant.SESSION_KEY, account);
|
setTag(CIMConstant.SESSION_KEY, account);
|
||||||
}
|
}
|
||||||
this.account = account;
|
this.account = account;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setTag(String key,Object value)
|
||||||
|
{
|
||||||
|
if(value!=null)
|
||||||
|
session.attr(AttributeKey.valueOf(key)).set(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getTag(String key)
|
||||||
|
{
|
||||||
|
Object tag = session.attr(AttributeKey.valueOf(key)).get();
|
||||||
|
return tag!=null?tag.toString():null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getGid() {
|
public String getGid() {
|
||||||
@ -79,11 +82,11 @@ public class CIMSession implements Serializable{
|
|||||||
this.gid = gid;
|
this.gid = gid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNid() {
|
public String getNid() {
|
||||||
return nid;
|
return nid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNid(int nid) {
|
public void setNid(String nid) {
|
||||||
this.nid = nid;
|
this.nid = nid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,9 +138,9 @@ public class CIMSession implements Serializable{
|
|||||||
|
|
||||||
public void setHeartbeat(Long heartbeat) {
|
public void setHeartbeat(Long heartbeat) {
|
||||||
this.heartbeat = heartbeat;
|
this.heartbeat = heartbeat;
|
||||||
if(session!=null && session.getAttachment()!=null)
|
if(session!=null )
|
||||||
{
|
{
|
||||||
((Map<String,Object>)session.getAttachment()).put(CIMConstant.HEARTBEAT_KEY, heartbeat);
|
setTag(CIMConstant.HEARTBEAT_KEY, heartbeat.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,45 +149,52 @@ public class CIMSession implements Serializable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void setAttribute(String key, Object value) {
|
|
||||||
if(session!=null)
|
public String getAppVersion() {
|
||||||
((Map<String,Object>)session.getAttachment()).put(key, value);
|
return appVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean containsAttribute(String key) {
|
|
||||||
|
|
||||||
|
public void setAppVersion(String appVersion) {
|
||||||
|
this.appVersion = appVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public boolean hasTag(String key) {
|
||||||
if(session!=null)
|
if(session!=null)
|
||||||
return ((Map<String,Object>)session.getAttachment()).containsKey(key);
|
return session.hasAttr(AttributeKey.valueOf(key));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getAttribute(String key) {
|
|
||||||
return ((Map<String,Object>)session.getAttachment()).get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeAttribute(String key) {
|
public void removeTag(String key) {
|
||||||
((Map<String,Object>)session.getAttachment()).remove(key);
|
session.attr(AttributeKey.valueOf(key)).remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SocketAddress getRemoteAddress() {
|
public SocketAddress getRemoteAddress() {
|
||||||
if(session!=null)
|
if(session!=null)
|
||||||
return session.getRemoteAddress();
|
return session.remoteAddress();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean write(Object msg) {
|
public boolean write(Object msg) {
|
||||||
if(session!=null && session.isConnected())
|
if(session!=null && session.isActive())
|
||||||
{
|
{
|
||||||
|
|
||||||
return session.write(msg).awaitUninterruptibly(5000);
|
return session.writeAndFlush(msg).awaitUninterruptibly(5000);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isConnected() {
|
public boolean isConnected() {
|
||||||
if(session!=null)
|
if(session!=null)
|
||||||
return session.isConnected();
|
return session.isActive();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +230,7 @@ public class CIMSession implements Serializable{
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (t.session.getId() == session.getId()&& t.host.equals(host)) {
|
if (t.session.id().asLongText().equals(session.id().asLongText())&& t.host.equals(host)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
@ -1,11 +1,11 @@
|
|||||||
|
|
||||||
package com.farsunset.cim.nio.session;
|
package com.farsunset.cim.server.session;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import com.farsunset.cim.nio.constant.CIMConstant;
|
import com.farsunset.cim.server.constant.CIMConstant;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自带默认 session管理实现, 各位可以自行实现 AbstractSessionManager接口来实现自己的 session管理
|
* 自带默认 session管理实现, 各位可以自行实现 AbstractSessionManager接口来实现自己的 session管理
|
||||||
@ -28,7 +28,7 @@ public class DefaultSessionManager implements SessionManager{
|
|||||||
public void addSession(String account,CIMSession session) {
|
public void addSession(String account,CIMSession session) {
|
||||||
if(session!=null)
|
if(session!=null)
|
||||||
{
|
{
|
||||||
session.setAttribute(CIMConstant.SESSION_KEY, account);
|
session.setTag(CIMConstant.SESSION_KEY, account);
|
||||||
sessions.put(account, session);
|
sessions.put(account, session);
|
||||||
connectionsCounter.incrementAndGet();
|
connectionsCounter.incrementAndGet();
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ public class DefaultSessionManager implements SessionManager{
|
|||||||
public void removeSession(CIMSession session) {
|
public void removeSession(CIMSession session) {
|
||||||
|
|
||||||
|
|
||||||
sessions.remove(session.getAttribute(CIMConstant.SESSION_KEY));
|
sessions.remove(session.getTag(CIMConstant.SESSION_KEY));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -65,13 +65,13 @@ public class DefaultSessionManager implements SessionManager{
|
|||||||
|
|
||||||
public boolean containsCIMSession(CIMSession ios)
|
public boolean containsCIMSession(CIMSession ios)
|
||||||
{
|
{
|
||||||
return sessions.containsKey(ios.getAttribute(CIMConstant.SESSION_KEY)) || sessions.containsValue(ios);
|
return sessions.containsKey(ios.getTag(CIMConstant.SESSION_KEY)) || sessions.containsValue(ios);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getAccount(CIMSession ios)
|
public String getAccount(CIMSession ios)
|
||||||
{
|
{
|
||||||
if(ios.getAttribute(CIMConstant.SESSION_KEY)==null)
|
if(ios.getTag(CIMConstant.SESSION_KEY)==null)
|
||||||
{
|
{
|
||||||
for(String key:sessions.keySet())
|
for(String key:sessions.keySet())
|
||||||
{
|
{
|
||||||
@ -82,7 +82,7 @@ public class DefaultSessionManager implements SessionManager{
|
|||||||
}
|
}
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
return ios.getAttribute(CIMConstant.SESSION_KEY).toString();
|
return ios.getTag(CIMConstant.SESSION_KEY).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
package com.farsunset.cim.nio.session;
|
package com.farsunset.cim.server.session;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
@ -6,6 +6,7 @@
|
|||||||
<classpathentry kind="con" path="melibrary.com.genuitec.eclipse.j2eedt.core.MYECLIPSE_JAVAEE_5_CONTAINER"/>
|
<classpathentry kind="con" path="melibrary.com.genuitec.eclipse.j2eedt.core.MYECLIPSE_JAVAEE_5_CONTAINER"/>
|
||||||
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/>
|
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/>
|
||||||
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
|
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
|
||||||
|
<classpathentry combineaccessrules="false" kind="src" path="/cim-server-sdk"/>
|
||||||
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/Spring.aop-3.0.2.jar"/>
|
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/Spring.aop-3.0.2.jar"/>
|
||||||
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/Spring.asm-3.0.2.RELEASE.jar"/>
|
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/Spring.asm-3.0.2.RELEASE.jar"/>
|
||||||
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/Spring.beans-3.0.2.RELEASE.jar"/>
|
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/Spring.beans-3.0.2.RELEASE.jar"/>
|
||||||
@ -19,7 +20,6 @@
|
|||||||
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/antlr-2.7.6.jar"/>
|
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/antlr-2.7.6.jar"/>
|
||||||
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/asm.jar"/>
|
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/asm.jar"/>
|
||||||
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/aspectjweaver.jar"/>
|
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/aspectjweaver.jar"/>
|
||||||
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/cim-core-1.6.jar"/>
|
|
||||||
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/commons-fileupload-1.2.1.jar"/>
|
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/commons-fileupload-1.2.1.jar"/>
|
||||||
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/commons-io-2.4.jar"/>
|
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/commons-io-2.4.jar"/>
|
||||||
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/commons-lang3-3.1.jar"/>
|
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/commons-lang3-3.1.jar"/>
|
||||||
@ -30,7 +30,7 @@
|
|||||||
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/httpcore-4.3.2.jar"/>
|
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/httpcore-4.3.2.jar"/>
|
||||||
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/jstl-1.2.jar"/>
|
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/jstl-1.2.jar"/>
|
||||||
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/log4j.jar"/>
|
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/log4j.jar"/>
|
||||||
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/netty-3.6.5.Final.jar"/>
|
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/netty-all-5.0.0.Alpha2.jar"/>
|
||||||
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/ognl-2.7.3.jar"/>
|
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/ognl-2.7.3.jar"/>
|
||||||
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/slf4j-api-1.7.5.jar"/>
|
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/slf4j-api-1.7.5.jar"/>
|
||||||
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/slf4j-nop-1.7.5.jar"/>
|
<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/slf4j-nop-1.7.5.jar"/>
|
@ -1,11 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project-module
|
<project-module
|
||||||
type="WEB"
|
type="WEB"
|
||||||
name="ichat-server"
|
name="cim-server"
|
||||||
id="myeclipse.1329027071311"
|
id="myeclipse.1329027071311"
|
||||||
context-root="/ichat-server"
|
context-root="/cim-server"
|
||||||
j2ee-spec="5.0"
|
j2ee-spec="5.0"
|
||||||
archive="ichat-server.war">
|
archive="cim-server.war">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="webrootdir" value="WebRoot" />
|
<attribute name="webrootdir" value="WebRoot" />
|
||||||
</attributes>
|
</attributes>
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<projectDescription>
|
<projectDescription>
|
||||||
<name>ichat-server</name>
|
<name>cim-server</name>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
<projects>
|
<projects>
|
||||||
</projects>
|
</projects>
|
@ -1,4 +1,4 @@
|
|||||||
log4j.rootLogger=warn,console, file
|
log4j.rootLogger=debug,console, file
|
||||||
|
|
||||||
#----------console----------------
|
#----------console----------------
|
||||||
log4j.appender.console=org.apache.log4j.ConsoleAppender
|
log4j.appender.console=org.apache.log4j.ConsoleAppender
|
@ -14,24 +14,24 @@
|
|||||||
>
|
>
|
||||||
|
|
||||||
|
|
||||||
<bean id="mainIoHandler" class="com.farsunset.cim.nio.handler.MainIOHandler" init-method="init" >
|
<bean id="mainIoHandler" class="com.farsunset.cim.launcher.CIMNioSocketAcceptor" init-method="bind" >
|
||||||
<property name="port" value="23456" />
|
<property name="port" value="23456" />
|
||||||
<property name="handlers">
|
<property name="handlers">
|
||||||
<map>
|
<map>
|
||||||
<entry key="client_bind">
|
<entry key="client_bind">
|
||||||
<bean class="com.farsunset.ichat.cim.handler.BindHandler" />
|
<bean class="com.farsunset.cim.handler.BindHandler" />
|
||||||
</entry>
|
</entry>
|
||||||
<entry key="client_logout">
|
<entry key="client_logout">
|
||||||
<bean class="com.farsunset.ichat.cim.handler.LogoutHandler" />
|
<bean class="com.farsunset.cim.handler.LogoutHandler" />
|
||||||
</entry>
|
</entry>
|
||||||
<entry key="client_heartbeat">
|
<entry key="client_heartbeat">
|
||||||
<bean class="com.farsunset.cim.nio.handler.HeartbeatHandler"/>
|
<bean class="com.farsunset.cim.server.handler.HeartbeatHandler"/>
|
||||||
</entry>
|
</entry>
|
||||||
<entry key="sessionClosedHander">
|
<entry key="client_cimsession_closed">
|
||||||
<bean class="com.farsunset.ichat.cim.handler.SessionClosedHandler"/>
|
<bean class="com.farsunset.cim.handler.SessionClosedHandler"/>
|
||||||
</entry>
|
</entry>
|
||||||
<entry key="client_get_offline_message">
|
<entry key="client_get_offline_message">
|
||||||
<bean class="com.farsunset.ichat.cim.handler.PushOfflineMessageHandler"/>
|
<bean class="com.farsunset.cim.handler.PushOfflineMessageHandler"/>
|
||||||
</entry>
|
</entry>
|
||||||
</map>
|
</map>
|
||||||
</property>
|
</property>
|
||||||
@ -39,5 +39,5 @@
|
|||||||
|
|
||||||
|
|
||||||
<!-- 这里可以自行实现com.farsunset.cim.nio.session.SessionManager接口,实现自己的session管理器 -->
|
<!-- 这里可以自行实现com.farsunset.cim.nio.session.SessionManager接口,实现自己的session管理器 -->
|
||||||
<bean id="defaultSessionManager" class="com.farsunset.cim.nio.session.DefaultSessionManager"/>
|
<bean id="defaultSessionManager" class="com.farsunset.cim.server.session.DefaultSessionManager"/>
|
||||||
</beans>
|
</beans>
|
@ -12,5 +12,5 @@
|
|||||||
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
|
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<bean id="contextHolder" class="com.farsunset.ichat.common.util.ContextHolder"/>
|
<bean id="contextHolder" class="com.farsunset.cim.util.ContextHolder"/>
|
||||||
</beans>
|
</beans>
|
@ -13,11 +13,11 @@
|
|||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
|
||||||
<bean id="messagePusher" class="com.farsunset.ichat.cim.push.DefaultMessagePusher">
|
<bean id="messagePusher" class="com.farsunset.cim.push.DefaultMessagePusher">
|
||||||
<property name="sessionManager" ref="defaultSessionManager"/>
|
<property name="sessionManager" ref="defaultSessionManager"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="systemMessagePusher" class="com.farsunset.ichat.cim.push.SystemMessagePusher">
|
<bean id="systemMessagePusher" class="com.farsunset.cim.push.SystemMessagePusher">
|
||||||
<property name="sessionManager" ref="defaultSessionManager"/>
|
<property name="sessionManager" ref="defaultSessionManager"/>
|
||||||
</bean>
|
</bean>
|
||||||
</beans>
|
</beans>
|
@ -10,12 +10,12 @@
|
|||||||
<constant name="struts.multipart.saveDir" value="/tmp"/>
|
<constant name="struts.multipart.saveDir" value="/tmp"/>
|
||||||
<constant name="struts.multipart.parser" value="jakarta"/>
|
<constant name="struts.multipart.parser" value="jakarta"/>
|
||||||
<package name="admin" extends="struts-default" namespace="/admin">
|
<package name="admin" extends="struts-default" namespace="/admin">
|
||||||
<action name="session_*" class="com.farsunset.ichat.admin.action.SessionAction" method="{1}">
|
<action name="session_*" class="com.farsunset.cim.admin.action.SessionAction" method="{1}">
|
||||||
<result name="list" type="dispatcher">/console/session/manage.jsp</result>
|
<result name="list" type="dispatcher">/console/session/manage.jsp</result>
|
||||||
</action>
|
</action>
|
||||||
</package>
|
</package>
|
||||||
|
|
||||||
<package name="cgi" extends="struts-default" namespace="/cgi">
|
<package name="cgi" extends="struts-default" namespace="/cgi">
|
||||||
<action name="message_*" class="com.farsunset.ichat.api.action.MessageAction" method="{1}"></action>
|
<action name="message_*" class="com.farsunset.cim.api.action.MessageAction" method="{1}"></action>
|
||||||
</package>
|
</package>
|
||||||
</struts>
|
</struts>
|
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
<%@ page language="java" pageEncoding="utf-8"%>
|
<%@ page language="java" pageEncoding="utf-8"%>
|
||||||
<%@ page import="java.util.Collection"%>
|
<%@ page import="java.util.Collection"%>
|
||||||
<%@ page import="com.farsunset.cim.nio.session.CIMSession"%>
|
<%@ page import="com.farsunset.cim.server.session.CIMSession"%>
|
||||||
<%
|
<%
|
||||||
String path = request.getContextPath();
|
String path = request.getContextPath();
|
||||||
String basePath = request.getScheme() + "://"
|
String basePath = request.getScheme() + "://"
|
||||||
@ -56,7 +56,7 @@
|
|||||||
|
|
||||||
function onImageError(obj)
|
function onImageError(obj)
|
||||||
{
|
{
|
||||||
obj.src="<%=basePath%>/webclient/images/icon_head_default.png";
|
obj.src="<%=basePath%>/resource/img/icon.png";
|
||||||
}
|
}
|
||||||
|
|
||||||
function openWebclient(){
|
function openWebclient(){
|
||||||
@ -92,6 +92,7 @@
|
|||||||
<th width="4%">头像</th>
|
<th width="4%">头像</th>
|
||||||
<th width="15%">账号</th>
|
<th width="15%">账号</th>
|
||||||
<th width="10%">终端</th>
|
<th width="10%">终端</th>
|
||||||
|
<th width="10%">应用版本</th>
|
||||||
<th width="10%">设备型号</th>
|
<th width="10%">设备型号</th>
|
||||||
<th width="10%">在线时长</th>
|
<th width="10%">在线时长</th>
|
||||||
<th width="28%">位置</th>
|
<th width="28%">位置</th>
|
||||||
@ -117,6 +118,9 @@
|
|||||||
<td>
|
<td>
|
||||||
<%=ios.getChannel()%>
|
<%=ios.getChannel()%>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
<%=ios.getAppVersion()==null?"":ios.getAppVersion()%>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<%=ios.getDeviceModel()==null?"":ios.getDeviceModel()%>
|
<%=ios.getDeviceModel()==null?"":ios.getDeviceModel()%>
|
||||||
</td>
|
</td>
|
||||||
@ -124,7 +128,7 @@
|
|||||||
<%=(System.currentTimeMillis()-ios.getBindTime())/1000 %>秒
|
<%=(System.currentTimeMillis()-ios.getBindTime())/1000 %>秒
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<%=ios.getAttribute("location")==null?"":ios.getAttribute("location") %>
|
<%=ios.getTag("location")==null?"":ios.getTag("location") %>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="btn-group btn-group-xs">
|
<div class="btn-group btn-group-xs">
|
@ -7,7 +7,9 @@
|
|||||||
|
|
||||||
<span id="current_account" style="color: white;float: right;font-weight: bold;"></span>
|
<span id="current_account" style="color: white;float: right;font-weight: bold;"></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div style="text-align: center;padding: 10px;">
|
||||||
|
请调用接口,或者在后台页面,推送一条消息到客户端
|
||||||
|
</div>
|
||||||
<div class="panel-body" id="messageList">
|
<div class="panel-body" id="messageList">
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user