对websdk和javasdk增加了处理下线的逻辑

This commit is contained in:
远方夕阳 2018-02-05 17:58:41 +08:00
parent 13805095b5
commit 627e2bcd9a
163 changed files with 26222 additions and 27614 deletions

View File

@ -26,86 +26,76 @@ import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
class CIMCacheManager {
class CIMCacheManager {
public static final String CIM_CONFIG_INFO = "CIM_CONFIG_INFO";
public static final String CIM_CONFIG_INFO = "CIM_CONFIG_INFO";
public static final String KEY_ACCOUNT = "KEY_ACCOUNT"; public static final String KEY_ACCOUNT = "KEY_ACCOUNT";
public static final String KEY_DEVICE_ID = "KEY_DEVICE_ID"; public static final String KEY_DEVICE_ID = "KEY_DEVICE_ID";
public static final String KEY_MANUAL_STOP = "KEY_MANUAL_STOP"; public static final String KEY_MANUAL_STOP = "KEY_MANUAL_STOP";
public static final String KEY_CIM_DESTROYED = "KEY_CIM_DESTROYED"; public static final String KEY_CIM_DESTROYED = "KEY_CIM_DESTROYED";
public static final String KEY_CIM_SERVIER_HOST = "KEY_CIM_SERVIER_HOST"; public static final String KEY_CIM_SERVIER_HOST = "KEY_CIM_SERVIER_HOST";
public static final String KEY_CIM_SERVIER_PORT = "KEY_CIM_SERVIER_PORT"; public static final String KEY_CIM_SERVIER_PORT = "KEY_CIM_SERVIER_PORT";
public static final String KEY_CIM_CONNECTION_STATE = "KEY_CIM_CONNECTION_STATE"; public static final String KEY_CIM_CONNECTION_STATE = "KEY_CIM_CONNECTION_STATE";
public static void remove(Context context, String key) {
public static void remove(Context context ,String key) ContentResolver resolver = context.getContentResolver();
{
ContentResolver resolver = context.getContentResolver();
resolver.delete(Uri.parse(CIMCacheProvider.CONTENT_URI), key, null); resolver.delete(Uri.parse(CIMCacheProvider.CONTENT_URI), key, null);
} }
public static void putString(Context context, String key, String value) {
public static void putString(Context context ,String key,String value) ContentResolver resolver = context.getContentResolver();
{ ContentValues values = new ContentValues();
values.put("value", value);
ContentResolver resolver = context.getContentResolver(); values.put("key", key);
ContentValues values = new ContentValues(); resolver.insert(Uri.parse(CIMCacheProvider.CONTENT_URI), values);
values.put("value", value);
values.put("key", key);
resolver.insert(Uri.parse(CIMCacheProvider.CONTENT_URI), values);
} }
public static String getString(Context context ,String key) public static String getString(Context context, String key) {
{
String value = null; String value = null;
ContentResolver resolver = context.getContentResolver(); ContentResolver resolver = context.getContentResolver();
Cursor cursor = resolver.query(Uri.parse(CIMCacheProvider.CONTENT_URI), new String[]{key}, null,null,null); Cursor cursor = resolver.query(Uri.parse(CIMCacheProvider.CONTENT_URI), new String[] { key }, null, null, null);
if (cursor!=null && cursor.moveToFirst()) if (cursor != null && cursor.moveToFirst()) {
{
value = cursor.getString(0); value = cursor.getString(0);
cursor.close(); cursor.close();
} }
closeQuietly(cursor); closeQuietly(cursor);
return value; return value;
} }
private static void closeQuietly(Cursor cursor){ private static void closeQuietly(Cursor cursor) {
try{ try {
if(cursor!=null) if (cursor != null)
cursor.close(); cursor.close();
}catch(Exception e){} } catch (Exception e) {
}
} }
public static void putBoolean(Context context,String key,boolean value) public static void putBoolean(Context context, String key, boolean value) {
{ putString(context, key, Boolean.toString(value));
putString(context,key,Boolean.toString(value));
} }
public static boolean getBoolean(Context context,String key) public static boolean getBoolean(Context context, String key) {
{ String value = getString(context, key);
String value = getString(context,key); return value == null ? false : Boolean.parseBoolean(value);
return value == null?false:Boolean.parseBoolean(value);
} }
public static void putInt(Context context, String key, int value) {
public static void putInt(Context context,String key,int value) putString(context, key, String.valueOf(value));
{
putString(context,key, String.valueOf(value));
} }
public static int getInt(Context context,String key) public static int getInt(Context context, String key) {
{ String value = getString(context, key);
String value = getString(context,key); return value == null ? 0 : Integer.parseInt(value);
return value == null?0:Integer.parseInt(value);
} }
} }

View File

@ -29,13 +29,12 @@ import android.database.MatrixCursor;
import android.net.Uri; import android.net.Uri;
public class CIMCacheProvider extends ContentProvider { public class CIMCacheProvider extends ContentProvider {
public static final String CONTENT_URI="content://com.farsunset.cim.provider"; public static final String CONTENT_URI = "content://com.farsunset.cim.provider";
static final String MODEL_KEY = "PRIVATE_CIM_CONFIG"; static final String MODEL_KEY = "PRIVATE_CIM_CONFIG";
@Override @Override
public int delete(Uri arg0, String key, String[] arg2) { public int delete(Uri arg0, String key, String[] arg2) {
getContext().getSharedPreferences(MODEL_KEY, Context.MODE_PRIVATE).edit().remove(key).apply(); getContext().getSharedPreferences(MODEL_KEY, Context.MODE_PRIVATE).edit().remove(key).apply();
return 0; return 0;
} }
@ -48,7 +47,7 @@ public class CIMCacheProvider extends ContentProvider {
public Uri insert(Uri arg0, ContentValues values) { public Uri insert(Uri arg0, ContentValues values) {
String key = values.getAsString("key"); String key = values.getAsString("key");
String value = values.getAsString("value"); String value = values.getAsString("value");
getContext().getSharedPreferences(MODEL_KEY, Context.MODE_PRIVATE).edit().putString(key, value).apply(); getContext().getSharedPreferences(MODEL_KEY, Context.MODE_PRIVATE).edit().putString(key, value).apply();
return null; return null;
} }
@ -59,9 +58,9 @@ public class CIMCacheProvider extends ContentProvider {
@Override @Override
public Cursor query(Uri arg0, String[] arg1, String key, String[] arg3, String arg4) { public Cursor query(Uri arg0, String[] arg1, String key, String[] arg3, String arg4) {
MatrixCursor cursor = new MatrixCursor(new String[]{"value"}); MatrixCursor cursor = new MatrixCursor(new String[] { "value" });
String value = getContext().getSharedPreferences(MODEL_KEY, Context.MODE_PRIVATE).getString(arg1[0], null); String value = getContext().getSharedPreferences(MODEL_KEY, Context.MODE_PRIVATE).getString(arg1[0], null);
cursor.addRow(new Object[]{value}); cursor.addRow(new Object[] { value });
return cursor; return cursor;
} }
@ -70,5 +69,4 @@ public class CIMCacheProvider extends ContentProvider {
return 0; return 0;
} }
} }

View File

@ -20,6 +20,7 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.android; package com.farsunset.cim.sdk.android;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
@ -57,25 +58,23 @@ import com.farsunset.cim.sdk.android.model.SentBody;
* *
* @author 3979434@qq.com * @author 3979434@qq.com
*/ */
class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFactory { class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFactory {
private final String TAG = CIMConnectorManager.class.getSimpleName(); private final String TAG = CIMConnectorManager.class.getSimpleName();
private final int READ_BUFFER_SIZE = 2048;//bit private final int READ_BUFFER_SIZE = 2048;// bit
private final int CONNECT_TIMEOUT = 10 * 1000;// private final int CONNECT_TIMEOUT = 10 * 1000;//
private final int WRITE_TIMEOUT = 10 * 1000;// private final int WRITE_TIMEOUT = 10 * 1000;//
private final int READ_IDLE_TIME = 120;// private final int READ_IDLE_TIME = 120;//
private final int HEARBEAT_TIME_OUT = (READ_IDLE_TIME + 10) * 1000;// 收到服务端心跳请求超时时间 毫秒 private final int HEARBEAT_TIME_OUT = (READ_IDLE_TIME + 10) * 1000;// 收到服务端心跳请求超时时间 毫秒
private final String KEY_LAST_HEART_TIME = "KEY_LAST_HEART_TIME" ; private final String KEY_LAST_HEART_TIME = "KEY_LAST_HEART_TIME";
private NioSocketConnector connector; private NioSocketConnector connector;
private ConnectFuture connectFuture; private ConnectFuture connectFuture;
private ExecutorService executor = Executors.newFixedThreadPool(1); private ExecutorService executor = Executors.newFixedThreadPool(1);
private Context context; private Context context;
private static CIMConnectorManager manager;
private static CIMConnectorManager manager;
private CIMConnectorManager(Context ctx) { private CIMConnectorManager(Context ctx) {
context = ctx; context = ctx;
@ -85,15 +84,15 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageF
connector.getSessionConfig().setTcpNoDelay(true); connector.getSessionConfig().setTcpNoDelay(true);
connector.getSessionConfig().setKeepAlive(true); connector.getSessionConfig().setKeepAlive(true);
connector.getSessionConfig().setReadBufferSize(READ_BUFFER_SIZE); connector.getSessionConfig().setReadBufferSize(READ_BUFFER_SIZE);
KeepAliveFilter keepAliveaHandler = new KeepAliveFilter(this); KeepAliveFilter keepAliveaHandler = new KeepAliveFilter(this);
keepAliveaHandler.setRequestInterval(READ_IDLE_TIME); keepAliveaHandler.setRequestInterval(READ_IDLE_TIME);
keepAliveaHandler.setRequestTimeoutHandler(KeepAliveRequestTimeoutHandler.NOOP); keepAliveaHandler.setRequestTimeoutHandler(KeepAliveRequestTimeoutHandler.NOOP);
keepAliveaHandler.setForwardEvent(true); keepAliveaHandler.setForwardEvent(true);
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ClientMessageCodecFactory())); connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ClientMessageCodecFactory()));
connector.getFilterChain().addLast("heartbeat", keepAliveaHandler); connector.getFilterChain().addLast("heartbeat", keepAliveaHandler);
connector.setHandler(this); connector.setHandler(this);
} }
@ -106,88 +105,85 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageF
} }
private synchronized void syncConnection(final String host,final int port) { private synchronized void syncConnection(final String host, final int port) {
if(isConnected()){ if (isConnected()) {
return ; return;
} }
try { try {
Log.i(TAG, "****************CIM正在连接服务器 "+host+":"+port+"......"); Log.i(TAG, "****************CIM正在连接服务器 " + host + ":" + port + "......");
CIMCacheManager.putBoolean(context,CIMCacheManager.KEY_CIM_CONNECTION_STATE, false); CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_CIM_CONNECTION_STATE, false);
InetSocketAddress remoteSocketAddress = new InetSocketAddress(host, port); InetSocketAddress remoteSocketAddress = new InetSocketAddress(host, port);
connectFuture = connector.connect(remoteSocketAddress); connectFuture = connector.connect(remoteSocketAddress);
connectFuture.awaitUninterruptibly(); connectFuture.awaitUninterruptibly();
connectFuture.getSession(); connectFuture.getSession();
} catch (Exception e) { } catch (Exception e) {
long interval = CIMConstant.RECONN_INTERVAL_TIME - (5*1000 - new Random().nextInt(15*1000)); long interval = CIMConstant.RECONN_INTERVAL_TIME - (5 * 1000 - new Random().nextInt(15 * 1000));
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED); intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED);
intent.putExtra(Exception.class.getName(), e.getClass().getSimpleName()); intent.putExtra(Exception.class.getName(), e.getClass().getSimpleName());
intent.putExtra("interval", interval); intent.putExtra("interval", interval);
context.sendBroadcast(intent); context.sendBroadcast(intent);
Log.e(TAG, "****************CIM连接服务器失败 "+host+":"+port+"......将在"+interval/1000+"秒后重新尝试连接"); Log.e(TAG, "****************CIM连接服务器失败 " + host + ":" + port + "......将在" + interval / 1000 + "秒后重新尝试连接");
} }
} }
public void connect(final String host, final int port) { public void connect(final String host, final int port) {
if (!isNetworkConnected(context)) { if (!isNetworkConnected(context)) {
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED); intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED);
intent.putExtra(Exception.class.getName(),NetworkDisabledException.class.getSimpleName()); intent.putExtra(Exception.class.getName(), NetworkDisabledException.class.getSimpleName());
context.sendBroadcast(intent); context.sendBroadcast(intent);
return; return;
} }
executor.execute(new Runnable() { executor.execute(new Runnable() {
public void run() public void run() {
{
syncConnection(host, port); syncConnection(host, port);
} }
}); });
} }
public synchronized void send(SentBody body) { public synchronized void send(SentBody body) {
boolean isSuccessed = false; boolean isSuccessed = false;
String exceptionName =SessionClosedException.class.getSimpleName(); String exceptionName = SessionClosedException.class.getSimpleName();
IoSession session = getCurrentSession(); IoSession session = getCurrentSession();
if(session!=null && session.isConnected()) if (session != null && session.isConnected()) {
{
WriteFuture wf = session.write(body); WriteFuture wf = session.write(body);
// 消息发送超时 5秒 // 消息发送超时 5秒
wf.awaitUninterruptibly(WRITE_TIMEOUT); wf.awaitUninterruptibly(WRITE_TIMEOUT);
isSuccessed = wf.isWritten(); isSuccessed = wf.isWritten();
if(wf.getException() != null) if (wf.getException() != null) {
{ exceptionName = wf.getException().getClass().getSimpleName();
exceptionName =wf.getException().getClass().getSimpleName();
} }
} }
if(!isSuccessed){ if (!isSuccessed) {
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_SENT_FAILED); intent.setAction(CIMConstant.IntentAction.ACTION_SENT_FAILED);
intent.putExtra(Exception.class.getName(),exceptionName); intent.putExtra(Exception.class.getName(), exceptionName);
intent.putExtra(SentBody.class.getName(), body); intent.putExtra(SentBody.class.getName(), body);
context.sendBroadcast(intent); context.sendBroadcast(intent);
} }
} }
public void destroy() { public void destroy() {
IoSession session = getCurrentSession(); IoSession session = getCurrentSession();
if (session != null) { if (session != null) {
session.closeNow(); session.closeNow();
@ -196,59 +192,51 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageF
if (connector != null && !connector.isDisposed()) { if (connector != null && !connector.isDisposed()) {
connector.dispose(); connector.dispose();
} }
manager = null; manager = null;
} }
public boolean isConnected() { public boolean isConnected() {
IoSession session = getCurrentSession(); IoSession session = getCurrentSession();
return session != null ; return session != null;
} }
public void closeSession() {
public void closeSession()
{
IoSession session = getCurrentSession(); IoSession session = getCurrentSession();
if(session!=null) if (session != null) {
{
session.closeNow(); session.closeNow();
} }
} }
public IoSession getCurrentSession() public IoSession getCurrentSession() {
{ Map<Long, IoSession> sessions = connector.getManagedSessions();
Map<Long,IoSession> sessions = connector.getManagedSessions(); for (Long key : sessions.keySet()) {
for(Long key:sessions.keySet())
{
IoSession session = sessions.get(key); IoSession session = sessions.get(key);
if(session.isConnected()){ if (session.isConnected()) {
return session; return session;
} }
} }
return null; return null;
} }
@Override @Override
public void sessionCreated(IoSession session) throws Exception { public void sessionCreated(IoSession session) throws Exception {
Log.i(TAG, "****************CIM连接服务器成功:" + session.getLocalAddress() + " NID:" + session.getId());
Log.i(TAG, "****************CIM连接服务器成功:"+session.getLocalAddress()+" NID:"+session.getId());
setLastHeartbeatTime(session); setLastHeartbeatTime(session);
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_SUCCESSED); intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_SUCCESSED);
context.sendBroadcast(intent); context.sendBroadcast(intent);
} }
@Override @Override
public void sessionClosed(IoSession session) { public void sessionClosed(IoSession session) {
Log.e(TAG, "****************CIM与服务器断开连接:"+session.getLocalAddress()+" NID:"+session.getId()); Log.e(TAG, "****************CIM与服务器断开连接:" + session.getLocalAddress() + " NID:" + session.getId());
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED); intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED);
context.sendBroadcast(intent); context.sendBroadcast(intent);
@ -256,45 +244,44 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageF
} }
@Override @Override
public void sessionIdle(IoSession session, IdleStatus status) { public void sessionIdle(IoSession session, IdleStatus status) {
Log.d(TAG, "****************CIM "+status.toString().toUpperCase()+":"+session.getLocalAddress() +" NID:"+session.getId()+ " isConnected:" + session.isConnected()); Log.d(TAG, "****************CIM " + status.toString().toUpperCase() + ":" + session.getLocalAddress() + " NID:"
+ session.getId() + " isConnected:" + session.isConnected());
/** /**
* 用于解决wifi情况下偶而路由器与服务器断开连接时客户端并没及时收到关闭事件 * 用于解决wifi情况下偶而路由器与服务器断开连接时客户端并没及时收到关闭事件 导致这样的情况下当前连接无效也不会重连的问题
* 导致这样的情况下当前连接无效也不会重连的问题
* *
*/ */
long lastHeartbeatTime = getLastHeartbeatTime(session); long lastHeartbeatTime = getLastHeartbeatTime(session);
if(System.currentTimeMillis() - lastHeartbeatTime >= HEARBEAT_TIME_OUT) if (System.currentTimeMillis() - lastHeartbeatTime >= HEARBEAT_TIME_OUT) {
{
session.closeNow(); session.closeNow();
Log.e(TAG, "****************CIM心跳超时 ,即将重新连接......"+" NID:"+session.getId()); Log.e(TAG, "****************CIM心跳超时 ,即将重新连接......" + " NID:" + session.getId());
} }
} }
@Override @Override
public void exceptionCaught(IoSession session, Throwable cause) { public void exceptionCaught(IoSession session, Throwable cause) {
Log.e(TAG, "****************CIM连接出现未知异常:"+session.getLocalAddress()+" NID:"+session.getId()); Log.e(TAG, "****************CIM连接出现未知异常:" + session.getLocalAddress() + " NID:" + session.getId());
if(cause!=null && cause.getMessage()!=null){ if (cause != null && cause.getMessage() != null) {
Log.e(TAG, cause.getMessage()); Log.e(TAG, cause.getMessage());
} }
} }
@Override @Override
public void messageReceived(IoSession session, Object obj){ public void messageReceived(IoSession session, Object obj) {
if (obj instanceof Message) { if (obj instanceof Message) {
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED); intent.setAction(CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED);
intent.putExtra(Message.class.getName(), (Message) obj); intent.putExtra(Message.class.getName(), (Message) obj);
context.sendBroadcast(intent); context.sendBroadcast(intent);
} }
if (obj instanceof ReplyBody) { if (obj instanceof ReplyBody) {
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_REPLY_RECEIVED); intent.setAction(CIMConstant.IntentAction.ACTION_REPLY_RECEIVED);
intent.putExtra(ReplyBody.class.getName(), (ReplyBody) obj); intent.putExtra(ReplyBody.class.getName(), (ReplyBody) obj);
@ -304,42 +291,38 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageF
@Override @Override
public void messageSent(IoSession session, Object message) { public void messageSent(IoSession session, Object message) {
if(message instanceof SentBody) if (message instanceof SentBody) {
{
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_SENT_SUCCESSED); intent.setAction(CIMConstant.IntentAction.ACTION_SENT_SUCCESSED);
intent.putExtra(SentBody.class.getName(), (SentBody) message); intent.putExtra(SentBody.class.getName(), (SentBody) message);
context.sendBroadcast(intent); context.sendBroadcast(intent);
} }
} }
private void setLastHeartbeatTime(IoSession session) {
private void setLastHeartbeatTime(IoSession session)
{
session.setAttribute(KEY_LAST_HEART_TIME, System.currentTimeMillis()); session.setAttribute(KEY_LAST_HEART_TIME, System.currentTimeMillis());
} }
private long getLastHeartbeatTime(IoSession session) private long getLastHeartbeatTime(IoSession session) {
{
long time = 0; long time = 0;
Object value = session.getAttribute(KEY_LAST_HEART_TIME); Object value = session.getAttribute(KEY_LAST_HEART_TIME);
if(value !=null){ if (value != null) {
time = Long.parseLong(value.toString()); time = Long.parseLong(value.toString());
} }
return time; return time;
} }
public static boolean isNetworkConnected(Context context) { public static boolean isNetworkConnected(Context context) {
try { try {
ConnectivityManager nw = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); ConnectivityManager nw = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = nw.getActiveNetworkInfo(); NetworkInfo networkInfo = nw.getActiveNetworkInfo();
return networkInfo != null; return networkInfo != null;
} catch (Exception e) {} } catch (Exception e) {
}
return false; return false;
} }
@Override @Override
public Object getRequest(IoSession arg0) { public Object getRequest(IoSession arg0) {
return null; return null;
@ -352,9 +335,9 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageF
@Override @Override
public boolean isRequest(IoSession session, Object data) { public boolean isRequest(IoSession session, Object data) {
setLastHeartbeatTime(session); setLastHeartbeatTime(session);
return data instanceof HeartbeatRequest; return data instanceof HeartbeatRequest;
} }

View File

@ -21,7 +21,6 @@
*/ */
package com.farsunset.cim.sdk.android; package com.farsunset.cim.sdk.android;
import com.farsunset.cim.sdk.android.constant.CIMConstant; import com.farsunset.cim.sdk.android.constant.CIMConstant;
import com.farsunset.cim.sdk.android.exception.SessionClosedException; import com.farsunset.cim.sdk.android.exception.SessionClosedException;
import com.farsunset.cim.sdk.android.model.Message; import com.farsunset.cim.sdk.android.model.Message;
@ -33,207 +32,185 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
/** /**
* 消息入口所有消息都会经过这里 * 消息入口所有消息都会经过这里
*/ */
public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver{ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver {
protected Context context; protected Context context;
@Override @Override
public void onReceive(Context ctx, Intent intent) { public void onReceive(Context ctx, Intent intent) {
context = ctx; context = ctx;
/*
* 操作事件广播用于提高service存活率
*/
if(intent.getAction().equals(Intent.ACTION_USER_PRESENT)
||intent.getAction().equals(Intent.ACTION_POWER_CONNECTED)
||intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED))
{
startPushService();
}
/* /*
* 设备网络状态变化事件 * 操作事件广播用于提高service存活率
*/ */
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_NETWORK_CHANGED)) if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)
{ || intent.getAction().equals(Intent.ACTION_POWER_CONNECTED)
ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); || intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED)) {
onDevicesNetworkChanged(connectivityManager.getActiveNetworkInfo()); startPushService();
} }
/* /*
* cim断开服务器事件 * 设备网络状态变化事件
*/ */
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED)) if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_NETWORK_CHANGED)) {
{ ConnectivityManager connectivityManager = (ConnectivityManager) context
onInnerConnectionClosed(); .getSystemService(Context.CONNECTIVITY_SERVICE);
} onDevicesNetworkChanged(connectivityManager.getActiveNetworkInfo());
}
/*
* cim连接服务器失败事件 /*
*/ * cim断开服务器事件
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED)) */
{ if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED)) {
long interval = intent.getLongExtra("interval", CIMConstant.RECONN_INTERVAL_TIME); onInnerConnectionClosed();
String exceptionName = intent.getStringExtra(Exception.class.getName()); }
onConnectionFailed(exceptionName,interval);
} /*
* cim连接服务器失败事件
/* */
* cim连接服务器成功事件 if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED)) {
*/ long interval = intent.getLongExtra("interval", CIMConstant.RECONN_INTERVAL_TIME);
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_SUCCESSED)) String exceptionName = intent.getStringExtra(Exception.class.getName());
{ onConnectionFailed(exceptionName, interval);
onInnerConnectionSuccessed(); }
}
/*
/* * cim连接服务器成功事件
* 收到推送消息事件 */
*/ if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_SUCCESSED)) {
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED)) onInnerConnectionSuccessed();
{ }
onInnerMessageReceived((Message)intent.getSerializableExtra(Message.class.getName()),intent);
} /*
* 收到推送消息事件
*/
/* if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED)) {
* 获取收到replybody成功事件 onInnerMessageReceived((Message) intent.getSerializableExtra(Message.class.getName()), intent);
*/ }
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_REPLY_RECEIVED))
{ /*
onReplyReceived((ReplyBody)intent.getSerializableExtra(ReplyBody.class.getName())); * 获取收到replybody成功事件
} */
if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_REPLY_RECEIVED)) {
onReplyReceived((ReplyBody) intent.getSerializableExtra(ReplyBody.class.getName()));
/* }
* 获取sendbody发送失败事件
*/ /*
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_SENT_FAILED)) * 获取sendbody发送失败事件
{ */
String exceptionName = intent.getStringExtra(Exception.class.getName()); if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_SENT_FAILED)) {
SentBody sentBody = (SentBody)intent.getSerializableExtra(SentBody.class.getName()); String exceptionName = intent.getStringExtra(Exception.class.getName());
onSentFailed(exceptionName,sentBody); SentBody sentBody = (SentBody) intent.getSerializableExtra(SentBody.class.getName());
} onSentFailed(exceptionName, sentBody);
}
/*
* 获取sendbody发送成功事件 /*
*/ * 获取sendbody发送成功事件
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_SENT_SUCCESSED)) */
{ if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_SENT_SUCCESSED)) {
onSentSucceed((SentBody)intent.getSerializableExtra(SentBody.class.getName())); onSentSucceed((SentBody) intent.getSerializableExtra(SentBody.class.getName()));
} }
/*
* 重新连接如果断开的话
/* */
* 重新连接如果断开的话 if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_RECOVERY)) {
*/ CIMPushManager.connect(context, 0);
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_RECOVERY)) }
{
CIMPushManager.connect(context,0);
}
} }
private void startPushService(){ private void startPushService() {
Intent intent = new Intent(context, CIMPushService.class); Intent intent = new Intent(context, CIMPushService.class);
intent.setAction(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE); intent.setAction(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE);
context.startService(intent); context.startService(intent);
} }
private void onInnerConnectionClosed(){ private void onInnerConnectionClosed() {
CIMCacheManager.putBoolean(context,CIMCacheManager.KEY_CIM_CONNECTION_STATE, false); CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_CIM_CONNECTION_STATE, false);
if(CIMConnectorManager.isNetworkConnected(context)) if (CIMConnectorManager.isNetworkConnected(context)) {
{ CIMPushManager.connect(context, 0);
CIMPushManager.connect(context,0);
} }
onConnectionClosed(); onConnectionClosed();
} }
private void onConnectionFailed(String exceptionName,long reinterval){ private void onConnectionFailed(String exceptionName, long reinterval) {
if(CIMConnectorManager.isNetworkConnected(context)) if (CIMConnectorManager.isNetworkConnected(context)) {
{
onConnectionFailed(); onConnectionFailed();
CIMPushManager.connect(context,reinterval); CIMPushManager.connect(context, reinterval);
} }
} }
private void onInnerConnectionSuccessed(){ private void onInnerConnectionSuccessed() {
CIMCacheManager.putBoolean(context,CIMCacheManager.KEY_CIM_CONNECTION_STATE, true); CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_CIM_CONNECTION_STATE, true);
boolean autoBind = CIMPushManager.autoBindAccount(context); boolean autoBind = CIMPushManager.autoBindAccount(context);
onConnectionSuccessed(autoBind); onConnectionSuccessed(autoBind);
} }
private void onDevicesNetworkChanged(NetworkInfo info) { private void onDevicesNetworkChanged(NetworkInfo info) {
if(info !=null) if (info != null) {
{ CIMPushManager.connect(context, 0);
CIMPushManager.connect(context,0); }
}
onNetworkChanged(info); onNetworkChanged(info);
} }
private void onInnerMessageReceived(com.farsunset.cim.sdk.android.model.Message message, Intent intent){ private void onInnerMessageReceived(com.farsunset.cim.sdk.android.model.Message message, Intent intent) {
if(isForceOfflineMessage(message.getAction())) if (isForceOfflineMessage(message.getAction())) {
{
CIMPushManager.stop(context); CIMPushManager.stop(context);
} }
onMessageReceived(message,intent); onMessageReceived(message, intent);
}
private boolean isForceOfflineMessage(String action)
{
return CIMConstant.MessageAction.ACTION_999.equals(action);
}
private void onSentFailed(String exceptionName, SentBody body){
//与服务端端开链接重新连接
if(SessionClosedException.class.getSimpleName().equals(exceptionName))
{
CIMPushManager.connect(context,0);
}else
{
//发送失败 重新发送
CIMPushManager.sendRequest(context, body);
}
} }
private boolean isForceOfflineMessage(String action) {
return CIMConstant.MessageAction.ACTION_999.equals(action);
public abstract void onMessageReceived(com.farsunset.cim.sdk.android.model.Message message,Intent intent); }
public void onNetworkChanged(NetworkInfo info) { private void onSentFailed(String exceptionName, SentBody body) {
// 与服务端端开链接重新连接
if (SessionClosedException.class.getSimpleName().equals(exceptionName)) {
CIMPushManager.connect(context, 0);
} else {
// 发送失败 重新发送
CIMPushManager.sendRequest(context, body);
}
}
public abstract void onMessageReceived(com.farsunset.cim.sdk.android.model.Message message, Intent intent);
public void onNetworkChanged(NetworkInfo info) {
CIMListenerManager.notifyOnNetworkChanged(info); CIMListenerManager.notifyOnNetworkChanged(info);
} }
public void onConnectionSuccessed(boolean hasAutoBind) {
public void onConnectionSuccessed(boolean hasAutoBind) {
CIMListenerManager.notifyOnConnectionSuccessed(hasAutoBind); CIMListenerManager.notifyOnConnectionSuccessed(hasAutoBind);
} }
public void onConnectionClosed() { public void onConnectionClosed() {
CIMListenerManager.notifyOnConnectionClosed(); CIMListenerManager.notifyOnConnectionClosed();
} }
public void onConnectionFailed() { public void onConnectionFailed() {
CIMListenerManager.notifyOnConnectionFailed(); CIMListenerManager.notifyOnConnectionFailed();
} }
public void onReplyReceived(ReplyBody body) { public void onReplyReceived(ReplyBody body) {
CIMListenerManager.notifyOnReplyReceived(body); CIMListenerManager.notifyOnReplyReceived(body);
} }
public void onSentSucceed(SentBody body){ public void onSentSucceed(SentBody body) {
CIMListenerManager.notifyOnSentSucceed(body); CIMListenerManager.notifyOnSentSucceed(body);
} }
} }

View File

@ -28,59 +28,60 @@ import com.farsunset.cim.sdk.android.model.ReplyBody;
import com.farsunset.cim.sdk.android.model.SentBody; import com.farsunset.cim.sdk.android.model.SentBody;
/** /**
*CIM 主要事件接口 * CIM 主要事件接口
*/ */
public interface CIMEventListener public interface CIMEventListener {
{
/**
* 当收到服务端推送过来的消息时调用
*
* @param message
*/
void onMessageReceived(Message message);
/** /**
* 当收到服务端推送过来的消息时调用 * 当调用CIMPushManager.sendRequest()向服务端发送请求获得相应时调用
* @param message *
*/ * @param replybody
void onMessageReceived(Message message); */
void onReplyReceived(ReplyBody replybody);
/** /**
* 当调用CIMPushManager.sendRequest()向服务端发送请求获得相应时调用 * 当调用CIMPushManager.sendRequest()向服务端发送请求成功时
* @param replybody *
*/ * @param body
void onReplyReceived(ReplyBody replybody); */
void onSentSuccessed(SentBody body);
/** /**
* 当调用CIMPushManager.sendRequest()向服务端发送请求成功时 * 当手机网络发生变化时调用
* @param body *
*/ * @param networkinfo
void onSentSuccessed(SentBody body); */
void onNetworkChanged(NetworkInfo networkinfo);
/**
/** * 当连接服务器成功时回调
* 当手机网络发生变化时调用 *
* @param networkinfo * @param hasAutoBind
*/ * : true 已经自动绑定账号到服务器了不需要再手动调用bindAccount
void onNetworkChanged(NetworkInfo networkinfo); */
void onConnectionSuccessed(boolean hasAutoBind);
/** /**
* 当连接服务器成功时回调 * 当断开服务器连接的时候回调
* @param hasAutoBind : true 已经自动绑定账号到服务器了不需要再手动调用bindAccount *
*/ */
void onConnectionSuccessed(boolean hasAutoBind); void onConnectionClosed();
/** /**
* 当断开服务器连接的时候回调 * 当连接服务器失败的时候回调
* *
*/ */
void onConnectionClosed(); void onConnectionFailed();
/** /**
* 当连接服务器失败的时候回调 * 监听器在容器里面的排序值越大则越先接收
* */
*/ int getEventDispatchOrder();
void onConnectionFailed();
/**
* 监听器在容器里面的排序值越大则越先接收
*/
int getEventDispatchOrder();
} }

View File

@ -20,6 +20,7 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.android; package com.farsunset.cim.sdk.android;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@ -30,25 +31,23 @@ import com.farsunset.cim.sdk.android.model.SentBody;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.util.Log; import android.util.Log;
/** /**
* CIM 消息监听器管理 * CIM 消息监听器管理
*/ */
public class CIMListenerManager { public class CIMListenerManager {
private static ArrayList<CIMEventListener> cimListeners = new ArrayList<CIMEventListener>(); private static ArrayList<CIMEventListener> cimListeners = new ArrayList<CIMEventListener>();
private static CIMMessageReceiveComparator comparator = new CIMMessageReceiveComparator(); private static CIMMessageReceiveComparator comparator = new CIMMessageReceiveComparator();
public static void registerMessageListener(CIMEventListener listener) { public static void registerMessageListener(CIMEventListener listener) {
if (!cimListeners.contains(listener)) { if (!cimListeners.contains(listener)) {
cimListeners.add(listener); cimListeners.add(listener);
Collections.sort(cimListeners,comparator); Collections.sort(cimListeners, comparator);
} }
} }
public static void removeMessageListener(CIMEventListener listener) { public static void removeMessageListener(CIMEventListener listener) {
for (int i = 0; i < cimListeners.size(); i++) { for (int i = 0; i < cimListeners.size(); i++) {
if (listener.getClass() == cimListeners.get(i).getClass()) { if (listener.getClass() == cimListeners.get(i).getClass()) {
@ -56,76 +55,72 @@ public class CIMListenerManager {
} }
} }
} }
public static void notifyOnNetworkChanged(NetworkInfo info) { public static void notifyOnNetworkChanged(NetworkInfo info) {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onNetworkChanged(info); listener.onNetworkChanged(info);
} }
} }
public static void notifyOnConnectionSuccessed(boolean hasAutoBind) { public static void notifyOnConnectionSuccessed(boolean hasAutoBind) {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onConnectionSuccessed(hasAutoBind); listener.onConnectionSuccessed(hasAutoBind);
} }
} }
public static void notifyOnMessageReceived(Message message) { public static void notifyOnMessageReceived(Message message) {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onMessageReceived(message); listener.onMessageReceived(message);
} }
} }
public static void notifyOnConnectionClosed() { public static void notifyOnConnectionClosed() {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onConnectionClosed(); listener.onConnectionClosed();
} }
} }
public static void notifyOnConnectionFailed() { public static void notifyOnConnectionFailed() {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onConnectionFailed(); listener.onConnectionFailed();
} }
} }
public static void notifyOnReplyReceived(ReplyBody body) { public static void notifyOnReplyReceived(ReplyBody body) {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onReplyReceived(body); listener.onReplyReceived(body);
} }
} }
public static void notifyOnSentSucceed(SentBody body) { public static void notifyOnSentSucceed(SentBody body) {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onSentSuccessed(body); listener.onSentSuccessed(body);
} }
} }
public static void destory() { public static void destory() {
cimListeners.clear(); cimListeners.clear();
} }
public static void logListenersName() { public static void logListenersName() {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
Log.i(CIMEventListener.class.getSimpleName(),"#######" + listener.getClass().getName() + "#######" ); Log.i(CIMEventListener.class.getSimpleName(), "#######" + listener.getClass().getName() + "#######");
} }
} }
/** /**
* 消息接收activity的接收顺序排序CIM_RECEIVE_ORDER倒序 * 消息接收activity的接收顺序排序CIM_RECEIVE_ORDER倒序
*/ */
private static class CIMMessageReceiveComparator implements Comparator<CIMEventListener>{ private static class CIMMessageReceiveComparator implements Comparator<CIMEventListener> {
@Override @Override
public int compare(CIMEventListener arg1, CIMEventListener arg2) { public int compare(CIMEventListener arg1, CIMEventListener arg2) {
int order1 = arg1.getEventDispatchOrder(); int order1 = arg1.getEventDispatchOrder();
int order2 = arg2.getEventDispatchOrder(); int order2 = arg2.getEventDispatchOrder();
return order2 - order1 ; return order2 - order1;
} }
} }
} }

View File

@ -20,6 +20,7 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.android; package com.farsunset.cim.sdk.android;
import java.util.UUID; import java.util.UUID;
import android.content.Context; import android.content.Context;
@ -34,212 +35,204 @@ import com.farsunset.cim.sdk.android.model.SentBody;
/** /**
* CIM 功能接口 * CIM 功能接口
*/ */
public class CIMPushManager { public class CIMPushManager {
static String ACTION_ACTIVATE_PUSH_SERVICE = "ACTION_ACTIVATE_PUSH_SERVICE";
static String ACTION_CREATE_CIM_CONNECTION = "ACTION_CREATE_CIM_CONNECTION";
static String ACTION_SEND_REQUEST_BODY = "ACTION_SEND_REQUEST_BODY";
static String ACTION_CLOSE_CIM_CONNECTION = "ACTION_CLOSE_CIM_CONNECTION";
static String ACTION_DESTORY = "ACTION_DESTORY";
static String KEY_SEND_BODY = "KEY_SEND_BODY";
static String KEY_CIM_CONNECTION_STATUS = "KEY_CIM_CONNECTION_STATUS";
static String ACTION_ACTIVATE_PUSH_SERVICE ="ACTION_ACTIVATE_PUSH_SERVICE";
static String ACTION_CREATE_CIM_CONNECTION ="ACTION_CREATE_CIM_CONNECTION";
static String ACTION_SEND_REQUEST_BODY ="ACTION_SEND_REQUEST_BODY";
static String ACTION_CLOSE_CIM_CONNECTION ="ACTION_CLOSE_CIM_CONNECTION";
static String ACTION_DESTORY ="ACTION_DESTORY";
static String KEY_SEND_BODY ="KEY_SEND_BODY";
static String KEY_CIM_CONNECTION_STATUS ="KEY_CIM_CONNECTION_STATUS";
/** /**
* 初始化,连接服务端在程序启动页或者 在Application里调用 * 初始化,连接服务端在程序启动页或者 在Application里调用
*
* @param context * @param context
* @param ip * @param ip
* @param port * @param port
*/ */
public static void connect(Context context,String host,int port){ public static void connect(Context context, String host, int port) {
connect(context,host,port,false,0); connect(context, host, port, false, 0);
} }
private static void connect(Context context,String ip,int port,boolean autoBind,long delayedTime){ private static void connect(Context context, String ip, int port, boolean autoBind, long delayedTime) {
CIMCacheManager.putBoolean(context,CIMCacheManager.KEY_CIM_DESTROYED, false); CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED, false);
CIMCacheManager.putBoolean(context,CIMCacheManager.KEY_MANUAL_STOP, false); CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_MANUAL_STOP, false);
CIMCacheManager.putString(context, CIMCacheManager.KEY_CIM_SERVIER_HOST, ip); CIMCacheManager.putString(context, CIMCacheManager.KEY_CIM_SERVIER_HOST, ip);
CIMCacheManager.putInt(context, CIMCacheManager.KEY_CIM_SERVIER_PORT, port); CIMCacheManager.putInt(context, CIMCacheManager.KEY_CIM_SERVIER_PORT, port);
if(!autoBind) if (!autoBind) {
{ CIMCacheManager.remove(context, CIMCacheManager.KEY_ACCOUNT);
CIMCacheManager.remove(context,CIMCacheManager.KEY_ACCOUNT);
} }
Intent serviceIntent = new Intent(context, CIMPushService.class); Intent serviceIntent = new Intent(context, CIMPushService.class);
serviceIntent.putExtra(CIMCacheManager.KEY_CIM_SERVIER_HOST, ip); serviceIntent.putExtra(CIMCacheManager.KEY_CIM_SERVIER_HOST, ip);
serviceIntent.putExtra(CIMCacheManager.KEY_CIM_SERVIER_PORT, port); serviceIntent.putExtra(CIMCacheManager.KEY_CIM_SERVIER_PORT, port);
serviceIntent.putExtra(CIMPushService.KEY_DELAYED_TIME, delayedTime); serviceIntent.putExtra(CIMPushService.KEY_DELAYED_TIME, delayedTime);
serviceIntent.setAction(ACTION_CREATE_CIM_CONNECTION); serviceIntent.setAction(ACTION_CREATE_CIM_CONNECTION);
context.startService(serviceIntent); context.startService(serviceIntent);
}
protected static void connect(Context context,long delayedTime){ }
boolean isManualStop = CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_MANUAL_STOP); protected static void connect(Context context, long delayedTime) {
boolean isManualDestory = CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_CIM_DESTROYED);
boolean isManualStop = CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_MANUAL_STOP);
if(isManualStop || isManualDestory) boolean isManualDestory = CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED);
{
return ; if (isManualStop || isManualDestory) {
return;
} }
String host = CIMCacheManager.getString(context, CIMCacheManager.KEY_CIM_SERVIER_HOST); String host = CIMCacheManager.getString(context, CIMCacheManager.KEY_CIM_SERVIER_HOST);
int port =CIMCacheManager.getInt(context, CIMCacheManager.KEY_CIM_SERVIER_PORT); int port = CIMCacheManager.getInt(context, CIMCacheManager.KEY_CIM_SERVIER_PORT);
connect(context,host,port,true,delayedTime); connect(context, host, port, true, delayedTime);
} }
/** /**
* 设置一个账号登录到服务端 * 设置一个账号登录到服务端
* @param account 用户唯一ID *
* @param account
* 用户唯一ID
*/ */
public static void bindAccount(Context context,String account){ public static void bindAccount(Context context, String account) {
boolean isManualDestory = CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED);
boolean isManualDestory = CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_CIM_DESTROYED); if (isManualDestory || account == null || account.trim().length() == 0) {
if(isManualDestory || account==null || account.trim().length()==0) return;
{ }
return ;
} sendBindRequest(context, account);
sendBindRequest(context,account);
} }
private static void sendBindRequest(Context context, String account) {
private static void sendBindRequest(Context context, String account){
CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_MANUAL_STOP, false);
CIMCacheManager.putBoolean(context,CIMCacheManager.KEY_MANUAL_STOP, false); CIMCacheManager.putString(context, CIMCacheManager.KEY_ACCOUNT, account);
CIMCacheManager.putString(context,CIMCacheManager.KEY_ACCOUNT, account);
String deviceId = CIMCacheManager.getString(context, CIMCacheManager.KEY_DEVICE_ID);
String deviceId = CIMCacheManager.getString(context,CIMCacheManager.KEY_DEVICE_ID); if (TextUtils.isEmpty(deviceId)) {
if(TextUtils.isEmpty(deviceId)) { deviceId = UUID.randomUUID().toString().replaceAll("-", "");
deviceId = UUID.randomUUID().toString().replaceAll("-", ""); CIMCacheManager.putString(context, CIMCacheManager.KEY_DEVICE_ID, deviceId);
CIMCacheManager.putString(context,CIMCacheManager.KEY_DEVICE_ID, deviceId); }
}
SentBody sent = new SentBody();
SentBody sent = new SentBody();
sent.setKey(CIMConstant.RequestKey.CLIENT_BIND); sent.setKey(CIMConstant.RequestKey.CLIENT_BIND);
sent.put("account", account); sent.put("account", account);
sent.put("deviceId",deviceId); sent.put("deviceId", deviceId);
sent.put("channel", "android"); sent.put("channel", "android");
sent.put("device",android.os.Build.MODEL); sent.put("device", android.os.Build.MODEL);
sent.put("version",getVersionName(context)); sent.put("version", getVersionName(context));
sent.put("osVersion",android.os.Build.VERSION.RELEASE); sent.put("osVersion", android.os.Build.VERSION.RELEASE);
sent.put("packageName",context.getPackageName()); sent.put("packageName", context.getPackageName());
sendRequest(context,sent); sendRequest(context, sent);
}
protected static boolean autoBindAccount(Context context){
String account = CIMCacheManager.getString(context,CIMCacheManager.KEY_ACCOUNT);
boolean isManualDestory = CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_CIM_DESTROYED);
if( account==null || account.trim().length()==0 || isManualDestory )
{
return false;
}
sendBindRequest(context,account);
return true;
} }
protected static boolean autoBindAccount(Context context) {
String account = CIMCacheManager.getString(context, CIMCacheManager.KEY_ACCOUNT);
/** boolean isManualDestory = CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED);
if (account == null || account.trim().length() == 0 || isManualDestory) {
return false;
}
sendBindRequest(context, account);
return true;
}
/**
* 发送一个CIM请求 * 发送一个CIM请求
*
* @param context * @param context
* @body * @body
*/ */
public static void sendRequest(Context context, SentBody body){ public static void sendRequest(Context context, SentBody body) {
boolean isManualStop = CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_MANUAL_STOP); boolean isManualStop = CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_MANUAL_STOP);
boolean isManualDestory = CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_CIM_DESTROYED); boolean isManualDestory = CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED);
if(isManualStop || isManualDestory) if (isManualStop || isManualDestory) {
{ return;
return ;
} }
Intent serviceIntent = new Intent(context, CIMPushService.class); Intent serviceIntent = new Intent(context, CIMPushService.class);
serviceIntent.putExtra(KEY_SEND_BODY, body); serviceIntent.putExtra(KEY_SEND_BODY, body);
serviceIntent.setAction(ACTION_SEND_REQUEST_BODY); serviceIntent.setAction(ACTION_SEND_REQUEST_BODY);
context.startService(serviceIntent); context.startService(serviceIntent);
} }
/** /**
* 停止接受推送将会退出当前账号登录端口与服务端的连接 * 停止接受推送将会退出当前账号登录端口与服务端的连接
*
* @param context * @param context
*/ */
public static void stop(Context context){ public static void stop(Context context) {
boolean isManualDestory = CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_CIM_DESTROYED);
if(isManualDestory){
return ;
}
CIMCacheManager.putBoolean(context,CIMCacheManager.KEY_MANUAL_STOP, true);
Intent serviceIntent = new Intent(context, CIMPushService.class); boolean isManualDestory = CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED);
if (isManualDestory) {
return;
}
CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_MANUAL_STOP, true);
Intent serviceIntent = new Intent(context, CIMPushService.class);
serviceIntent.setAction(ACTION_CLOSE_CIM_CONNECTION); serviceIntent.setAction(ACTION_CLOSE_CIM_CONNECTION);
context.startService(serviceIntent); context.startService(serviceIntent);
} }
/**
/**
* 完全销毁CIM一般用于完全退出程序调用resume将不能恢复 * 完全销毁CIM一般用于完全退出程序调用resume将不能恢复
*
* @param context * @param context
*/ */
public static void destroy(Context context){ public static void destroy(Context context) {
CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED, true);
CIMCacheManager.putBoolean(context,CIMCacheManager.KEY_CIM_DESTROYED, true); CIMCacheManager.putString(context, CIMCacheManager.KEY_ACCOUNT, null);
CIMCacheManager.putString(context,CIMCacheManager.KEY_ACCOUNT, null);
Intent serviceIntent = new Intent(context, CIMPushService.class);
Intent serviceIntent = new Intent(context, CIMPushService.class);
serviceIntent.setAction(ACTION_DESTORY); serviceIntent.setAction(ACTION_DESTORY);
context.startService(serviceIntent); context.startService(serviceIntent);
} }
/**
/** * 重新恢复接收推送重新连接服务端并登录当前账号
* 重新恢复接收推送重新连接服务端并登录当前账号 *
* @param context * @param context
*/ */
public static void resume(Context context){ public static void resume(Context context) {
boolean isManualDestory = CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_CIM_DESTROYED); boolean isManualDestory = CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED);
if(isManualDestory){ if (isManualDestory) {
return ; return;
} }
autoBindAccount(context); autoBindAccount(context);
} }
public static boolean isConnected(Context context){ public static boolean isConnected(Context context) {
return CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_CIM_CONNECTION_STATE); return CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_CIM_CONNECTION_STATE);
} }
private static String getVersionName(Context context) {
String versionName = null;
private static String getVersionName(Context context) {
String versionName = null;
try { try {
PackageInfo mPackageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); PackageInfo mPackageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
versionName = mPackageInfo.versionName; versionName = mPackageInfo.versionName;

View File

@ -20,6 +20,7 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.android; package com.farsunset.cim.sdk.android;
import android.app.Service; import android.app.Service;
import android.content.Intent; import android.content.Intent;
import android.os.Handler; import android.os.Handler;
@ -28,98 +29,88 @@ import android.os.Message;
import android.util.Log; import android.util.Log;
import com.farsunset.cim.sdk.android.model.SentBody; import com.farsunset.cim.sdk.android.model.SentBody;
/** /**
* 与服务端连接服务 * 与服务端连接服务
*
* @author 3979434 * @author 3979434
* *
*/ */
public class CIMPushService extends Service { public class CIMPushService extends Service {
private final String TAG = CIMPushService.class.getSimpleName(); private final String TAG = CIMPushService.class.getSimpleName();
public final static String KEY_DELAYED_TIME ="KEY_DELAYED_TIME"; public final static String KEY_DELAYED_TIME = "KEY_DELAYED_TIME";
private CIMConnectorManager manager; private CIMConnectorManager manager;
@Override
public void onCreate() @Override
{ public void onCreate() {
manager = CIMConnectorManager.getManager(this.getApplicationContext()); manager = CIMConnectorManager.getManager(this.getApplicationContext());
} }
Handler connectionHandler = new Handler() {
Handler connectionHandler = new Handler(){
@Override @Override
public void handleMessage(android.os.Message message){ public void handleMessage(android.os.Message message) {
connectionHandler.removeMessages(0); connectionHandler.removeMessages(0);
String host = message.getData().getString(CIMCacheManager.KEY_CIM_SERVIER_HOST); String host = message.getData().getString(CIMCacheManager.KEY_CIM_SERVIER_HOST);
int port = message.getData().getInt(CIMCacheManager.KEY_CIM_SERVIER_PORT,0); int port = message.getData().getInt(CIMCacheManager.KEY_CIM_SERVIER_PORT, 0);
manager.connect(host, port); manager.connect(host, port);
} }
}; };
@Override
@Override public int onStartCommand(Intent intent, int flags, int startId) {
public int onStartCommand(Intent intent,int flags, int startId) {
intent = (intent == null ? new Intent(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE) : intent);
intent = (intent == null ? new Intent(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE) : intent); String action = intent.getAction();
String action = intent.getAction(); if (CIMPushManager.ACTION_CREATE_CIM_CONNECTION.equals(action)) {
if(CIMPushManager.ACTION_CREATE_CIM_CONNECTION.equals(action)) long delayMillis = intent.getLongExtra(KEY_DELAYED_TIME, 0);
{ if (delayMillis > 0) {
long delayMillis = intent.getLongExtra(KEY_DELAYED_TIME,0); Message msg = connectionHandler.obtainMessage();
if( delayMillis > 0){ msg.what = 0;
msg.setData(intent.getExtras());
Message msg = connectionHandler.obtainMessage(); connectionHandler.sendMessageDelayed(msg, delayMillis);
msg.what = 0;
msg.setData(intent.getExtras()); } else {
connectionHandler.sendMessageDelayed(msg, delayMillis); String host = intent.getStringExtra(CIMCacheManager.KEY_CIM_SERVIER_HOST);
int port = intent.getIntExtra(CIMCacheManager.KEY_CIM_SERVIER_PORT, 0);
}else manager.connect(host, port);
{ }
String host = intent.getStringExtra(CIMCacheManager.KEY_CIM_SERVIER_HOST); }
int port = intent.getIntExtra(CIMCacheManager.KEY_CIM_SERVIER_PORT,0);
manager.connect(host,port); if (CIMPushManager.ACTION_SEND_REQUEST_BODY.equals(action)) {
} manager.send((SentBody) intent.getSerializableExtra(CIMPushManager.KEY_SEND_BODY));
} }
if(CIMPushManager.ACTION_SEND_REQUEST_BODY.equals(action)) if (CIMPushManager.ACTION_CLOSE_CIM_CONNECTION.equals(action)) {
{ manager.closeSession();
manager.send((SentBody) intent.getSerializableExtra(CIMPushManager.KEY_SEND_BODY)); }
}
if (CIMPushManager.ACTION_DESTORY.equals(action)) {
if(CIMPushManager.ACTION_CLOSE_CIM_CONNECTION.equals(action)) manager.destroy();
{ this.stopSelf();
manager.closeSession(); }
}
if (CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE.equals(action)) {
if(CIMPushManager.ACTION_DESTORY.equals(action)) if (!manager.isConnected()) {
{
manager.destroy(); boolean isManualStop = CIMCacheManager.getBoolean(getApplicationContext(),
this.stopSelf(); CIMCacheManager.KEY_MANUAL_STOP);
} Log.w(TAG, "manager.isConnected() == false, isManualStop == " + isManualStop);
CIMPushManager.connect(this, 0);
if(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE.equals(action) )
{ } else {
if(!manager.isConnected()){ Log.i(TAG, "manager.isConnected() == true");
}
boolean isManualStop = CIMCacheManager.getBoolean(getApplicationContext(),CIMCacheManager.KEY_MANUAL_STOP);
Log.w(TAG, "manager.isConnected() == false, isManualStop == " + isManualStop); }
CIMPushManager.connect(this,0);
return START_STICKY;
}else }
{
Log.i(TAG, "manager.isConnected() == true");
}
}
return START_STICKY;
}
@Override @Override
public IBinder onBind(Intent arg0) { public IBinder onBind(Intent arg0) {
return null; return null;

View File

@ -21,90 +21,85 @@
*/ */
package com.farsunset.cim.sdk.android.constant; package com.farsunset.cim.sdk.android.constant;
/** /**
* 常量 * 常量
*/ */
public interface CIMConstant { public interface CIMConstant {
long RECONN_INTERVAL_TIME= 30 * 1000; long RECONN_INTERVAL_TIME = 30 * 1000;
//消息头长度为3个字节第一个字节为消息类型第二第三字节 转换int后为消息长度 // 消息头长度为3个字节第一个字节为消息类型第二第三字节 转换int后为消息长度
int DATA_HEADER_LENGTH = 3; int DATA_HEADER_LENGTH = 3;
public static interface ReturnCode{
public static interface ReturnCode {
String CODE_404 ="404";
String CODE_404 = "404";
String CODE_403 ="403";
String CODE_403 = "403";
String CODE_405 ="405";
String CODE_405 = "405";
String CODE_200 ="200";
String CODE_200 = "200";
String CODE_206 ="206";
String CODE_206 = "206";
String CODE_500 ="500";
String CODE_500 = "500";
} }
public static interface ProtobufType {
byte C_H_RS = 0;
byte S_H_RQ = 1;
byte MESSAGE = 2;
byte SENTBODY = 3;
byte REPLYBODY = 4;
}
public static interface RequestKey {
String CLIENT_BIND = "client_bind";
String CLIENT_LOGOUT = "client_logout";
public static interface ProtobufType{
byte C_H_RS = 0;
byte S_H_RQ = 1;
byte MESSAGE = 2;
byte SENTBODY = 3;
byte REPLYBODY = 4;
}
public static interface RequestKey{
String CLIENT_BIND ="client_bind";
String CLIENT_LOGOUT ="client_logout";
@Deprecated @Deprecated
String CLIENT_PULL_MESSAGE ="client_pull_message"; String CLIENT_PULL_MESSAGE = "client_pull_message";
} }
public static interface MessageAction {
public static interface MessageAction{
// 被其他设备登录挤下线消息
//被其他设备登录挤下线消息 String ACTION_999 = "999";
String ACTION_999 ="999"; }
}
public static interface IntentAction {
public static interface IntentAction{ // 消息广播action
String ACTION_MESSAGE_RECEIVED = "com.farsunset.cim.MESSAGE_RECEIVED";
// 消息广播action
String ACTION_MESSAGE_RECEIVED = "com.farsunset.cim.MESSAGE_RECEIVED"; // 发送sendbody失败广播
String ACTION_SENT_FAILED = "com.farsunset.cim.SENT_FAILED";
// 发送sendbody失败广播
String ACTION_SENT_FAILED = "com.farsunset.cim.SENT_FAILED"; // 发送sendbody成功广播
String ACTION_SENT_SUCCESSED = "com.farsunset.cim.SENT_SUCCESSED";
// 发送sendbody成功广播
String ACTION_SENT_SUCCESSED = "com.farsunset.cim.SENT_SUCCESSED"; // 链接意外关闭广播
String ACTION_CONNECTION_CLOSED = "com.farsunset.cim.CONNECTION_CLOSED";
// 链接意外关闭广播
String ACTION_CONNECTION_CLOSED = "com.farsunset.cim.CONNECTION_CLOSED"; // 链接失败广播
String ACTION_CONNECTION_FAILED = "com.farsunset.cim.CONNECTION_FAILED";
// 链接失败广播
String ACTION_CONNECTION_FAILED = "com.farsunset.cim.CONNECTION_FAILED"; // 链接成功广播
String ACTION_CONNECTION_SUCCESSED = "com.farsunset.cim.CONNECTION_SUCCESSED";
// 链接成功广播
String ACTION_CONNECTION_SUCCESSED = "com.farsunset.cim.CONNECTION_SUCCESSED"; // 发送sendbody成功后获得replaybody回应广播
String ACTION_REPLY_RECEIVED = "com.farsunset.cim.REPLY_RECEIVED";
// 发送sendbody成功后获得replaybody回应广播
String ACTION_REPLY_RECEIVED = "com.farsunset.cim.REPLY_RECEIVED"; // 网络变化广播
String ACTION_NETWORK_CHANGED = "android.net.conn.CONNECTIVITY_CHANGE";
// 网络变化广播
String ACTION_NETWORK_CHANGED = "android.net.conn.CONNECTIVITY_CHANGE"; // 重试连接
String ACTION_CONNECTION_RECOVERY = "com.farsunset.cim.CONNECTION_RECOVERY";
//重试连接 }
String ACTION_CONNECTION_RECOVERY = "com.farsunset.cim.CONNECTION_RECOVERY";
}
} }

View File

@ -23,14 +23,14 @@ package com.farsunset.cim.sdk.android.exception;
import java.io.Serializable; import java.io.Serializable;
public class NetworkDisabledException extends Exception implements Serializable { public class NetworkDisabledException extends Exception implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public NetworkDisabledException() { public NetworkDisabledException() {
super(); super();
} }
public NetworkDisabledException(String s) { public NetworkDisabledException(String s) {
super(s); super(s);
} }

View File

@ -24,7 +24,7 @@ package com.farsunset.cim.sdk.android.exception;
import java.io.Serializable; import java.io.Serializable;
public class SessionClosedException extends Exception implements Serializable { public class SessionClosedException extends Exception implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public SessionClosedException() { public SessionClosedException() {

View File

@ -26,7 +26,7 @@ import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder; import org.apache.mina.filter.codec.ProtocolEncoder;
/** /**
* android客户端端消息 编码解码器 * android客户端端消息 编码解码器
*/ */
public class ClientMessageCodecFactory implements ProtocolCodecFactory { public class ClientMessageCodecFactory implements ProtocolCodecFactory {
@ -34,23 +34,23 @@ public class ClientMessageCodecFactory implements ProtocolCodecFactory {
/** /**
* 消息编码器 * 消息编码器
*/ */
private final ClientMessageEncoder encoder; private final ClientMessageEncoder encoder;
/** /**
* 消息解码器 * 消息解码器
*/ */
private final ClientMessageDecoder decoder; private final ClientMessageDecoder decoder;
public ClientMessageCodecFactory() {
public ClientMessageCodecFactory() { encoder = new ClientMessageEncoder();
encoder = new ClientMessageEncoder(); decoder = new ClientMessageDecoder();
decoder = new ClientMessageDecoder(); }
}
public ProtocolEncoder getEncoder(IoSession session) throws Exception {
public ProtocolEncoder getEncoder(IoSession session) throws Exception { return encoder;
return encoder; }
}
public ProtocolDecoder getDecoder(IoSession session) throws Exception { public ProtocolDecoder getDecoder(IoSession session) throws Exception {
return decoder; return decoder;
} }
} }

View File

@ -21,7 +21,6 @@
*/ */
package com.farsunset.cim.sdk.android.filter; package com.farsunset.cim.sdk.android.filter;
import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder; import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
@ -35,79 +34,73 @@ import com.farsunset.cim.sdk.android.model.ReplyBody;
import com.farsunset.cim.sdk.android.model.proto.MessageProto; import com.farsunset.cim.sdk.android.model.proto.MessageProto;
import com.farsunset.cim.sdk.android.model.proto.ReplyBodyProto; import com.farsunset.cim.sdk.android.model.proto.ReplyBodyProto;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
/** /**
* 客户端消息解码 * 客户端消息解码
*/ */
public class ClientMessageDecoder extends CumulativeProtocolDecoder { public class ClientMessageDecoder extends CumulativeProtocolDecoder {
final static String TAG = ClientMessageDecoder.class.getSimpleName(); final static String TAG = ClientMessageDecoder.class.getSimpleName();
@Override @Override
public boolean doDecode(IoSession iosession, IoBuffer iobuffer, public boolean doDecode(IoSession iosession, IoBuffer iobuffer, ProtocolDecoderOutput out) throws Exception {
ProtocolDecoderOutput out) throws Exception {
/**
* 消息头3位
*/
if (iobuffer.remaining() < CIMConstant.DATA_HEADER_LENGTH) {
return false;
}
iobuffer.mark();
byte conetnType = iobuffer.get();
byte lv = iobuffer.get();// int 低位
byte hv = iobuffer.get();// int 高位
int conetnLength = getContentLength(lv, hv);
// 如果消息体没有接收完整则重置读取等待下一次重新读取
if (conetnLength > iobuffer.remaining()) {
iobuffer.reset();
return false;
}
byte[] dataBytes = new byte[conetnLength];
iobuffer.get(dataBytes, 0, conetnLength);
Object message = mappingMessageObject(dataBytes, conetnType);
if (message != null) {
out.write(message);
}
/**
* 消息头3位
*/
if(iobuffer.remaining() < CIMConstant.DATA_HEADER_LENGTH){
return false;
}
iobuffer.mark();
byte conetnType = iobuffer.get();
byte lv =iobuffer.get();//int 低位
byte hv =iobuffer.get();//int 高位
int conetnLength = getContentLength(lv,hv);
//如果消息体没有接收完整则重置读取等待下一次重新读取
if(conetnLength > iobuffer.remaining()){
iobuffer.reset();
return false;
}
byte[] dataBytes = new byte[conetnLength];
iobuffer.get(dataBytes, 0, conetnLength);
Object message = mappingMessageObject(dataBytes,conetnType);
if(message!=null){
out.write(message);
}
return true; return true;
} }
private Object mappingMessageObject(byte[] bytes,byte type) throws InvalidProtocolBufferException { private Object mappingMessageObject(byte[] bytes, byte type) throws InvalidProtocolBufferException {
if (CIMConstant.ProtobufType.S_H_RQ == type) {
if(CIMConstant.ProtobufType.S_H_RQ == type)
{
HeartbeatRequest request = HeartbeatRequest.getInstance(); HeartbeatRequest request = HeartbeatRequest.getInstance();
Log.i(TAG,request.toString()); Log.i(TAG, request.toString());
return request; return request;
} }
if(CIMConstant.ProtobufType.REPLYBODY == type) if (CIMConstant.ProtobufType.REPLYBODY == type) {
{
ReplyBodyProto.Model bodyProto = ReplyBodyProto.Model.parseFrom(bytes); ReplyBodyProto.Model bodyProto = ReplyBodyProto.Model.parseFrom(bytes);
ReplyBody body = new ReplyBody(); ReplyBody body = new ReplyBody();
body.setKey(bodyProto.getKey()); body.setKey(bodyProto.getKey());
body.setTimestamp(bodyProto.getTimestamp()); body.setTimestamp(bodyProto.getTimestamp());
body.putAll(bodyProto.getDataMap()); body.putAll(bodyProto.getDataMap());
body.setCode(bodyProto.getCode()); body.setCode(bodyProto.getCode());
body.setMessage(bodyProto.getMessage()); body.setMessage(bodyProto.getMessage());
Log.i(TAG,body.toString()); Log.i(TAG, body.toString());
return body; return body;
} }
if(CIMConstant.ProtobufType.MESSAGE == type) if (CIMConstant.ProtobufType.MESSAGE == type) {
{
MessageProto.Model bodyProto = MessageProto.Model.parseFrom(bytes); MessageProto.Model bodyProto = MessageProto.Model.parseFrom(bytes);
Message message = new Message(); Message message = new Message();
message.setMid(bodyProto.getMid()); message.setMid(bodyProto.getMid());
@ -119,25 +112,26 @@ public class ClientMessageDecoder extends CumulativeProtocolDecoder {
message.setExtra(bodyProto.getExtra()); message.setExtra(bodyProto.getExtra());
message.setTimestamp(bodyProto.getTimestamp()); message.setTimestamp(bodyProto.getTimestamp());
message.setFormat(bodyProto.getFormat()); message.setFormat(bodyProto.getFormat());
Log.i(TAG,message.toString()); Log.i(TAG, message.toString());
return message; return message;
} }
return null; return null;
} }
/** /**
* 解析消息体长度 * 解析消息体长度
*
* @param type * @param type
* @param length * @param length
* @return * @return
*/ */
private int getContentLength(byte lv,byte hv){ private int getContentLength(byte lv, byte hv) {
int l = (lv & 0xff); int l = (lv & 0xff);
int h = (hv & 0xff); int h = (hv & 0xff);
return (l| (h <<= 8)); return (l | (h <<= 8));
} }
} }

View File

@ -29,45 +29,48 @@ import android.util.Log;
import com.farsunset.cim.sdk.android.constant.CIMConstant; import com.farsunset.cim.sdk.android.constant.CIMConstant;
import com.farsunset.cim.sdk.android.model.Protobufable; import com.farsunset.cim.sdk.android.model.Protobufable;
/** /**
* 客户端消息发送前进行编码 * 客户端消息发送前进行编码
*/ */
public class ClientMessageEncoder extends ProtocolEncoderAdapter { public class ClientMessageEncoder extends ProtocolEncoderAdapter {
final static String TAG = ClientMessageEncoder.class.getSimpleName(); final static String TAG = ClientMessageEncoder.class.getSimpleName();
@Override @Override
public void encode(IoSession iosession, Object object, ProtocolEncoderOutput out) throws Exception { public void encode(IoSession iosession, Object object, ProtocolEncoderOutput out) throws Exception {
if(object instanceof Protobufable){ if (object instanceof Protobufable) {
Protobufable data = (Protobufable) object; Protobufable data = (Protobufable) object;
byte[] byteArray = data.getByteArray(); byte[] byteArray = data.getByteArray();
IoBuffer buff = IoBuffer.allocate(byteArray.length + CIMConstant.DATA_HEADER_LENGTH).setAutoExpand(true); IoBuffer buff = IoBuffer.allocate(byteArray.length + CIMConstant.DATA_HEADER_LENGTH).setAutoExpand(true);
buff.put(createHeader(data.getType(),byteArray.length)); buff.put(createHeader(data.getType(), byteArray.length));
buff.put(byteArray); buff.put(byteArray);
buff.flip(); buff.flip();
out.write(buff); out.write(buff);
//打印出收到的消息 // 打印出收到的消息
Log.i(TAG,data.toString()); Log.i(TAG, data.toString());
} }
} }
/** /**
* 消息体最大为65535 * 消息体最大为65535
*
* @param type * @param type
* @param length * @param length
* @return * @return
*/ */
private byte[] createHeader(byte type,int length){ private byte[] createHeader(byte type, int length) {
byte[] header = new byte[CIMConstant.DATA_HEADER_LENGTH]; byte[] header = new byte[CIMConstant.DATA_HEADER_LENGTH];
header[0] = type; header[0] = type;
header[1] = (byte) (length & 0xff); header[1] = (byte) (length & 0xff);
header[2] = (byte) ((length >> 8) & 0xff); header[2] = (byte) ((length >> 8) & 0xff);
return header; return header;
} }
} }

View File

@ -24,39 +24,39 @@ package com.farsunset.cim.sdk.android.model;
import java.io.Serializable; import java.io.Serializable;
import com.farsunset.cim.sdk.android.constant.CIMConstant; import com.farsunset.cim.sdk.android.constant.CIMConstant;
/** /**
* 服务端心跳请求 * 服务端心跳请求
* *
*/ */
public class HeartbeatRequest implements Serializable,Protobufable { public class HeartbeatRequest implements Serializable, Protobufable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final String TAG = "SERVER_HEARTBEAT_REQUEST"; private static final String TAG = "SERVER_HEARTBEAT_REQUEST";
private static final String CMD_HEARTBEAT_REQUEST = "SR"; private static final String CMD_HEARTBEAT_REQUEST = "SR";
private static HeartbeatRequest object = new HeartbeatRequest(); private static HeartbeatRequest object = new HeartbeatRequest();
private HeartbeatRequest(){ private HeartbeatRequest() {
} }
public static HeartbeatRequest getInstance() { public static HeartbeatRequest getInstance() {
return object; return object;
} }
@Override @Override
public byte[] getByteArray() { public byte[] getByteArray() {
return CMD_HEARTBEAT_REQUEST.getBytes(); return CMD_HEARTBEAT_REQUEST.getBytes();
} }
public String toString(){ public String toString() {
return TAG; return TAG;
} }
@Override @Override
public byte getType() { public byte getType() {
return CIMConstant.ProtobufType.S_H_RQ; return CIMConstant.ProtobufType.S_H_RQ;
} }
} }

View File

@ -24,30 +24,32 @@ package com.farsunset.cim.sdk.android.model;
import java.io.Serializable; import java.io.Serializable;
import com.farsunset.cim.sdk.android.constant.CIMConstant; import com.farsunset.cim.sdk.android.constant.CIMConstant;
/** /**
* 客户端心跳响应 * 客户端心跳响应
*/ */
public class HeartbeatResponse implements Serializable,Protobufable { public class HeartbeatResponse implements Serializable, Protobufable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final String TAG = "CLIENT_HEARTBEAT_RESPONSE"; private static final String TAG = "CLIENT_HEARTBEAT_RESPONSE";
private static final String CMD_HEARTBEAT_RESPONSE = "CR"; private static final String CMD_HEARTBEAT_RESPONSE = "CR";
private static HeartbeatResponse object = new HeartbeatResponse(); private static HeartbeatResponse object = new HeartbeatResponse();
private HeartbeatResponse(){ private HeartbeatResponse() {
} }
public static HeartbeatResponse getInstance() { public static HeartbeatResponse getInstance() {
return object; return object;
} }
@Override @Override
public byte[] getByteArray() { public byte[] getByteArray() {
return CMD_HEARTBEAT_RESPONSE.getBytes(); return CMD_HEARTBEAT_RESPONSE.getBytes();
} }
public String toString(){ public String toString() {
return TAG; return TAG;
} }
@ -55,5 +57,5 @@ public class HeartbeatResponse implements Serializable,Protobufable {
public byte getType() { public byte getType() {
return CIMConstant.ProtobufType.C_H_RS; return CIMConstant.ProtobufType.C_H_RS;
} }
} }

View File

@ -30,13 +30,11 @@ public class Message implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 消息类型用户自定义消息类别 * 消息类型用户自定义消息类别
*/ */
private String mid; private String mid;
/** /**
* 消息类型用户自定义消息类别 * 消息类型用户自定义消息类别
*/ */
@ -59,8 +57,6 @@ public class Message implements Serializable {
*/ */
private String receiver; private String receiver;
/** /**
* content 内容格式 * content 内容格式
*/ */
@ -72,12 +68,11 @@ public class Message implements Serializable {
private String extra; private String extra;
private long timestamp; private long timestamp;
public Message() {
public Message()
{
timestamp = System.currentTimeMillis(); timestamp = System.currentTimeMillis();
} }
public long getTimestamp() { public long getTimestamp() {
return timestamp; return timestamp;
} }
@ -86,14 +81,14 @@ public class Message implements Serializable {
this.timestamp = timestamp; this.timestamp = timestamp;
} }
public String getAction() { public String getAction() {
return action; return action;
} }
public void setAction(String action) { public void setAction(String action) {
this.action = action; this.action = action;
} }
public String getTitle() { public String getTitle() {
return title; return title;
} }
@ -126,7 +121,6 @@ public class Message implements Serializable {
this.receiver = receiver; this.receiver = receiver;
} }
public String getFormat() { public String getFormat() {
return format; return format;
} }
@ -134,17 +128,17 @@ public class Message implements Serializable {
public void setFormat(String format) { public void setFormat(String format) {
this.format = format; this.format = format;
} }
public String getExtra() { public String getExtra() {
return extra; return extra;
} }
public void setExtra(String extra) { public void setExtra(String extra) {
this.extra = extra; this.extra = extra;
} }
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("#Message#").append("\n"); buffer.append("#Message#").append("\n");
buffer.append("mid:").append(mid).append("\n"); buffer.append("mid:").append(mid).append("\n");
@ -158,7 +152,6 @@ public class Message implements Serializable {
buffer.append("timestamp:").append(timestamp); buffer.append("timestamp:").append(timestamp);
return buffer.toString(); return buffer.toString();
} }
public String getMid() { public String getMid() {
return mid; return mid;
@ -169,8 +162,7 @@ public class Message implements Serializable {
} }
public boolean isNotEmpty(String txt) { public boolean isNotEmpty(String txt) {
return txt != null && txt.trim().length()!=0; return txt != null && txt.trim().length() != 0;
} }
} }

View File

@ -20,12 +20,13 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.android.model; package com.farsunset.cim.sdk.android.model;
/** /**
* 需要向另一端发送的结构体 * 需要向另一端发送的结构体
*/ */
public interface Protobufable { public interface Protobufable {
byte[] getByteArray(); byte[] getByteArray();
byte getType(); byte getType();
} }

View File

@ -31,35 +31,31 @@ import java.util.Set;
* *
*/ */
public class ReplyBody implements Serializable { public class ReplyBody implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 请求key * 请求key
*/ */
private String key; private String key;
/** /**
* 返回码 * 返回码
*/ */
private String code; private String code;
/** /**
* 返回说明 * 返回说明
*/ */
private String message; private String message;
private long timestamp; private long timestamp;
/** /**
* 返回数据集合 * 返回数据集合
*/ */
private Hashtable<String, String> data = new Hashtable<String, String>(); private Hashtable<String, String> data = new Hashtable<String, String>();
public long getTimestamp() { public long getTimestamp() {
return timestamp; return timestamp;
} }
@ -68,8 +64,6 @@ public class ReplyBody implements Serializable {
this.timestamp = timestamp; this.timestamp = timestamp;
} }
public String getKey() { public String getKey() {
return key; return key;
} }
@ -101,8 +95,8 @@ public class ReplyBody implements Serializable {
public void putAll(Map<String, String> map) { public void putAll(Map<String, String> map) {
data.putAll(map); data.putAll(map);
} }
public Set<String> getKeySet() { public Set<String> getKeySet() {
return data.keySet(); return data.keySet();
} }
@ -114,24 +108,21 @@ public class ReplyBody implements Serializable {
this.code = code; this.code = code;
} }
public String toString() {
public String toString()
{
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("#ReplyBody#").append("\n"); buffer.append("#ReplyBody#").append("\n");
buffer.append("key:").append(this.getKey()).append("\n"); buffer.append("key:").append(this.getKey()).append("\n");
buffer.append("timestamp:").append(timestamp).append("\n"); buffer.append("timestamp:").append(timestamp).append("\n");
buffer.append("code:").append(code).append("\n"); buffer.append("code:").append(code).append("\n");
if(!data.isEmpty()){ if (!data.isEmpty()) {
buffer.append("data{").append("\n"); buffer.append("data{").append("\n");
for(String key:getKeySet()) for (String key : getKeySet()) {
{
buffer.append(key).append(":").append(this.get(key)).append("\n"); buffer.append(key).append(":").append(this.get(key)).append("\n");
} }
buffer.append("}"); buffer.append("}");
} }
return buffer.toString(); return buffer.toString();
} }

View File

@ -32,13 +32,13 @@ import com.farsunset.cim.sdk.android.model.proto.SentBodyProto;
* java |android 客户端请求结构 * java |android 客户端请求结构
* *
*/ */
public class SentBody implements Serializable,Protobufable { public class SentBody implements Serializable, Protobufable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private String key; private String key;
private Hashtable<String, String> data = new Hashtable<String, String>();; private Hashtable<String, String> data = new Hashtable<String, String>();;
private long timestamp; private long timestamp;
@ -67,18 +67,16 @@ public class SentBody implements Serializable,Protobufable {
} }
public void put(String k, String v) { public void put(String k, String v) {
if(k == null || v == null){ if (k == null || v == null) {
return; return;
} }
data.put(k, v); data.put(k, v);
} }
public Set<String> getKeySet() { public Set<String> getKeySet() {
return data.keySet(); return data.keySet();
} }
public void remove(String k) { public void remove(String k) {
data.remove(k); data.remove(k);
} }
@ -86,34 +84,34 @@ public class SentBody implements Serializable,Protobufable {
@Override @Override
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("#SentBody#").append("\n");; buffer.append("#SentBody#").append("\n");
;
buffer.append("key:").append(key).append("\n"); buffer.append("key:").append(key).append("\n");
buffer.append("timestamp:").append(timestamp).append("\n"); buffer.append("timestamp:").append(timestamp).append("\n");
if(!data.isEmpty()){ if (!data.isEmpty()) {
buffer.append("data{").append("\n"); buffer.append("data{").append("\n");
for(String key:getKeySet()) for (String key : getKeySet()) {
{
buffer.append(key).append(":").append(this.get(key)).append("\n"); buffer.append(key).append(":").append(this.get(key)).append("\n");
} }
buffer.append("}"); buffer.append("}");
} }
return buffer.toString(); return buffer.toString();
} }
@Override @Override
public byte[] getByteArray() { public byte[] getByteArray() {
SentBodyProto.Model.Builder builder = SentBodyProto.Model.newBuilder(); SentBodyProto.Model.Builder builder = SentBodyProto.Model.newBuilder();
builder.setKey(key); builder.setKey(key);
builder.setTimestamp(timestamp); builder.setTimestamp(timestamp);
if(!data.isEmpty()){ if (!data.isEmpty()) {
builder.putAllData(data); builder.putAllData(data);
} }
return builder.build().toByteArray(); return builder.build().toByteArray();
} }
@Override @Override
public byte getType() { public byte getType() {
return CIMConstant.ProtobufType.SENTBODY; return CIMConstant.ProtobufType.SENTBODY;
} }
} }

View File

@ -23,69 +23,58 @@ package com.farsunset.cim.sdk.client;
import java.util.HashMap; import java.util.HashMap;
class CIMCacheToolkit { class CIMCacheManager {
private static HashMap<String, String> CIM_CONFIG_INFO = new HashMap<String, String>();
private static HashMap<String,String> CIM_CONFIG_INFO = new HashMap<String,String>();
public static final String KEY_MANUAL_STOP = "KEY_MANUAL_STOP"; public static final String KEY_MANUAL_STOP = "KEY_MANUAL_STOP";
public static final String KEY_CIM_DESTROYED = "KEY_CIM_DESTROYED"; public static final String KEY_CIM_DESTROYED = "KEY_CIM_DESTROYED";
public static final String KEY_CIM_SERVIER_HOST = "KEY_CIM_SERVIER_HOST"; public static final String KEY_CIM_SERVIER_HOST = "KEY_CIM_SERVIER_HOST";
public static final String KEY_CIM_SERVIER_PORT = "KEY_CIM_SERVIER_PORT"; public static final String KEY_CIM_SERVIER_PORT = "KEY_CIM_SERVIER_PORT";
public static final String KEY_CIM_CONNECTION_STATE = "KEY_CIM_CONNECTION_STATE"; public static final String KEY_CIM_CONNECTION_STATE = "KEY_CIM_CONNECTION_STATE";
static CIMCacheToolkit toolkit; static CIMCacheManager toolkit;
public static CIMCacheToolkit getInstance(){
if (toolkit==null){ public static CIMCacheManager getInstance() {
toolkit = new CIMCacheToolkit(); if (toolkit == null) {
} toolkit = new CIMCacheManager();
}
return toolkit; return toolkit;
} }
public void remove(String key) {
public void remove(String key)
{
CIM_CONFIG_INFO.remove(key); CIM_CONFIG_INFO.remove(key);
} }
public void putString(String key, String value) {
public void putString(String key,String value) CIM_CONFIG_INFO.put(key, value);
{
CIM_CONFIG_INFO.put(key,value);
} }
public String getString(String key) public String getString(String key) {
{
return CIM_CONFIG_INFO.get(key); return CIM_CONFIG_INFO.get(key);
} }
public void putBoolean(String key,boolean value) public void putBoolean(String key, boolean value) {
{ putString(key, Boolean.toString(value));
putString(key,Boolean.toString(value));
} }
public boolean getBoolean(String key) public boolean getBoolean(String key) {
{
String value = getString(key); String value = getString(key);
return value == null?false:Boolean.parseBoolean(value); return value == null ? false : Boolean.parseBoolean(value);
} }
public void putInt(String key, int value) {
public void putInt(String key,int value)
{
putString(key, String.valueOf(value)); putString(key, String.valueOf(value));
} }
public int getInt(String key) public int getInt(String key) {
{
String value = getString(key); String value = getString(key);
return value == null?0:Integer.parseInt(value); return value == null ? 0 : Integer.parseInt(value);
} }
} }

View File

@ -20,6 +20,7 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.client; package com.farsunset.cim.sdk.client;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
@ -46,31 +47,28 @@ import com.farsunset.cim.sdk.client.model.Intent;
import com.farsunset.cim.sdk.client.model.Message; import com.farsunset.cim.sdk.client.model.Message;
import com.farsunset.cim.sdk.client.model.ReplyBody; import com.farsunset.cim.sdk.client.model.ReplyBody;
import com.farsunset.cim.sdk.client.model.SentBody; import com.farsunset.cim.sdk.client.model.SentBody;
/** /**
* 连接服务端管理cim核心处理类管理连接以及消息处理 * 连接服务端管理cim核心处理类管理连接以及消息处理
* *
* @author 3979434@qq.com * @author 3979434@qq.com
*/ */
class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFactory { class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFactory {
protected final Logger logger = Logger.getLogger(CIMConnectorManager.class); protected final Logger logger = Logger.getLogger(CIMConnectorManager.class);
private final int READ_BUFFER_SIZE = 2048;//bit private final int READ_BUFFER_SIZE = 2048;// bit
private final int CONNECT_TIMEOUT = 10 * 1000;// private final int CONNECT_TIMEOUT = 10 * 1000;//
private final int WRITE_TIMEOUT = 10 * 1000;// private final int WRITE_TIMEOUT = 10 * 1000;//
private final int READ_IDLE_TIME = 120;// private final int READ_IDLE_TIME = 120;//
private final int HEARBEAT_TIME_OUT = (READ_IDLE_TIME + 20) * 1000;// 收到服务端心跳请求超时时间 毫秒 private final int HEARBEAT_TIME_OUT = (READ_IDLE_TIME + 20) * 1000;// 收到服务端心跳请求超时时间 毫秒
private final String KEY_LAST_HEART_TIME = "KEY_LAST_HEART_TIME" ; private final String KEY_LAST_HEART_TIME = "KEY_LAST_HEART_TIME";
private NioSocketConnector connector; private NioSocketConnector connector;
private ConnectFuture connectFuture; private ConnectFuture connectFuture;
private ExecutorService executor = Executors.newFixedThreadPool(1); private ExecutorService executor = Executors.newFixedThreadPool(1);
private static CIMConnectorManager manager;
private static CIMConnectorManager manager;
private CIMConnectorManager() { private CIMConnectorManager() {
connector = new NioSocketConnector(); connector = new NioSocketConnector();
@ -78,15 +76,15 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageF
connector.getSessionConfig().setTcpNoDelay(true); connector.getSessionConfig().setTcpNoDelay(true);
connector.getSessionConfig().setKeepAlive(true); connector.getSessionConfig().setKeepAlive(true);
connector.getSessionConfig().setReadBufferSize(READ_BUFFER_SIZE); connector.getSessionConfig().setReadBufferSize(READ_BUFFER_SIZE);
KeepAliveFilter keepAliveaHandler = new KeepAliveFilter(this); KeepAliveFilter keepAliveaHandler = new KeepAliveFilter(this);
keepAliveaHandler.setRequestInterval(READ_IDLE_TIME); keepAliveaHandler.setRequestInterval(READ_IDLE_TIME);
keepAliveaHandler.setRequestTimeoutHandler(KeepAliveRequestTimeoutHandler.NOOP); keepAliveaHandler.setRequestTimeoutHandler(KeepAliveRequestTimeoutHandler.NOOP);
keepAliveaHandler.setForwardEvent(true); keepAliveaHandler.setForwardEvent(true);
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ClientMessageCodecFactory())); connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ClientMessageCodecFactory()));
connector.getFilterChain().addLast("heartbeat", keepAliveaHandler); connector.getFilterChain().addLast("heartbeat", keepAliveaHandler);
connector.setHandler(this); connector.setHandler(this);
} }
@ -99,75 +97,74 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageF
} }
private synchronized void syncConnection(final String host,final int port) { private synchronized void syncConnection(final String host, final int port) {
if(isConnected()){ if (isConnected()) {
return ; return;
} }
try { try {
logger.info("****************CIM正在连接服务器 "+host+":"+port+"......"); logger.info("****************CIM正在连接服务器 " + host + ":" + port + "......");
CIMCacheToolkit.getInstance().putBoolean(CIMCacheToolkit.KEY_CIM_CONNECTION_STATE, false); CIMCacheManager.getInstance().putBoolean(CIMCacheManager.KEY_CIM_CONNECTION_STATE, false);
InetSocketAddress remoteSocketAddress = new InetSocketAddress(host, port); InetSocketAddress remoteSocketAddress = new InetSocketAddress(host, port);
connectFuture = connector.connect(remoteSocketAddress); connectFuture = connector.connect(remoteSocketAddress);
connectFuture.awaitUninterruptibly(); connectFuture.awaitUninterruptibly();
connectFuture.getSession(); connectFuture.getSession();
} catch (Exception e) { } catch (Exception e) {
long interval = CIMConstant.RECONN_INTERVAL_TIME - (5*1000 - new Random().nextInt(15*1000)); long interval = CIMConstant.RECONN_INTERVAL_TIME - (5 * 1000 - new Random().nextInt(15 * 1000));
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED); intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED);
intent.putExtra(Exception.class.getName(), e); intent.putExtra(Exception.class.getName(), e);
intent.putExtra("interval", interval); intent.putExtra("interval", interval);
sendBroadcast(intent); sendBroadcast(intent);
logger.error("****************CIM连接服务器失败 "+host+":"+port+"......将在"+interval/1000+"秒后重新尝试连接"); logger.error(
"****************CIM连接服务器失败 " + host + ":" + port + "......将在" + interval / 1000 + "秒后重新尝试连接");
}
}
} }
public void connect(final String host, final int port) { public void connect(final String host, final int port) {
executor.execute(new Runnable() { executor.execute(new Runnable() {
public void run() public void run() {
{
syncConnection(host, port); syncConnection(host, port);
} }
}); });
} }
public synchronized void send(SentBody body) { public synchronized void send(SentBody body) {
boolean isSuccessed = false; boolean isSuccessed = false;
Throwable exception = new SessionDisconnectedException(); Throwable exception = new SessionDisconnectedException();
IoSession session = getCurrentSession(); IoSession session = getCurrentSession();
if(session!=null && session.isConnected()) if (session != null && session.isConnected()) {
{
WriteFuture wf = session.write(body); WriteFuture wf = session.write(body);
// 消息发送超时 5秒 // 消息发送超时 5秒
wf.awaitUninterruptibly(WRITE_TIMEOUT); wf.awaitUninterruptibly(WRITE_TIMEOUT);
isSuccessed = wf.isWritten(); isSuccessed = wf.isWritten();
exception = wf.getException(); exception = wf.getException();
} }
if(!isSuccessed){ if (!isSuccessed) {
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_SENT_FAILED); intent.setAction(CIMConstant.IntentAction.ACTION_SENT_FAILED);
intent.putExtra(Exception.class.getName(),exception); intent.putExtra(Exception.class.getName(), exception);
intent.putExtra(SentBody.class.getName(), body); intent.putExtra(SentBody.class.getName(), body);
sendBroadcast(intent); sendBroadcast(intent);
} }
} }
public void destroy() { public void destroy() {
IoSession session = getCurrentSession(); IoSession session = getCurrentSession();
if (session != null) { if (session != null) {
session.closeNow(); session.closeNow();
@ -176,59 +173,51 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageF
if (connector != null && !connector.isDisposed()) { if (connector != null && !connector.isDisposed()) {
connector.dispose(); connector.dispose();
} }
manager = null; manager = null;
} }
public boolean isConnected() { public boolean isConnected() {
IoSession session = getCurrentSession(); IoSession session = getCurrentSession();
return session != null ; return session != null;
} }
public void closeSession() {
public void closeSession()
{
IoSession session = getCurrentSession(); IoSession session = getCurrentSession();
if(session!=null) if (session != null) {
{
session.closeNow(); session.closeNow();
} }
} }
public IoSession getCurrentSession() public IoSession getCurrentSession() {
{ Map<Long, IoSession> sessions = connector.getManagedSessions();
Map<Long,IoSession> sessions = connector.getManagedSessions(); for (Long key : sessions.keySet()) {
for(Long key:sessions.keySet())
{
IoSession session = sessions.get(key); IoSession session = sessions.get(key);
if(session.isConnected()){ if (session.isConnected()) {
return session; return session;
} }
} }
return null; return null;
} }
@Override @Override
public void sessionCreated(IoSession session) throws Exception { public void sessionCreated(IoSession session) throws Exception {
logger.info("****************CIM连接服务器成功:" + session.getLocalAddress() + " NID:" + session.getId());
logger.info("****************CIM连接服务器成功:"+session.getLocalAddress()+" NID:"+session.getId());
setLastHeartbeatTime(session); setLastHeartbeatTime(session);
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_SUCCESSED); intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_SUCCESSED);
sendBroadcast(intent); sendBroadcast(intent);
} }
@Override @Override
public void sessionClosed(IoSession session) { public void sessionClosed(IoSession session) {
logger.error("****************CIM与服务器断开连接:"+session.getLocalAddress()+" NID:"+session.getId()); logger.error("****************CIM与服务器断开连接:" + session.getLocalAddress() + " NID:" + session.getId());
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED); intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED);
sendBroadcast(intent); sendBroadcast(intent);
@ -236,31 +225,30 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageF
} }
@Override @Override
public void sessionIdle(IoSession session, IdleStatus status) { public void sessionIdle(IoSession session, IdleStatus status) {
logger.debug("****************CIM "+status.toString().toUpperCase()+":"+session.getLocalAddress() +" NID:"+session.getId()+ " isConnected:" + session.isConnected()); logger.debug("****************CIM " + status.toString().toUpperCase() + ":" + session.getLocalAddress()
+ " NID:" + session.getId() + " isConnected:" + session.isConnected());
/** /**
* 用于解决wifi情况下偶而路由器与服务器断开连接时客户端并没及时收到关闭事件 * 用于解决wifi情况下偶而路由器与服务器断开连接时客户端并没及时收到关闭事件 导致这样的情况下当前连接无效也不会重连的问题
* 导致这样的情况下当前连接无效也不会重连的问题
* *
*/ */
long lastHeartbeatTime = getLastHeartbeatTime(session); long lastHeartbeatTime = getLastHeartbeatTime(session);
if(System.currentTimeMillis() - lastHeartbeatTime >= HEARBEAT_TIME_OUT) if (System.currentTimeMillis() - lastHeartbeatTime >= HEARBEAT_TIME_OUT) {
{
session.closeNow(); session.closeNow();
logger.error("****************CIM心跳超时 ,即将重新连接......"+" NID:"+session.getId()); logger.error("****************CIM心跳超时 ,即将重新连接......" + " NID:" + session.getId());
} }
} }
@Override @Override
public void exceptionCaught(IoSession session, Throwable cause) { public void exceptionCaught(IoSession session, Throwable cause) {
logger.error("****************CIM连接出现未知异常:"+session.getLocalAddress()+" NID:"+session.getId()); logger.error("****************CIM连接出现未知异常:" + session.getLocalAddress() + " NID:" + session.getId());
if(cause!=null && cause.getMessage()!=null){ if (cause != null && cause.getMessage() != null) {
logger.error(cause.getMessage()); logger.error(cause.getMessage());
} }
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_UNCAUGHT_EXCEPTION); intent.setAction(CIMConstant.IntentAction.ACTION_UNCAUGHT_EXCEPTION);
intent.putExtra(Exception.class.getName(), cause); intent.putExtra(Exception.class.getName(), cause);
@ -268,18 +256,18 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageF
} }
@Override @Override
public void messageReceived(IoSession session, Object obj){ public void messageReceived(IoSession session, Object obj) {
if (obj instanceof Message) { if (obj instanceof Message) {
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED); intent.setAction(CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED);
intent.putExtra(Message.class.getName(), (Message) obj); intent.putExtra(Message.class.getName(), (Message) obj);
sendBroadcast(intent); sendBroadcast(intent);
} }
if (obj instanceof ReplyBody) { if (obj instanceof ReplyBody) {
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_REPLY_RECEIVED); intent.setAction(CIMConstant.IntentAction.ACTION_REPLY_RECEIVED);
intent.putExtra(ReplyBody.class.getName(), (ReplyBody) obj); intent.putExtra(ReplyBody.class.getName(), (ReplyBody) obj);
@ -289,32 +277,27 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageF
@Override @Override
public void messageSent(IoSession session, Object message) { public void messageSent(IoSession session, Object message) {
if(message instanceof SentBody) if (message instanceof SentBody) {
{
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_SENT_SUCCESSED); intent.setAction(CIMConstant.IntentAction.ACTION_SENT_SUCCESSED);
intent.putExtra(SentBody.class.getName(), (SentBody) message); intent.putExtra(SentBody.class.getName(), (SentBody) message);
sendBroadcast(intent); sendBroadcast(intent);
} }
} }
private void setLastHeartbeatTime(IoSession session) {
private void setLastHeartbeatTime(IoSession session)
{
session.setAttribute(KEY_LAST_HEART_TIME, System.currentTimeMillis()); session.setAttribute(KEY_LAST_HEART_TIME, System.currentTimeMillis());
} }
private long getLastHeartbeatTime(IoSession session) private long getLastHeartbeatTime(IoSession session) {
{
long time = 0; long time = 0;
Object value = session.getAttribute(KEY_LAST_HEART_TIME); Object value = session.getAttribute(KEY_LAST_HEART_TIME);
if(value !=null){ if (value != null) {
time = Long.parseLong(value.toString()); time = Long.parseLong(value.toString());
} }
return time; return time;
} }
@Override @Override
public Object getRequest(IoSession arg0) { public Object getRequest(IoSession arg0) {
return null; return null;
@ -327,9 +310,9 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageF
@Override @Override
public boolean isRequest(IoSession session, Object data) { public boolean isRequest(IoSession session, Object data) {
setLastHeartbeatTime(session); setLastHeartbeatTime(session);
return data instanceof HeartbeatRequest; return data instanceof HeartbeatRequest;
} }
@ -337,13 +320,13 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageF
public boolean isResponse(IoSession arg0, Object arg1) { public boolean isResponse(IoSession arg0, Object arg1) {
return false; return false;
} }
private void sendBroadcast(final Intent intent) { private void sendBroadcast(final Intent intent) {
executor.execute(new Runnable(){ executor.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
CIMEventBroadcastReceiver.getInstance().onReceive(intent); CIMEventBroadcastReceiver.getInstance().onReceive(intent);
} }
}); });
} }
} }

View File

@ -21,7 +21,6 @@
*/ */
package com.farsunset.cim.sdk.client; package com.farsunset.cim.sdk.client;
import java.util.Random; import java.util.Random;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
@ -32,171 +31,155 @@ import com.farsunset.cim.sdk.client.model.Intent;
import com.farsunset.cim.sdk.client.model.Message; import com.farsunset.cim.sdk.client.model.Message;
import com.farsunset.cim.sdk.client.model.ReplyBody; import com.farsunset.cim.sdk.client.model.ReplyBody;
import com.farsunset.cim.sdk.client.model.SentBody; import com.farsunset.cim.sdk.client.model.SentBody;
/** /**
* 消息入口所有消息都会经过这里 * 消息入口所有消息都会经过这里
*/ */
public class CIMEventBroadcastReceiver { public class CIMEventBroadcastReceiver {
Random random = new Random(); Random random = new Random();
private static CIMEventBroadcastReceiver recerver; private static CIMEventBroadcastReceiver recerver;
private CIMEventListener listener; private CIMEventListener listener;
private Timer connectionHandler = new Timer();; private Timer connectionHandler = new Timer();;
public static CIMEventBroadcastReceiver getInstance(){
if (recerver==null){ public static CIMEventBroadcastReceiver getInstance() {
recerver = new CIMEventBroadcastReceiver(); if (recerver == null) {
} recerver = new CIMEventBroadcastReceiver();
}
return recerver; return recerver;
} }
public void setGlobalCIMEventListener(CIMEventListener ls){ public void setGlobalCIMEventListener(CIMEventListener ls) {
listener = ls; listener = ls;
} }
public void onReceive(Intent intent) { public void onReceive(Intent intent) {
/*
/* * cim断开服务器事件
* cim断开服务器事件 */
*/ if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED)) {
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED)) onInnerConnectionClosed();
{ }
onInnerConnectionClosed();
} /*
* cim连接服务器失败事件
/* */
* cim连接服务器失败事件 if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED)) {
*/ long interval = intent.getLongExtra("interval", CIMConstant.RECONN_INTERVAL_TIME);
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED)) onInnerConnectionFailed((Exception) intent.getExtra(Exception.class.getName()), interval);
{ }
long interval = intent.getLongExtra("interval", CIMConstant.RECONN_INTERVAL_TIME);
onInnerConnectionFailed((Exception) intent.getExtra(Exception.class.getName()),interval); /*
} * cim连接服务器成功事件
*/
/* if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_SUCCESSED)) {
* cim连接服务器成功事件 onInnerConnectionSuccessed();
*/ }
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_SUCCESSED))
{ /*
onInnerConnectionSuccessed(); * 收到推送消息事件
} */
if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED)) {
/* onInnerMessageReceived((Message) intent.getExtra(Message.class.getName()));
* 收到推送消息事件 }
*/
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED)) /*
{ * 获取收到replybody成功事件
onInnerMessageReceived((Message)intent.getExtra(Message.class.getName())); */
} if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_REPLY_RECEIVED)) {
listener.onReplyReceived((ReplyBody) intent.getExtra(ReplyBody.class.getName()));
}
/*
* 获取收到replybody成功事件 /*
*/ * 获取sendbody发送失败事件
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_REPLY_RECEIVED)) */
{ if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_SENT_FAILED)) {
listener.onReplyReceived((ReplyBody)intent.getExtra(ReplyBody.class.getName())); onSentFailed((Exception) intent.getExtra(Exception.class.getName()),
} (SentBody) intent.getExtra(SentBody.class.getName()));
}
/* /*
* 获取sendbody发送失败事件 * 获取sendbody发送成功事件
*/ */
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_SENT_FAILED)) if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_SENT_SUCCESSED)) {
{ onSentSucceed((SentBody) intent.getExtra(SentBody.class.getName()));
onSentFailed((Exception) intent.getExtra(Exception.class.getName()),(SentBody)intent.getExtra(SentBody.class.getName())); }
}
/*
/* * 获取cim数据传输异常事件
* 获取sendbody发送成功事件 */
*/ if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_UNCAUGHT_EXCEPTION)) {
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_SENT_SUCCESSED)) onUncaughtException((Exception) intent.getExtra(Exception.class.getName()));
{ }
onSentSucceed((SentBody)intent.getExtra(SentBody.class.getName()));
} /*
* 重新连接如果断开的话
*/
/* if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_RECOVERY)) {
* 获取cim数据传输异常事件 CIMPushManager.connect();
*/ }
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_UNCAUGHT_EXCEPTION))
{
onUncaughtException((Exception)intent.getExtra(Exception.class.getName()));
}
/*
* 重新连接如果断开的话
*/
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_RECOVERY))
{
CIMPushManager.connect();
}
} }
private void onInnerConnectionClosed() {
private void onInnerConnectionClosed(){
listener.onConnectionClosed(); listener.onConnectionClosed();
CIMCacheToolkit.getInstance().putBoolean(CIMCacheToolkit.KEY_CIM_CONNECTION_STATE, false); CIMCacheManager.getInstance().putBoolean(CIMCacheManager.KEY_CIM_CONNECTION_STATE, false);
CIMPushManager.connect(); CIMPushManager.connect();
} }
private void onInnerConnectionFailed(Exception e, long interval) {
connectionHandler.schedule(new ConnectionTask(), interval);
private void onInnerConnectionFailed(Exception e,long interval){
listener.onConnectionFailed(e);
connectionHandler.schedule(new ConnectionTask(),interval);
listener.onConnectionFailed(e);
} }
private void onInnerConnectionSuccessed(){ private void onInnerConnectionSuccessed() {
CIMCacheToolkit.getInstance().putBoolean(CIMCacheToolkit.KEY_CIM_CONNECTION_STATE, true); CIMCacheManager.getInstance().putBoolean(CIMCacheManager.KEY_CIM_CONNECTION_STATE, true);
boolean autoBind = CIMPushManager.autoBindDeviceId(); boolean autoBind = CIMPushManager.autoBindDeviceId();
listener.onConnectionSuccessed(autoBind); listener.onConnectionSuccessed(autoBind);
} }
private void onUncaughtException(Throwable arg0) {} private void onUncaughtException(Throwable arg0) {
}
private void onInnerMessageReceived(com.farsunset.cim.sdk.client.model.Message message) {
if (isForceOfflineMessage(message.getAction())) {
CIMPushManager.stop();
}
private void onInnerMessageReceived(com.farsunset.cim.sdk.client.model.Message message)
{
listener.onMessageReceived(message); listener.onMessageReceived(message);
} }
private void onSentFailed(Exception e, SentBody body){ private boolean isForceOfflineMessage(String action) {
return CIMConstant.MessageAction.ACTION_999.equals(action);
e.printStackTrace();
//与服务端端开链接重新连接
if(e instanceof SessionDisconnectedException)
{
CIMPushManager.connect();
}else
{
//发送失败 重新发送
//CIMPushManager.sendRequest( body);
}
} }
private void onSentSucceed(SentBody body){} private void onSentFailed(Exception e, SentBody body) {
e.printStackTrace();
// 与服务端端开链接重新连接
class ConnectionTask extends TimerTask{ if (e instanceof SessionDisconnectedException) {
CIMPushManager.connect();
public void run(){ } else {
// 发送失败 重新发送
CIMPushManager.sendRequest(body);
}
}
private void onSentSucceed(SentBody body) {
}
class ConnectionTask extends TimerTask {
public void run() {
CIMPushManager.connect(); CIMPushManager.connect();
} }
} }
} }

View File

@ -21,50 +21,49 @@
*/ */
package com.farsunset.cim.sdk.client; package com.farsunset.cim.sdk.client;
import com.farsunset.cim.sdk.client.model.Message; import com.farsunset.cim.sdk.client.model.Message;
import com.farsunset.cim.sdk.client.model.ReplyBody; import com.farsunset.cim.sdk.client.model.ReplyBody;
/** /**
*CIM 主要事件接口 * CIM 主要事件接口
*/ */
public interface CIMEventListener public interface CIMEventListener {
{
/**
* 当收到服务端推送过来的消息时调用
*
* @param message
*/
void onMessageReceived(Message message);
/** /**
* 当收到服务端推送过来的消息时调用 * 当调用CIMPushManager.sendRequest()向服务端发送请求获得相应时调用
* @param message *
*/ * @param replybody
void onMessageReceived(Message message); */
void onReplyReceived(ReplyBody replybody);
/** /**
* 当调用CIMPushManager.sendRequest()向服务端发送请求获得相应时调用 * 当连接服务器成功时回调
* @param replybody *
*/ * @param hasAutoBind
void onReplyReceived(ReplyBody replybody); * : true 已经自动绑定账号到服务器了不需要再手动调用bindAccount
*/
void onConnectionSuccessed(boolean hasAutoBind);
/**
/** * 当断开服务器连接的时候回调
* 当连接服务器成功时回调 */
* @param hasAutoBind : true 已经自动绑定账号到服务器了不需要再手动调用bindAccount void onConnectionClosed();
*/
void onConnectionSuccessed(boolean hasAutoBind); /**
* 当服务器连接失败的时候回调
/** *
* 当断开服务器连接的时候回调 */
*/ void onConnectionFailed(Exception e);
void onConnectionClosed();
/**
/** * 监听器在容器里面的排序值越大则越先接收
* 当服务器连接失败的时候回调 */
* int getEventDispatchOrder();
*/
void onConnectionFailed(Exception e);
/**
* 监听器在容器里面的排序值越大则越先接收
*/
int getEventDispatchOrder();
} }

View File

@ -20,6 +20,7 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.client; package com.farsunset.cim.sdk.client;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@ -29,26 +30,23 @@ import org.apache.log4j.Logger;
import com.farsunset.cim.sdk.client.model.Message; import com.farsunset.cim.sdk.client.model.Message;
import com.farsunset.cim.sdk.client.model.ReplyBody; import com.farsunset.cim.sdk.client.model.ReplyBody;
/** /**
* CIM 消息监听器管理 * CIM 消息监听器管理
*/ */
public class CIMListenerManager { public class CIMListenerManager {
private static ArrayList<CIMEventListener> cimListeners = new ArrayList<CIMEventListener>(); private static ArrayList<CIMEventListener> cimListeners = new ArrayList<CIMEventListener>();
private static CIMMessageReceiveComparator comparator = new CIMMessageReceiveComparator(); private static CIMMessageReceiveComparator comparator = new CIMMessageReceiveComparator();
protected static final Logger logger = Logger.getLogger(CIMListenerManager.class); protected static final Logger logger = Logger.getLogger(CIMListenerManager.class);
public static void registerMessageListener(CIMEventListener listener) { public static void registerMessageListener(CIMEventListener listener) {
if (!cimListeners.contains(listener)) { if (!cimListeners.contains(listener)) {
cimListeners.add(listener); cimListeners.add(listener);
Collections.sort(cimListeners,comparator); Collections.sort(cimListeners, comparator);
} }
} }
public static void removeMessageListener(CIMEventListener listener) { public static void removeMessageListener(CIMEventListener listener) {
for (int i = 0; i < cimListeners.size(); i++) { for (int i = 0; i < cimListeners.size(); i++) {
if (listener.getClass() == cimListeners.get(i).getClass()) { if (listener.getClass() == cimListeners.get(i).getClass()) {
@ -56,61 +54,60 @@ public class CIMListenerManager {
} }
} }
} }
public static void notifyOnConnectionSuccessed(boolean antoBind) { public static void notifyOnConnectionSuccessed(boolean antoBind) {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onConnectionSuccessed(antoBind); listener.onConnectionSuccessed(antoBind);
} }
} }
public static void notifyOnMessageReceived(Message message) { public static void notifyOnMessageReceived(Message message) {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onMessageReceived(message); listener.onMessageReceived(message);
} }
} }
public static void notifyOnConnectionClosed() { public static void notifyOnConnectionClosed() {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onConnectionClosed(); listener.onConnectionClosed();
} }
} }
public static void notifyOnReplyReceived(ReplyBody body) { public static void notifyOnReplyReceived(ReplyBody body) {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onReplyReceived(body); listener.onReplyReceived(body);
} }
} }
public static void notifyOnConnectionFailed(Exception e) { public static void notifyOnConnectionFailed(Exception e) {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onConnectionFailed(e); listener.onConnectionFailed(e);
} }
} }
public static void destory() { public static void destory() {
cimListeners.clear(); cimListeners.clear();
} }
public static void logListenersName() { public static void logListenersName() {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
logger.debug("#######" + listener.getClass().getName() + "#######" ); logger.debug("#######" + listener.getClass().getName() + "#######");
} }
} }
/** /**
* 消息接收activity的接收顺序排序CIM_RECEIVE_ORDER倒序 * 消息接收activity的接收顺序排序CIM_RECEIVE_ORDER倒序
*/ */
private static class CIMMessageReceiveComparator implements Comparator<CIMEventListener>{ private static class CIMMessageReceiveComparator implements Comparator<CIMEventListener> {
@Override @Override
public int compare(CIMEventListener arg1, CIMEventListener arg2) { public int compare(CIMEventListener arg1, CIMEventListener arg2) {
int order1 = arg1.getEventDispatchOrder(); int order1 = arg1.getEventDispatchOrder();
int order2 = arg2.getEventDispatchOrder(); int order2 = arg2.getEventDispatchOrder();
return order2 - order1 ; return order2 - order1;
} }
} }
} }

View File

@ -20,6 +20,7 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.client; package com.farsunset.cim.sdk.client;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.NetworkInterface; import java.net.NetworkInterface;
import java.util.Properties; import java.util.Properties;
@ -33,254 +34,246 @@ import com.farsunset.cim.sdk.client.model.SentBody;
/** /**
* CIM 功能接口 * CIM 功能接口
*/ */
public class CIMPushManager { public class CIMPushManager {
protected static final Logger logger = Logger.getLogger(CIMPushManager.class); protected static final Logger logger = Logger.getLogger(CIMPushManager.class);
static String ACTION_ACTIVATE_PUSH_SERVICE ="ACTION_ACTIVATE_PUSH_SERVICE"; static String ACTION_ACTIVATE_PUSH_SERVICE = "ACTION_ACTIVATE_PUSH_SERVICE";
static String ACTION_CREATE_CIM_CONNECTION ="ACTION_CREATE_CIM_CONNECTION"; static String ACTION_CREATE_CIM_CONNECTION = "ACTION_CREATE_CIM_CONNECTION";
static String ACTION_SEND_REQUEST_BODY ="ACTION_SEND_REQUEST_BODY"; static String ACTION_SEND_REQUEST_BODY = "ACTION_SEND_REQUEST_BODY";
static String ACTION_CLOSE_CIM_CONNECTION ="ACTION_CLOSE_CIM_CONNECTION"; static String ACTION_CLOSE_CIM_CONNECTION = "ACTION_CLOSE_CIM_CONNECTION";
static String ACTION_DESTORY ="ACTION_DESTORY"; static String ACTION_DESTORY = "ACTION_DESTORY";
static String KEY_CIM_CONNECTION_STATUS = "KEY_CIM_CONNECTION_STATUS";
static String KEY_CIM_CONNECTION_STATUS ="KEY_CIM_CONNECTION_STATUS";
// 被销毁的destroy()
//被销毁的destroy()
public static final int STATE_DESTROYED = 0x0000DE; public static final int STATE_DESTROYED = 0x0000DE;
//被销停止的 stop() // 被销停止的 stop()
public static final int STATE_STOPED = 0x0000EE; public static final int STATE_STOPED = 0x0000EE;
public static final int STATE_NORMAL = 0x000000; public static final int STATE_NORMAL = 0x000000;
/** /**
* 初始化,连接服务端在程序启动页或者 在Application里调用 * 初始化,连接服务端在程序启动页或者 在Application里调用
*
* @param context * @param context
* @param ip * @param ip
* @param port * @param port
*/ */
public static void connect(String ip,int port){ public static void connect(String ip, int port) {
CIMCacheToolkit.getInstance().putBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED, false); CIMCacheManager.getInstance().putBoolean(CIMCacheManager.KEY_CIM_DESTROYED, false);
CIMCacheToolkit.getInstance().putBoolean(CIMCacheToolkit.KEY_MANUAL_STOP, false); CIMCacheManager.getInstance().putBoolean(CIMCacheManager.KEY_MANUAL_STOP, false);
CIMCacheToolkit.getInstance().putString( CIMCacheToolkit.KEY_CIM_SERVIER_HOST, ip); CIMCacheManager.getInstance().putString(CIMCacheManager.KEY_CIM_SERVIER_HOST, ip);
CIMCacheToolkit.getInstance().putInt( CIMCacheToolkit.KEY_CIM_SERVIER_PORT, port); CIMCacheManager.getInstance().putInt(CIMCacheManager.KEY_CIM_SERVIER_PORT, port);
Intent serviceIntent = new Intent(); Intent serviceIntent = new Intent();
serviceIntent.putExtra(CIMCacheToolkit.KEY_CIM_SERVIER_HOST, ip); serviceIntent.putExtra(CIMCacheManager.KEY_CIM_SERVIER_HOST, ip);
serviceIntent.putExtra(CIMCacheToolkit.KEY_CIM_SERVIER_PORT, port); serviceIntent.putExtra(CIMCacheManager.KEY_CIM_SERVIER_PORT, port);
serviceIntent.setAction(ACTION_CREATE_CIM_CONNECTION); serviceIntent.setAction(ACTION_CREATE_CIM_CONNECTION);
startService(serviceIntent); startService(serviceIntent);
} }
private static void startService(Intent intent) { private static void startService(Intent intent) {
CIMPushService.getInstance().onStartCommand(intent); CIMPushService.getInstance().onStartCommand(intent);
}
protected static void connect(){
boolean isManualStop = CIMCacheToolkit.getInstance().getBoolean(CIMCacheToolkit.KEY_MANUAL_STOP);
boolean isManualDestory = CIMCacheToolkit.getInstance().getBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED);
if(isManualStop || isManualDestory)
{
return ;
}
String host = CIMCacheToolkit.getInstance().getString( CIMCacheToolkit.KEY_CIM_SERVIER_HOST);
int port =CIMCacheToolkit.getInstance().getInt( CIMCacheToolkit.KEY_CIM_SERVIER_PORT);
connect(host,port);
} }
protected static void connect() {
private static void sendBindRequest(String account){
boolean isManualStop = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_MANUAL_STOP);
CIMCacheToolkit.getInstance().putBoolean(CIMCacheToolkit.KEY_MANUAL_STOP, false); boolean isManualDestory = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
SentBody sent = new SentBody();
Properties sysPro=System.getProperties(); if (isManualStop || isManualDestory) {
return;
}
String host = CIMCacheManager.getInstance().getString(CIMCacheManager.KEY_CIM_SERVIER_HOST);
int port = CIMCacheManager.getInstance().getInt(CIMCacheManager.KEY_CIM_SERVIER_PORT);
connect(host, port);
}
private static void sendBindRequest(String account) {
CIMCacheManager.getInstance().putBoolean(CIMCacheManager.KEY_MANUAL_STOP, false);
SentBody sent = new SentBody();
Properties sysPro = System.getProperties();
sent.setKey(CIMConstant.RequestKey.CLIENT_BIND); sent.setKey(CIMConstant.RequestKey.CLIENT_BIND);
sent.put("account", account); sent.put("account", account);
sent.put("deviceId", getLocalMac()); sent.put("deviceId", getLocalMac());
sent.put("channel", sysPro.getProperty("os.name")); sent.put("channel", sysPro.getProperty("os.name"));
sent.put("device",getDeviceModel()); sent.put("device", getDeviceModel());
sent.put("version",getClientVersion()); sent.put("version", getClientVersion());
sent.put("osVersion",sysPro.getProperty("os.version")); sent.put("osVersion", sysPro.getProperty("os.version"));
sendRequest(sent); sendRequest(sent);
} }
/** /**
* 设置一个账号登录到服务端 * 设置一个账号登录到服务端
* @param account 用户唯一ID *
* @param account
* 用户唯一ID
*/ */
public static void bindAccount(String account){ public static void bindAccount(String account) {
boolean isManualDestory = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
boolean isManualDestory = CIMCacheToolkit.getInstance().getBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED); if (isManualDestory || account == null || account.trim().length() == 0) {
if(isManualDestory || account==null || account.trim().length()==0) return;
{ }
return ; sendBindRequest(account);
}
sendBindRequest(account);
}
protected static boolean autoBindDeviceId(){
String account = getAccount();
boolean isManualDestory = CIMCacheToolkit.getInstance().getBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED);
boolean isManualStoped = CIMCacheToolkit.getInstance().getBoolean(CIMCacheToolkit.KEY_MANUAL_STOP);
if( isManualStoped || account==null || account.trim().length()==0 || isManualDestory )
{
return false;
}
sendBindRequest(account);
return true;
} }
protected static boolean autoBindDeviceId() {
String account = getAccount();
/**
boolean isManualDestory = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
boolean isManualStoped = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_MANUAL_STOP);
if (isManualStoped || account == null || account.trim().length() == 0 || isManualDestory) {
return false;
}
sendBindRequest(account);
return true;
}
/**
* 发送一个CIM请求 * 发送一个CIM请求
*
* @param context * @param context
* @body * @body
*/ */
public static void sendRequest(SentBody body){ public static void sendRequest(SentBody body) {
boolean isManualStop = CIMCacheToolkit.getInstance().getBoolean(CIMCacheToolkit.KEY_MANUAL_STOP); boolean isManualStop = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_MANUAL_STOP);
boolean isManualDestory = CIMCacheToolkit.getInstance().getBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED); boolean isManualDestory = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
if(isManualStop || isManualDestory) if (isManualStop || isManualDestory) {
{ return;
return ;
} }
Intent serviceIntent = new Intent(); Intent serviceIntent = new Intent();
serviceIntent.putExtra(SentBody.class.getName(), body); serviceIntent.putExtra(SentBody.class.getName(), body);
serviceIntent.setAction(ACTION_SEND_REQUEST_BODY); serviceIntent.setAction(ACTION_SEND_REQUEST_BODY);
startService(serviceIntent); startService(serviceIntent);
}
/**
* 停止接受推送将会退出当前账号登录端口与服务端的连接
* @param context
*/
public static void stop(){
boolean isManualDestory = CIMCacheToolkit.getInstance().getBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED);
if(isManualDestory){
return ;
}
CIMCacheToolkit.getInstance().putBoolean(CIMCacheToolkit.KEY_MANUAL_STOP, true);
Intent serviceIntent = new Intent();
serviceIntent.setAction(ACTION_CLOSE_CIM_CONNECTION);
startService(serviceIntent);
} }
/**
/** * 停止接受推送将会退出当前账号登录端口与服务端的连接
* 完全销毁CIM一般用于完全退出程序调用resume将不能恢复 *
* @param context * @param context
*/ */
public static void destroy(){ public static void stop() {
boolean isManualDestory = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
CIMCacheToolkit.getInstance().putBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED, true); if (isManualDestory) {
return;
Intent serviceIntent = new Intent(); }
CIMCacheManager.getInstance().putBoolean(CIMCacheManager.KEY_MANUAL_STOP, true);
startService(new Intent(ACTION_CLOSE_CIM_CONNECTION));
}
/**
* 完全销毁CIM一般用于完全退出程序调用resume将不能恢复
*
* @param context
*/
public static void destroy() {
CIMCacheManager.getInstance().putBoolean(CIMCacheManager.KEY_CIM_DESTROYED, true);
Intent serviceIntent = new Intent();
serviceIntent.setAction(ACTION_DESTORY); serviceIntent.setAction(ACTION_DESTORY);
startService(serviceIntent); startService(serviceIntent);
} }
/**
/** * 重新恢复接收推送重新连接服务端并登录当前账号如果aotuBind == true
* 重新恢复接收推送重新连接服务端并登录当前账号如果aotuBind == true *
* @param context * @param context
* @param aotuBind * @param aotuBind
*/ */
public static void resume(){ public static void resume() {
boolean isManualDestory = CIMCacheToolkit.getInstance().getBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED); boolean isManualDestory = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
if(isManualDestory){ if (isManualDestory) {
return ; return;
} }
autoBindDeviceId(); autoBindDeviceId();
} }
public static boolean isConnected(){ public static boolean isConnected() {
return CIMCacheToolkit.getInstance().getBoolean(CIMCacheToolkit.KEY_CIM_CONNECTION_STATE); return CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_CONNECTION_STATE);
} }
public static int getState(){ public static int getState() {
boolean isManualDestory = CIMCacheToolkit.getInstance().getBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED); boolean isManualDestory = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
if(isManualDestory){ if (isManualDestory) {
return STATE_DESTROYED; return STATE_DESTROYED;
} }
boolean isManualStop = CIMCacheToolkit.getInstance().getBoolean(CIMCacheToolkit.KEY_MANUAL_STOP); boolean isManualStop = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_MANUAL_STOP);
if(isManualStop){ if (isManualStop) {
return STATE_STOPED; return STATE_STOPED;
} }
return STATE_NORMAL; return STATE_NORMAL;
} }
public static String getDeviceModel() {
public static String getDeviceModel(){ return System.getProperties().getProperty(CIMConstant.ConfigKey.DEVICE_MODEL);
return System.getProperties().getProperty(CIMConstant.ConfigKey.DEVICE_MODEL); }
}
public static String getClientVersion() {
public static String getClientVersion(){ return System.getProperties().getProperty(CIMConstant.ConfigKey.CLIENT_VERSION);
return System.getProperties().getProperty(CIMConstant.ConfigKey.CLIENT_VERSION); }
}
public static String getAccount(){ public static String getAccount() {
return System.getProperties().getProperty(CIMConstant.ConfigKey.CLIENT_ACCOUNT); return System.getProperties().getProperty(CIMConstant.ConfigKey.CLIENT_ACCOUNT);
} }
public static void setAccount(String account){
System.getProperties().put(CIMConstant.ConfigKey.CLIENT_ACCOUNT,account); public static void setAccount(String account) {
} System.getProperties().put(CIMConstant.ConfigKey.CLIENT_ACCOUNT, account);
public static void setClientVersion(String version){ }
System.getProperties().put(CIMConstant.ConfigKey.CLIENT_VERSION,version);
} public static void setClientVersion(String version) {
System.getProperties().put(CIMConstant.ConfigKey.CLIENT_VERSION, version);
public static void setDeviceModel(String model){ }
System.getProperties().put(CIMConstant.ConfigKey.DEVICE_MODEL,model);
} public static void setDeviceModel(String model) {
System.getProperties().put(CIMConstant.ConfigKey.DEVICE_MODEL, model);
private static String getLocalMac() { }
InetAddress ia;
private static String getLocalMac() {
InetAddress ia;
try { try {
ia = InetAddress.getLocalHost(); ia = InetAddress.getLocalHost();
byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress(); byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();
StringBuffer sb = new StringBuffer(""); StringBuffer sb = new StringBuffer("");
for(int i=0; i<mac.length; i++) { for (int i = 0; i < mac.length; i++) {
if(i!=0) { if (i != 0) {
sb.append("-"); sb.append("-");
} }
//字节转换为整数 // 字节转换为整数
int temp = mac[i]&0xff; int temp = mac[i] & 0xff;
String str = Integer.toHexString(temp); String str = Integer.toHexString(temp);
if(str.length()==1) { if (str.length() == 1) {
sb.append("0"+str); sb.append("0" + str);
}else { } else {
sb.append(str); sb.append(str);
} }
} }
@ -289,7 +282,7 @@ public class CIMPushManager {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
return null; return null;
} }
} }

View File

@ -20,73 +20,62 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.client; package com.farsunset.cim.sdk.client;
import com.farsunset.cim.sdk.client.model.Intent; import com.farsunset.cim.sdk.client.model.Intent;
import com.farsunset.cim.sdk.client.model.SentBody; import com.farsunset.cim.sdk.client.model.SentBody;
/** /**
* 与服务端连接服务 * 与服务端连接服务
* *
*/ */
public class CIMPushService { public class CIMPushService {
protected final static int DEF_CIM_PORT = 23456; protected final static int DEF_CIM_PORT = 23456;
private CIMConnectorManager manager; private CIMConnectorManager manager;
private static CIMPushService service; private static CIMPushService service;
public static CIMPushService getInstance(){
if (service==null){ public static CIMPushService getInstance() {
service = new CIMPushService(); if (service == null) {
} service = new CIMPushService();
}
return service; return service;
} }
public CIMPushService()
{
manager = CIMConnectorManager.getManager();
}
public void onStartCommand(Intent intent) {
intent = (intent == null ? new Intent(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE) : intent);
public CIMPushService() {
String action = intent.getAction(); manager = CIMConnectorManager.getManager();
}
if(CIMPushManager.ACTION_CREATE_CIM_CONNECTION.equals(action))
{ public void onStartCommand(Intent intent) {
String host = CIMCacheToolkit.getInstance().getString(CIMCacheToolkit.KEY_CIM_SERVIER_HOST);
int port =CIMCacheToolkit.getInstance().getInt(CIMCacheToolkit.KEY_CIM_SERVIER_PORT); intent = (intent == null ? new Intent(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE) : intent);
manager.connect(host,port);
} String action = intent.getAction();
if(CIMPushManager.ACTION_SEND_REQUEST_BODY.equals(action)) if (CIMPushManager.ACTION_CREATE_CIM_CONNECTION.equals(action)) {
{ String host = CIMCacheManager.getInstance().getString(CIMCacheManager.KEY_CIM_SERVIER_HOST);
manager.send((SentBody) intent.getExtra(SentBody.class.getName())); int port = CIMCacheManager.getInstance().getInt(CIMCacheManager.KEY_CIM_SERVIER_PORT);
} manager.connect(host, port);
}
if(CIMPushManager.ACTION_CLOSE_CIM_CONNECTION.equals(action))
{ if (CIMPushManager.ACTION_SEND_REQUEST_BODY.equals(action)) {
manager.closeSession(); manager.send((SentBody) intent.getExtra(SentBody.class.getName()));
} }
if(CIMPushManager.ACTION_DESTORY.equals(action)) if (CIMPushManager.ACTION_CLOSE_CIM_CONNECTION.equals(action)) {
{ manager.closeSession();
manager.destroy(); }
}
if (CIMPushManager.ACTION_DESTORY.equals(action)) {
if(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE.equals(action) && !manager.isConnected()) manager.destroy();
{ }
String host = CIMCacheToolkit.getInstance().getString(CIMCacheToolkit.KEY_CIM_SERVIER_HOST); if (CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE.equals(action) && !manager.isConnected()) {
int port =CIMCacheToolkit.getInstance().getInt( CIMCacheToolkit.KEY_CIM_SERVIER_PORT);
manager.connect(host,port); String host = CIMCacheManager.getInstance().getString(CIMCacheManager.KEY_CIM_SERVIER_HOST);
} int port = CIMCacheManager.getInstance().getInt(CIMCacheManager.KEY_CIM_SERVIER_PORT);
} manager.connect(host, port);
}
}
} }

View File

@ -21,100 +21,97 @@
*/ */
package com.farsunset.cim.sdk.client.constant; package com.farsunset.cim.sdk.client.constant;
/** /**
* 常量 * 常量
*/ */
public interface CIMConstant { public interface CIMConstant {
long RECONN_INTERVAL_TIME= 30 * 1000; long RECONN_INTERVAL_TIME = 30 * 1000;
//消息头长度为3个字节第一个字节为消息类型第二第三字节 转换int后为消息长度 // 消息头长度为3个字节第一个字节为消息类型第二第三字节 转换int后为消息长度
int DATA_HEADER_LENGTH = 3; int DATA_HEADER_LENGTH = 3;
public static interface ReturnCode{
public static interface ReturnCode {
String CODE_404 ="404";
String CODE_404 = "404";
String CODE_403 ="403";
String CODE_403 = "403";
String CODE_405 ="405";
String CODE_405 = "405";
String CODE_200 ="200";
String CODE_200 = "200";
String CODE_206 ="206";
String CODE_206 = "206";
String CODE_500 ="500";
String CODE_500 = "500";
}
public static interface ConfigKey{
public static String DEVICE_MODEL ="client.model";
public static String CLIENT_VERSION ="client.version";
public static String CLIENT_ACCOUNT ="client.account";
} }
public static interface ProtobufType{ public static interface ConfigKey {
byte C_H_RS = 0;
byte S_H_RQ = 1; public static String DEVICE_MODEL = "client.model";
byte MESSAGE = 2; public static String CLIENT_VERSION = "client.version";
byte SENTBODY = 3; public static String CLIENT_ACCOUNT = "client.account";
byte REPLYBODY = 4;
} }
public static interface RequestKey{ public static interface ProtobufType {
byte C_H_RS = 0;
byte S_H_RQ = 1;
String CLIENT_BIND ="client_bind"; byte MESSAGE = 2;
byte SENTBODY = 3;
String CLIENT_LOGOUT ="client_logout"; byte REPLYBODY = 4;
}
public static interface RequestKey {
String CLIENT_BIND = "client_bind";
String CLIENT_LOGOUT = "client_logout";
@Deprecated @Deprecated
String CLIENT_PULL_MESSAGE ="client_pull_message"; String CLIENT_PULL_MESSAGE = "client_pull_message";
} }
public static interface MessageAction {
public static interface MessageAction{
// 被其他设备登录挤下线消息
//被其他设备登录挤下线消息 String ACTION_999 = "999";
String ACTION_999 ="999"; // 被系统禁用消息
//被系统禁用消息 String ACTION_444 = "444";
String ACTION_444 ="444"; }
}
public static interface IntentAction {
public static interface IntentAction{ // 消息广播action
String ACTION_MESSAGE_RECEIVED = "com.farsunset.cim.MESSAGE_RECEIVED";
// 消息广播action
String ACTION_MESSAGE_RECEIVED = "com.farsunset.cim.MESSAGE_RECEIVED"; // 发送sendbody失败广播
String ACTION_SENT_FAILED = "com.farsunset.cim.SENT_FAILED";
// 发送sendbody失败广播
String ACTION_SENT_FAILED = "com.farsunset.cim.SENT_FAILED"; // 发送sendbody成功广播
String ACTION_SENT_SUCCESSED = "com.farsunset.cim.SENT_SUCCESSED";
// 发送sendbody成功广播
String ACTION_SENT_SUCCESSED = "com.farsunset.cim.SENT_SUCCESSED"; // 链接意外关闭广播
String ACTION_CONNECTION_CLOSED = "com.farsunset.cim.CONNECTION_CLOSED";
// 链接意外关闭广播
String ACTION_CONNECTION_CLOSED = "com.farsunset.cim.CONNECTION_CLOSED"; // 链接失败广播
String ACTION_CONNECTION_FAILED = "com.farsunset.cim.CONNECTION_FAILED";
// 链接失败广播
String ACTION_CONNECTION_FAILED = "com.farsunset.cim.CONNECTION_FAILED"; // 链接成功广播
String ACTION_CONNECTION_SUCCESSED = "com.farsunset.cim.CONNECTION_SUCCESSED";
// 链接成功广播
String ACTION_CONNECTION_SUCCESSED = "com.farsunset.cim.CONNECTION_SUCCESSED"; // 发送sendbody成功后获得replaybody回应广播
String ACTION_REPLY_RECEIVED = "com.farsunset.cim.REPLY_RECEIVED";
// 发送sendbody成功后获得replaybody回应广播
String ACTION_REPLY_RECEIVED = "com.farsunset.cim.REPLY_RECEIVED"; // 网络变化广播
String ACTION_NETWORK_CHANGED = "android.net.conn.CONNECTIVITY_CHANGE";
// 网络变化广播
String ACTION_NETWORK_CHANGED = "android.net.conn.CONNECTIVITY_CHANGE"; // 未知异常
String ACTION_UNCAUGHT_EXCEPTION = "com.farsunset.cim.UNCAUGHT_EXCEPTION";
// 未知异常
String ACTION_UNCAUGHT_EXCEPTION = "com.farsunset.cim.UNCAUGHT_EXCEPTION"; // 重试连接
String ACTION_CONNECTION_RECOVERY = "com.farsunset.cim.CONNECTION_RECOVERY";
//重试连接 }
String ACTION_CONNECTION_RECOVERY = "com.farsunset.cim.CONNECTION_RECOVERY";
}
} }

View File

@ -21,15 +21,14 @@
*/ */
package com.farsunset.cim.sdk.client.exception; package com.farsunset.cim.sdk.client.exception;
public class NetworkDisconnectedException extends Exception { public class NetworkDisconnectedException extends Exception {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public NetworkDisconnectedException() { public NetworkDisconnectedException() {
super(); super();
} }
public NetworkDisconnectedException(String s) { public NetworkDisconnectedException(String s) {
super(s); super(s);
} }

View File

@ -21,9 +21,8 @@
*/ */
package com.farsunset.cim.sdk.client.exception; package com.farsunset.cim.sdk.client.exception;
public class SessionDisconnectedException extends Exception { public class SessionDisconnectedException extends Exception {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public SessionDisconnectedException() { public SessionDisconnectedException() {

View File

@ -26,7 +26,7 @@ import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder; import org.apache.mina.filter.codec.ProtocolEncoder;
/** /**
* android客户端端消息 编码解码器 * android客户端端消息 编码解码器
*/ */
public class ClientMessageCodecFactory implements ProtocolCodecFactory { public class ClientMessageCodecFactory implements ProtocolCodecFactory {
@ -34,23 +34,23 @@ public class ClientMessageCodecFactory implements ProtocolCodecFactory {
/** /**
* 消息编码器 * 消息编码器
*/ */
private final ClientMessageEncoder encoder; private final ClientMessageEncoder encoder;
/** /**
* 消息解码器 * 消息解码器
*/ */
private final ClientMessageDecoder decoder; private final ClientMessageDecoder decoder;
public ClientMessageCodecFactory() {
public ClientMessageCodecFactory() { encoder = new ClientMessageEncoder();
encoder = new ClientMessageEncoder(); decoder = new ClientMessageDecoder();
decoder = new ClientMessageDecoder(); }
}
public ProtocolEncoder getEncoder(IoSession session) throws Exception {
public ProtocolEncoder getEncoder(IoSession session) throws Exception { return encoder;
return encoder; }
}
public ProtocolDecoder getDecoder(IoSession session) throws Exception { public ProtocolDecoder getDecoder(IoSession session) throws Exception {
return decoder; return decoder;
} }
} }

View File

@ -21,7 +21,6 @@
*/ */
package com.farsunset.cim.sdk.client.filter; package com.farsunset.cim.sdk.client.filter;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSession;
@ -35,78 +34,72 @@ import com.farsunset.cim.sdk.client.model.ReplyBody;
import com.farsunset.cim.sdk.model.proto.MessageProto; import com.farsunset.cim.sdk.model.proto.MessageProto;
import com.farsunset.cim.sdk.model.proto.ReplyBodyProto; import com.farsunset.cim.sdk.model.proto.ReplyBodyProto;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
/** /**
* 客户端消息解码 * 客户端消息解码
*/ */
public class ClientMessageDecoder extends CumulativeProtocolDecoder { public class ClientMessageDecoder extends CumulativeProtocolDecoder {
protected final Logger logger = Logger.getLogger(ClientMessageDecoder.class); protected final Logger logger = Logger.getLogger(ClientMessageDecoder.class);
@Override @Override
public boolean doDecode(IoSession iosession, IoBuffer iobuffer, public boolean doDecode(IoSession iosession, IoBuffer iobuffer, ProtocolDecoderOutput out) throws Exception {
ProtocolDecoderOutput out) throws Exception {
/**
* 消息头3位
*/
if (iobuffer.remaining() < CIMConstant.DATA_HEADER_LENGTH) {
return false;
}
iobuffer.mark();
byte conetnType = iobuffer.get();
byte lv = iobuffer.get();// int 低位
byte hv = iobuffer.get();// int 高位
int conetnLength = getContentLength(lv, hv);
// 如果消息体没有接收完整则重置读取等待下一次重新读取
if (conetnLength > iobuffer.remaining()) {
iobuffer.reset();
return false;
}
byte[] dataBytes = new byte[conetnLength];
iobuffer.get(dataBytes, 0, conetnLength);
Object message = mappingMessageObject(dataBytes, conetnType);
if (message != null) {
out.write(message);
}
/**
* 消息头3位
*/
if(iobuffer.remaining() < CIMConstant.DATA_HEADER_LENGTH){
return false;
}
iobuffer.mark();
byte conetnType = iobuffer.get();
byte lv =iobuffer.get();//int 低位
byte hv =iobuffer.get();//int 高位
int conetnLength = getContentLength(lv,hv);
//如果消息体没有接收完整则重置读取等待下一次重新读取
if(conetnLength > iobuffer.remaining()){
iobuffer.reset();
return false;
}
byte[] dataBytes = new byte[conetnLength];
iobuffer.get(dataBytes, 0, conetnLength);
Object message = mappingMessageObject(dataBytes,conetnType);
if(message!=null){
out.write(message);
}
return true; return true;
} }
private Object mappingMessageObject(byte[] bytes,byte type) throws InvalidProtocolBufferException { private Object mappingMessageObject(byte[] bytes, byte type) throws InvalidProtocolBufferException {
if (CIMConstant.ProtobufType.S_H_RQ == type) {
if(CIMConstant.ProtobufType.S_H_RQ == type)
{
HeartbeatRequest request = HeartbeatRequest.getInstance(); HeartbeatRequest request = HeartbeatRequest.getInstance();
logger.info(request.toString()); logger.info(request.toString());
return request; return request;
} }
if(CIMConstant.ProtobufType.REPLYBODY == type) if (CIMConstant.ProtobufType.REPLYBODY == type) {
{
ReplyBodyProto.Model bodyProto = ReplyBodyProto.Model.parseFrom(bytes); ReplyBodyProto.Model bodyProto = ReplyBodyProto.Model.parseFrom(bytes);
ReplyBody body = new ReplyBody(); ReplyBody body = new ReplyBody();
body.setKey(bodyProto.getKey()); body.setKey(bodyProto.getKey());
body.setTimestamp(bodyProto.getTimestamp()); body.setTimestamp(bodyProto.getTimestamp());
body.putAll(bodyProto.getDataMap()); body.putAll(bodyProto.getDataMap());
body.setCode(bodyProto.getCode()); body.setCode(bodyProto.getCode());
body.setMessage(bodyProto.getMessage()); body.setMessage(bodyProto.getMessage());
logger.info(body.toString()); logger.info(body.toString());
return body; return body;
} }
if(CIMConstant.ProtobufType.MESSAGE == type) if (CIMConstant.ProtobufType.MESSAGE == type) {
{
MessageProto.Model bodyProto = MessageProto.Model.parseFrom(bytes); MessageProto.Model bodyProto = MessageProto.Model.parseFrom(bytes);
Message message = new Message(); Message message = new Message();
message.setMid(bodyProto.getMid()); message.setMid(bodyProto.getMid());
@ -118,25 +111,26 @@ public class ClientMessageDecoder extends CumulativeProtocolDecoder {
message.setExtra(bodyProto.getExtra()); message.setExtra(bodyProto.getExtra());
message.setTimestamp(bodyProto.getTimestamp()); message.setTimestamp(bodyProto.getTimestamp());
message.setFormat(bodyProto.getFormat()); message.setFormat(bodyProto.getFormat());
logger.info(message.toString()); logger.info(message.toString());
return message; return message;
} }
return null; return null;
} }
/** /**
* 解析消息体长度 * 解析消息体长度
*
* @param type * @param type
* @param length * @param length
* @return * @return
*/ */
private int getContentLength(byte lv,byte hv){ private int getContentLength(byte lv, byte hv) {
int l = (lv & 0xff); int l = (lv & 0xff);
int h = (hv & 0xff); int h = (hv & 0xff);
return (l| (h <<= 8)); return (l | (h <<= 8));
} }
} }

View File

@ -29,45 +29,48 @@ import org.apache.mina.filter.codec.ProtocolEncoderOutput;
import com.farsunset.cim.sdk.client.constant.CIMConstant; import com.farsunset.cim.sdk.client.constant.CIMConstant;
import com.farsunset.cim.sdk.client.model.Protobufable; import com.farsunset.cim.sdk.client.model.Protobufable;
/** /**
* 客户端消息发送前进行编码 * 客户端消息发送前进行编码
*/ */
public class ClientMessageEncoder extends ProtocolEncoderAdapter { public class ClientMessageEncoder extends ProtocolEncoderAdapter {
protected final Logger logger = Logger.getLogger(ClientMessageEncoder.class); protected final Logger logger = Logger.getLogger(ClientMessageEncoder.class);
@Override @Override
public void encode(IoSession iosession, Object object, ProtocolEncoderOutput out) throws Exception { public void encode(IoSession iosession, Object object, ProtocolEncoderOutput out) throws Exception {
if(object instanceof Protobufable){ if (object instanceof Protobufable) {
Protobufable data = (Protobufable) object; Protobufable data = (Protobufable) object;
byte[] byteArray = data.getByteArray(); byte[] byteArray = data.getByteArray();
IoBuffer buff = IoBuffer.allocate(byteArray.length + CIMConstant.DATA_HEADER_LENGTH).setAutoExpand(true); IoBuffer buff = IoBuffer.allocate(byteArray.length + CIMConstant.DATA_HEADER_LENGTH).setAutoExpand(true);
buff.put(createHeader(data.getType(),byteArray.length)); buff.put(createHeader(data.getType(), byteArray.length));
buff.put(byteArray); buff.put(byteArray);
buff.flip(); buff.flip();
out.write(buff); out.write(buff);
//打印出收到的消息 // 打印出收到的消息
logger.info(data.toString()); logger.info(data.toString());
} }
} }
/** /**
* 消息体最大为65535 * 消息体最大为65535
*
* @param type * @param type
* @param length * @param length
* @return * @return
*/ */
private byte[] createHeader(byte type,int length){ private byte[] createHeader(byte type, int length) {
byte[] header = new byte[CIMConstant.DATA_HEADER_LENGTH]; byte[] header = new byte[CIMConstant.DATA_HEADER_LENGTH];
header[0] = type; header[0] = type;
header[1] = (byte) (length & 0xff); header[1] = (byte) (length & 0xff);
header[2] = (byte) ((length >> 8) & 0xff); header[2] = (byte) ((length >> 8) & 0xff);
return header; return header;
} }
} }

View File

@ -29,35 +29,34 @@ import com.farsunset.cim.sdk.client.constant.CIMConstant;
* 服务端心跳请求 * 服务端心跳请求
* *
*/ */
public class HeartbeatRequest implements Serializable,Protobufable { public class HeartbeatRequest implements Serializable, Protobufable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final String TAG = "SERVER_HEARTBEAT_REQUEST"; private static final String TAG = "SERVER_HEARTBEAT_REQUEST";
private static final String CMD_HEARTBEAT_RESPONSE = "SR"; private static final String CMD_HEARTBEAT_RESPONSE = "SR";
private static HeartbeatRequest object = new HeartbeatRequest(); private static HeartbeatRequest object = new HeartbeatRequest();
private HeartbeatRequest(){ private HeartbeatRequest() {
} }
public static HeartbeatRequest getInstance() { public static HeartbeatRequest getInstance() {
return object; return object;
} }
@Override @Override
public byte[] getByteArray() { public byte[] getByteArray() {
return CMD_HEARTBEAT_RESPONSE.getBytes(); return CMD_HEARTBEAT_RESPONSE.getBytes();
} }
public String toString(){ public String toString() {
return TAG; return TAG;
} }
@Override @Override
public byte getType() { public byte getType() {
return CIMConstant.ProtobufType.S_H_RQ; return CIMConstant.ProtobufType.S_H_RQ;
} }
} }

View File

@ -28,27 +28,28 @@ import com.farsunset.cim.sdk.client.constant.CIMConstant;
/** /**
* 客户端心跳响应 * 客户端心跳响应
*/ */
public class HeartbeatResponse implements Serializable,Protobufable { public class HeartbeatResponse implements Serializable, Protobufable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final String TAG = "CLIENT_HEARTBEAT_RESPONSE"; private static final String TAG = "CLIENT_HEARTBEAT_RESPONSE";
private static final String CMD_HEARTBEAT_RESPONSE = "CR"; private static final String CMD_HEARTBEAT_RESPONSE = "CR";
private static HeartbeatResponse object = new HeartbeatResponse(); private static HeartbeatResponse object = new HeartbeatResponse();
private HeartbeatResponse(){ private HeartbeatResponse() {
} }
public static HeartbeatResponse getInstance() { public static HeartbeatResponse getInstance() {
return object; return object;
} }
@Override @Override
public byte[] getByteArray() { public byte[] getByteArray() {
return CMD_HEARTBEAT_RESPONSE.getBytes(); return CMD_HEARTBEAT_RESPONSE.getBytes();
} }
public String toString(){ public String toString() {
return TAG; return TAG;
} }
@ -56,5 +57,5 @@ public class HeartbeatResponse implements Serializable,Protobufable {
public byte getType() { public byte getType() {
return CIMConstant.ProtobufType.C_H_RS; return CIMConstant.ProtobufType.C_H_RS;
} }
} }

View File

@ -23,6 +23,7 @@ package com.farsunset.cim.sdk.client.model;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap; import java.util.HashMap;
/** /**
* java |android 客户端请求结构 * java |android 客户端请求结构
* *
@ -35,14 +36,13 @@ public class Intent implements Serializable {
private HashMap<String, Object> data = new HashMap<String, Object>(); private HashMap<String, Object> data = new HashMap<String, Object>();
public Intent() { public Intent() {
} }
public Intent(String action) { public Intent(String action) {
this.action = action; this.action = action;
} }
public String getAction() { public String getAction() {
return action; return action;
} }
@ -51,18 +51,19 @@ public class Intent implements Serializable {
this.action = action; this.action = action;
} }
public void putExtra(String key , Object value){ public void putExtra(String key, Object value) {
data.put(key, value); data.put(key, value);
} }
public Object getExtra(String key){
public Object getExtra(String key) {
return data.get(key); return data.get(key);
} }
public long getLongExtra(String key, long defValue) { public long getLongExtra(String key, long defValue) {
Object v = getExtra(key); Object v = getExtra(key);
try{ try {
return Long.parseLong(v.toString()); return Long.parseLong(v.toString());
}catch(Exception e){ } catch (Exception e) {
return defValue; return defValue;
} }
} }

View File

@ -30,13 +30,11 @@ public class Message implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 消息类型用户自定义消息类别 * 消息类型用户自定义消息类别
*/ */
private String mid; private String mid;
/** /**
* 消息类型用户自定义消息类别 * 消息类型用户自定义消息类别
*/ */
@ -59,8 +57,6 @@ public class Message implements Serializable {
*/ */
private String receiver; private String receiver;
/** /**
* content 内容格式 * content 内容格式
*/ */
@ -72,12 +68,11 @@ public class Message implements Serializable {
private String extra; private String extra;
private long timestamp; private long timestamp;
public Message() {
public Message()
{
timestamp = System.currentTimeMillis(); timestamp = System.currentTimeMillis();
} }
public long getTimestamp() { public long getTimestamp() {
return timestamp; return timestamp;
} }
@ -86,14 +81,14 @@ public class Message implements Serializable {
this.timestamp = timestamp; this.timestamp = timestamp;
} }
public String getAction() { public String getAction() {
return action; return action;
} }
public void setAction(String action) { public void setAction(String action) {
this.action = action; this.action = action;
} }
public String getTitle() { public String getTitle() {
return title; return title;
} }
@ -126,7 +121,6 @@ public class Message implements Serializable {
this.receiver = receiver; this.receiver = receiver;
} }
public String getFormat() { public String getFormat() {
return format; return format;
} }
@ -134,17 +128,17 @@ public class Message implements Serializable {
public void setFormat(String format) { public void setFormat(String format) {
this.format = format; this.format = format;
} }
public String getExtra() { public String getExtra() {
return extra; return extra;
} }
public void setExtra(String extra) { public void setExtra(String extra) {
this.extra = extra; this.extra = extra;
} }
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("#Message#").append("\n"); buffer.append("#Message#").append("\n");
buffer.append("mid:").append(mid).append("\n"); buffer.append("mid:").append(mid).append("\n");
@ -158,7 +152,6 @@ public class Message implements Serializable {
buffer.append("timestamp:").append(timestamp); buffer.append("timestamp:").append(timestamp);
return buffer.toString(); return buffer.toString();
} }
public String getMid() { public String getMid() {
return mid; return mid;
@ -169,8 +162,7 @@ public class Message implements Serializable {
} }
public boolean isNotEmpty(String txt) { public boolean isNotEmpty(String txt) {
return txt != null && txt.trim().length()!=0; return txt != null && txt.trim().length() != 0;
} }
} }

View File

@ -20,12 +20,13 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.client.model; package com.farsunset.cim.sdk.client.model;
/** /**
* 需要向另一端发送的结构体 * 需要向另一端发送的结构体
*/ */
public interface Protobufable { public interface Protobufable {
byte[] getByteArray(); byte[] getByteArray();
byte getType(); byte getType();
} }

View File

@ -25,25 +25,25 @@ import java.io.Serializable;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
/** /**
* 请求应答对象 * 请求应答对象
* *
*/ */
public class ReplyBody implements Serializable { public class ReplyBody implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 请求key * 请求key
*/ */
private String key; private String key;
/** /**
* 返回码 * 返回码
*/ */
private String code; private String code;
/** /**
* 返回说明 * 返回说明
*/ */
@ -54,14 +54,13 @@ public class ReplyBody implements Serializable {
*/ */
private HashMap<String, String> data; private HashMap<String, String> data;
private long timestamp; private long timestamp;
public ReplyBody() public ReplyBody() {
{
data = new HashMap<String, String>(); data = new HashMap<String, String>();
timestamp = System.currentTimeMillis(); timestamp = System.currentTimeMillis();
} }
public long getTimestamp() { public long getTimestamp() {
return timestamp; return timestamp;
} }
@ -70,8 +69,6 @@ public class ReplyBody implements Serializable {
this.timestamp = timestamp; this.timestamp = timestamp;
} }
public String getKey() { public String getKey() {
return key; return key;
} }
@ -81,8 +78,8 @@ public class ReplyBody implements Serializable {
} }
public void put(String k, String v) { public void put(String k, String v) {
if(v!=null && k!=null){ if (v != null && k != null) {
data.put(k, v); data.put(k, v);
} }
} }
@ -105,8 +102,8 @@ public class ReplyBody implements Serializable {
public void putAll(Map<String, String> map) { public void putAll(Map<String, String> map) {
data.putAll(map); data.putAll(map);
} }
public Set<String> getKeySet() { public Set<String> getKeySet() {
return data.keySet(); return data.keySet();
} }
@ -118,24 +115,21 @@ public class ReplyBody implements Serializable {
this.code = code; this.code = code;
} }
public String toString() {
public String toString()
{
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("#ReplyBody#").append("\n"); buffer.append("#ReplyBody#").append("\n");
buffer.append("key:").append(this.getKey()).append("\n"); buffer.append("key:").append(this.getKey()).append("\n");
buffer.append("timestamp:").append(timestamp).append("\n"); buffer.append("timestamp:").append(timestamp).append("\n");
buffer.append("code:").append(code).append("\n"); buffer.append("code:").append(code).append("\n");
if(!data.isEmpty()){ if (!data.isEmpty()) {
buffer.append("data{").append("\n"); buffer.append("data{").append("\n");
for(String key:getKeySet()) for (String key : getKeySet()) {
{
buffer.append(key).append(":").append(this.get(key)).append("\n"); buffer.append(key).append(":").append(this.get(key)).append("\n");
} }
buffer.append("}"); buffer.append("}");
} }
return buffer.toString(); return buffer.toString();
} }

View File

@ -28,17 +28,18 @@ import java.util.Set;
import com.farsunset.cim.sdk.client.constant.CIMConstant; import com.farsunset.cim.sdk.client.constant.CIMConstant;
import com.farsunset.cim.sdk.model.proto.SentBodyProto; import com.farsunset.cim.sdk.model.proto.SentBodyProto;
/** /**
* java |android 客户端请求结构 * java |android 客户端请求结构
* *
*/ */
public class SentBody implements Serializable,Protobufable { public class SentBody implements Serializable, Protobufable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private String key; private String key;
private HashMap<String, String> data = new HashMap<String, String>();; private HashMap<String, String> data = new HashMap<String, String>();;
private long timestamp; private long timestamp;
@ -67,19 +68,19 @@ public class SentBody implements Serializable,Protobufable {
} }
public void put(String k, String v) { public void put(String k, String v) {
if(v!=null && k!=null){ if (v != null && k != null) {
data.put(k, v); data.put(k, v);
} }
} }
public void putAll(Map<String, String> map) { public void putAll(Map<String, String> map) {
data.putAll(map); data.putAll(map);
} }
public Set<String> getKeySet() { public Set<String> getKeySet() {
return data.keySet(); return data.keySet();
} }
public void remove(String k) { public void remove(String k) {
data.remove(k); data.remove(k);
} }
@ -87,34 +88,34 @@ public class SentBody implements Serializable,Protobufable {
@Override @Override
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("#SentBody#").append("\n");; buffer.append("#SentBody#").append("\n");
;
buffer.append("key:").append(key).append("\n"); buffer.append("key:").append(key).append("\n");
buffer.append("timestamp:").append(timestamp).append("\n"); buffer.append("timestamp:").append(timestamp).append("\n");
if(!data.isEmpty()){ if (!data.isEmpty()) {
buffer.append("data{").append("\n"); buffer.append("data{").append("\n");
for(String key:getKeySet()) for (String key : getKeySet()) {
{
buffer.append(key).append(":").append(this.get(key)).append("\n"); buffer.append(key).append(":").append(this.get(key)).append("\n");
} }
buffer.append("}"); buffer.append("}");
} }
return buffer.toString(); return buffer.toString();
} }
@Override @Override
public byte[] getByteArray() { public byte[] getByteArray() {
SentBodyProto.Model.Builder builder = SentBodyProto.Model.newBuilder(); SentBodyProto.Model.Builder builder = SentBodyProto.Model.newBuilder();
builder.setKey(key); builder.setKey(key);
builder.setTimestamp(timestamp); builder.setTimestamp(timestamp);
if(!data.isEmpty()){ if (!data.isEmpty()) {
builder.putAllData(data); builder.putAllData(data);
} }
return builder.build().toByteArray(); return builder.build().toByteArray();
} }
@Override @Override
public byte getType() { public byte getType() {
return CIMConstant.ProtobufType.SENTBODY; return CIMConstant.ProtobufType.SENTBODY;
} }
} }

View File

@ -21,41 +21,39 @@
*/ */
package com.farsunset.cim.sdk.server.constant; package com.farsunset.cim.sdk.server.constant;
/** /**
* 常量 * 常量
*/ */
public interface CIMConstant { public interface CIMConstant {
//消息头长度为3个字节第一个字节为消息类型第二第三字节 转换int后为消息长度 // 消息头长度为3个字节第一个字节为消息类型第二第三字节 转换int后为消息长度
int DATA_HEADER_LENGTH = 3; int DATA_HEADER_LENGTH = 3;
public static interface ReturnCode{
String CODE_200 ="200";
String CODE_404 ="404"; public static interface ReturnCode {
String CODE_403 ="403"; String CODE_200 = "200";
String CODE_500 ="500"; String CODE_404 = "404";
String CODE_403 = "403";
String CODE_500 = "500";
} }
String SESSION_KEY ="account";
String HEARTBEAT_KEY ="heartbeat";
public static interface ProtobufType{ String SESSION_KEY = "account";
String HEARTBEAT_KEY = "heartbeat";
public static interface ProtobufType {
byte S_H_RQ = 1; byte S_H_RQ = 1;
byte C_H_RS = 0; byte C_H_RS = 0;
byte MESSAGE = 2; byte MESSAGE = 2;
byte SENTBODY = 3; byte SENTBODY = 3;
byte REPLYBODY = 4; byte REPLYBODY = 4;
} }
public static interface MessageAction{ public static interface MessageAction {
//被其他设备登录挤下线消息 // 被其他设备登录挤下线消息
String ACTION_999 ="999"; String ACTION_999 = "999";
} }
} }

View File

@ -26,26 +26,26 @@ import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder; import org.apache.mina.filter.codec.ProtocolEncoder;
/** /**
* 服务端消息 编码解码器 * 服务端消息 编码解码器
*/ */
public class ServerMessageCodecFactory implements ProtocolCodecFactory { public class ServerMessageCodecFactory implements ProtocolCodecFactory {
private final ServerMessageEncoder encoder; private final ServerMessageEncoder encoder;
private final ServerMessageDecoder decoder; private final ServerMessageDecoder decoder;
public ServerMessageCodecFactory() { public ServerMessageCodecFactory() {
encoder = new ServerMessageEncoder(); encoder = new ServerMessageEncoder();
decoder = new ServerMessageDecoder(); decoder = new ServerMessageDecoder();
} }
public ProtocolEncoder getEncoder(IoSession session) throws Exception { public ProtocolEncoder getEncoder(IoSession session) throws Exception {
return encoder; return encoder;
} }
public ProtocolDecoder getDecoder(IoSession session) throws Exception { public ProtocolDecoder getDecoder(IoSession session) throws Exception {
return decoder; return decoder;
} }
} }

View File

@ -25,11 +25,11 @@ import org.apache.mina.filter.codec.demux.DemuxingProtocolDecoder;
import com.farsunset.cim.sdk.server.filter.decoder.AppMessageDecoder; import com.farsunset.cim.sdk.server.filter.decoder.AppMessageDecoder;
import com.farsunset.cim.sdk.server.filter.decoder.WebMessageDecoder; import com.farsunset.cim.sdk.server.filter.decoder.WebMessageDecoder;
/** /**
* 服务端接收消息解码 * 服务端接收消息解码
*/ */
public class ServerMessageDecoder extends DemuxingProtocolDecoder { public class ServerMessageDecoder extends DemuxingProtocolDecoder {
public ServerMessageDecoder() { public ServerMessageDecoder() {
addMessageDecoder(new AppMessageDecoder()); addMessageDecoder(new AppMessageDecoder());

View File

@ -105,8 +105,8 @@ public class ServerMessageEncoder extends ProtocolEncoderAdapter {
} }
/** /**
* 发送到websocket的数据需要进行相关格式转换 * 发送到websocket的数据需要进行相关格式转换 对传入数据进行无掩码转换
* 对传入数据进行无掩码转换 *
* @param data * @param data
* @return * @return
*/ */

View File

@ -20,6 +20,7 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.server.filter.decoder; package com.farsunset.cim.sdk.server.filter.decoder;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession; import org.apache.mina.core.session.IoSession;
@ -31,96 +32,91 @@ import com.farsunset.cim.sdk.server.constant.CIMConstant;
import com.farsunset.cim.sdk.server.model.HeartbeatResponse; import com.farsunset.cim.sdk.server.model.HeartbeatResponse;
import com.farsunset.cim.sdk.server.model.SentBody; import com.farsunset.cim.sdk.server.model.SentBody;
import com.farsunset.cim.sdk.server.model.proto.SentBodyProto; import com.farsunset.cim.sdk.server.model.proto.SentBodyProto;
/** /**
* 服务端接收消息解码 * 服务端接收消息解码
*/ */
public class AppMessageDecoder extends MessageDecoderAdapter { public class AppMessageDecoder extends MessageDecoderAdapter {
protected final Logger logger = Logger.getLogger(AppMessageDecoder.class); protected final Logger logger = Logger.getLogger(AppMessageDecoder.class);
@Override @Override
public MessageDecoderResult decodable(IoSession arg0, IoBuffer iobuffer) { public MessageDecoderResult decodable(IoSession arg0, IoBuffer iobuffer) {
if(iobuffer.remaining() < CIMConstant.DATA_HEADER_LENGTH){ if (iobuffer.remaining() < CIMConstant.DATA_HEADER_LENGTH) {
return NEED_DATA; return NEED_DATA;
} }
/** /**
* 原生SDK只会发送2种类型消息 1个心跳类型 另一个是sendbody报文的第一个字节为消息类型 * 原生SDK只会发送2种类型消息 1个心跳类型 另一个是sendbody报文的第一个字节为消息类型
*/ */
byte conetnType = iobuffer.get(); byte conetnType = iobuffer.get();
if(conetnType == CIMConstant.ProtobufType.C_H_RS || conetnType == CIMConstant.ProtobufType.SENTBODY) { if (conetnType == CIMConstant.ProtobufType.C_H_RS || conetnType == CIMConstant.ProtobufType.SENTBODY) {
return OK; return OK;
} }
return NOT_OK; return NOT_OK;
} }
@Override @Override
public MessageDecoderResult decode(IoSession iosession, IoBuffer iobuffer, ProtocolDecoderOutput out) throws Exception { public MessageDecoderResult decode(IoSession iosession, IoBuffer iobuffer, ProtocolDecoderOutput out)
iobuffer.mark(); throws Exception {
iobuffer.mark();
byte conetnType = iobuffer.get();
byte lv =iobuffer.get();//int 低位 byte conetnType = iobuffer.get();
byte hv =iobuffer.get();//int 高位 byte lv = iobuffer.get();// int 低位
byte hv = iobuffer.get();// int 高位
int conetnLength = getContentLength(lv,hv);
int conetnLength = getContentLength(lv, hv);
//如果消息体没有接收完整则重置读取等待下一次重新读取
if(conetnLength > iobuffer.remaining()){ // 如果消息体没有接收完整则重置读取等待下一次重新读取
iobuffer.reset(); if (conetnLength > iobuffer.remaining()) {
return NEED_DATA; iobuffer.reset();
} return NEED_DATA;
}
byte[] dataBytes = new byte[conetnLength];
iobuffer.get(dataBytes, 0, conetnLength); byte[] dataBytes = new byte[conetnLength];
iobuffer.get(dataBytes, 0, conetnLength);
Object message = mappingMessageObject(dataBytes,conetnType);
if(message != null){ Object message = mappingMessageObject(dataBytes, conetnType);
out.write(message); if (message != null) {
} out.write(message);
return OK; }
return OK;
} }
public Object mappingMessageObject(byte[] data,byte type) throws Exception public Object mappingMessageObject(byte[] data, byte type) throws Exception {
{
if (CIMConstant.ProtobufType.C_H_RS == type) {
if(CIMConstant.ProtobufType.C_H_RS == type)
{
HeartbeatResponse response = HeartbeatResponse.getInstance(); HeartbeatResponse response = HeartbeatResponse.getInstance();
logger.info(response.toString()); logger.info(response.toString());
return response; return response;
} }
if(CIMConstant.ProtobufType.SENTBODY == type) if (CIMConstant.ProtobufType.SENTBODY == type) {
{
SentBodyProto.Model bodyProto = SentBodyProto.Model.parseFrom(data); SentBodyProto.Model bodyProto = SentBodyProto.Model.parseFrom(data);
SentBody body = new SentBody(); SentBody body = new SentBody();
body.setKey(bodyProto.getKey()); body.setKey(bodyProto.getKey());
body.setTimestamp(bodyProto.getTimestamp()); body.setTimestamp(bodyProto.getTimestamp());
body.putAll(bodyProto.getDataMap()); body.putAll(bodyProto.getDataMap());
logger.info(body.toString()); logger.info(body.toString());
return body; return body;
} }
return null; return null;
} }
/** /**
* 解析消息体长度 * 解析消息体长度
*
* @param type * @param type
* @param length * @param length
* @return * @return
*/ */
private int getContentLength(byte lv,byte hv){ private int getContentLength(byte lv, byte hv) {
int l = (lv & 0xff); int l = (lv & 0xff);
int h = (hv & 0xff); int h = (hv & 0xff);
return (l| (h <<= 8)); return (l | (h <<= 8));
} }
} }

View File

@ -45,7 +45,8 @@ public class WebMessageDecoder extends MessageDecoderAdapter {
public static final byte HAS_EXTEND_DATA = 126; public static final byte HAS_EXTEND_DATA = 126;
public static final byte HAS_EXTEND_DATA_CONTINUE = 127; public static final byte HAS_EXTEND_DATA_CONTINUE = 127;
public static final byte PAYLOADLEN = 0x7F;// 0111 1111 public static final byte PAYLOADLEN = 0x7F;// 0111 1111
public static final Pattern SEC_KEY_PATTERN = Pattern.compile("^(Sec-WebSocket-Key:).+",Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); public static final Pattern SEC_KEY_PATTERN = Pattern.compile("^(Sec-WebSocket-Key:).+",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
protected final Logger logger = Logger.getLogger(WebMessageDecoder.class); protected final Logger logger = Logger.getLogger(WebMessageDecoder.class);
@ -55,11 +56,10 @@ public class WebMessageDecoder extends MessageDecoderAdapter {
return NEED_DATA; return NEED_DATA;
} }
/** /**
* 原生SDK只会发送2种类型消息 1个心跳类型 另一个是sendbody报文的第一个字节为消息类型 * 原生SDK只会发送2种类型消息 1个心跳类型 另一个是sendbody报文的第一个字节为消息类型
* 如果非原生sdk发出的消息则认为是websocket发送的消息 * 如果非原生sdk发出的消息则认为是websocket发送的消息 websocket发送的消息 第一个字节不可能等于C_H_RS或者SENTBODY
* websocket发送的消息 第一个字节不可能等于C_H_RS或者SENTBODY */
*/
byte conetnType = iobuffer.get(); byte conetnType = iobuffer.get();
if (conetnType == CIMConstant.ProtobufType.C_H_RS || conetnType == CIMConstant.ProtobufType.SENTBODY) { if (conetnType == CIMConstant.ProtobufType.C_H_RS || conetnType == CIMConstant.ProtobufType.SENTBODY) {
return NOT_OK; return NOT_OK;
@ -104,7 +104,7 @@ public class WebMessageDecoder extends MessageDecoderAdapter {
} }
@Override @Override
public MessageDecoderResult decode(IoSession iosession, IoBuffer in, ProtocolDecoderOutput out)throws Exception { public MessageDecoderResult decode(IoSession iosession, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
in.get(); in.get();
byte head = in.get(); byte head = in.get();
byte datalength = (byte) (head & PAYLOADLEN); byte datalength = (byte) (head & PAYLOADLEN);
@ -121,26 +121,26 @@ public class WebMessageDecoder extends MessageDecoderAdapter {
// 获取掩码 // 获取掩码
byte[] mask = new byte[4]; byte[] mask = new byte[4];
in.get(mask); in.get(mask);
data = new byte[in.remaining()]; data = new byte[in.remaining()];
in.get(data); in.get(data);
for (int i = 0; i < data.length; i++) { for (int i = 0; i < data.length; i++) {
// 数据进行异或运算 // 数据进行异或运算
data[i] = (byte) (data[i] ^ mask[i % 4]); data[i] = (byte) (data[i] ^ mask[i % 4]);
} }
handleSentBodyAndHeartPing(data,out); handleSentBodyAndHeartPing(data, out);
} else { } else {
data = new byte[in.remaining()]; data = new byte[in.remaining()];
in.get(data); in.get(data);
handleWebsocketHandshake(new String(data, "UTF-8"),out); handleWebsocketHandshake(new String(data, "UTF-8"), out);
} }
return OK; return OK;
} }
private void handleWebsocketHandshake(String message,ProtocolDecoderOutput out) { private void handleWebsocketHandshake(String message, ProtocolDecoderOutput out) {
SentBody body = new SentBody(); SentBody body = new SentBody();
body.setKey(CIMNioSocketAcceptor.WEBSOCKET_HANDLER_KEY); body.setKey(CIMNioSocketAcceptor.WEBSOCKET_HANDLER_KEY);
Matcher m = SEC_KEY_PATTERN.matcher(message); Matcher m = SEC_KEY_PATTERN.matcher(message);
if (m.find()) { if (m.find()) {
String foundstring = m.group(); String foundstring = m.group();
@ -149,10 +149,9 @@ public class WebMessageDecoder extends MessageDecoderAdapter {
out.write(body); out.write(body);
} }
public void handleSentBodyAndHeartPing(byte[] data, ProtocolDecoderOutput out) throws UnsupportedEncodingException {
public void handleSentBodyAndHeartPing(byte[] data,ProtocolDecoderOutput out) throws UnsupportedEncodingException {
String message = new String(data, "UTF-8"); String message = new String(data, "UTF-8");
/** /**
* 只处理心跳响应以及sentbody消息 * 只处理心跳响应以及sentbody消息
*/ */
@ -160,12 +159,11 @@ public class WebMessageDecoder extends MessageDecoderAdapter {
HeartbeatResponse response = HeartbeatResponse.getInstance(); HeartbeatResponse response = HeartbeatResponse.getInstance();
logger.info(response.toString()); logger.info(response.toString());
out.write(response); out.write(response);
}else if(data.length > 2) } else if (data.length > 2) {
{
SentBody body = JSON.parseObject(message, SentBody.class); SentBody body = JSON.parseObject(message, SentBody.class);
logger.info(body.toString()); logger.info(body.toString());
out.write(body); out.write(body);
} }
} }
} }

View File

@ -47,108 +47,102 @@ import com.farsunset.cim.sdk.server.model.ReplyBody;
import com.farsunset.cim.sdk.server.model.SentBody; import com.farsunset.cim.sdk.server.model.SentBody;
import com.farsunset.cim.sdk.server.session.CIMSession; import com.farsunset.cim.sdk.server.session.CIMSession;
public class CIMNioSocketAcceptor extends IoHandlerAdapter implements KeepAliveMessageFactory{ public class CIMNioSocketAcceptor extends IoHandlerAdapter implements KeepAliveMessageFactory {
public final static String WEBSOCKET_HANDLER_KEY = "client_websocket_handshake"; public final static String WEBSOCKET_HANDLER_KEY = "client_websocket_handshake";
public final static String CIMSESSION_CLOSED_HANDLER_KEY = "client_cimsession_closed"; public final static String CIMSESSION_CLOSED_HANDLER_KEY = "client_cimsession_closed";
private Logger logger = Logger.getLogger(CIMNioSocketAcceptor.class); private Logger logger = Logger.getLogger(CIMNioSocketAcceptor.class);
private HashMap<String, CIMRequestHandler> handlers = new HashMap<String, CIMRequestHandler>(); private HashMap<String, CIMRequestHandler> handlers = new HashMap<String, CIMRequestHandler>();
private IoAcceptor acceptor; private IoAcceptor acceptor;
private int port; private int port;
private final int IDLE_TIME = 120;// private final int IDLE_TIME = 120;//
private final int TIME_OUT = 10;// private final int TIME_OUT = 10;//
private final int READ_BUFFER_SIZE = 1024;//byte private final int READ_BUFFER_SIZE = 1024;// byte
public void bind() throws IOException public void bind() throws IOException {
{
/**
* 预制websocket握手请求的处理
*/
handlers.put(WEBSOCKET_HANDLER_KEY, new WebsocketHandler());
acceptor = new NioSocketAcceptor();
acceptor.getSessionConfig().setReadBufferSize(READ_BUFFER_SIZE);
((DefaultSocketSessionConfig)acceptor.getSessionConfig()).setKeepAlive(true);
((DefaultSocketSessionConfig)acceptor.getSessionConfig()).setTcpNoDelay(true);
KeepAliveFilter keepAliveFilter = new KeepAliveFilter(this,IdleStatus.WRITER_IDLE);
keepAliveFilter.setRequestInterval(IDLE_TIME);
keepAliveFilter.setRequestTimeout(TIME_OUT);
keepAliveFilter.setForwardEvent(true);
acceptor.getFilterChain().addLast("executor",new ExecutorFilter());
acceptor.getFilterChain().addLast("logger",new LoggingFilter());
acceptor.getFilterChain().addLast("codec",new ProtocolCodecFilter(new ServerMessageCodecFactory()));
acceptor.getFilterChain().addLast("heartbeat",keepAliveFilter);
acceptor.setHandler(this); /**
* 预制websocket握手请求的处理
acceptor.bind(new InetSocketAddress(port)); */
} handlers.put(WEBSOCKET_HANDLER_KEY, new WebsocketHandler());
public void unbind() acceptor = new NioSocketAcceptor();
{ acceptor.getSessionConfig().setReadBufferSize(READ_BUFFER_SIZE);
acceptor.unbind(); ((DefaultSocketSessionConfig) acceptor.getSessionConfig()).setKeepAlive(true);
} ((DefaultSocketSessionConfig) acceptor.getSessionConfig()).setTcpNoDelay(true);
KeepAliveFilter keepAliveFilter = new KeepAliveFilter(this, IdleStatus.WRITER_IDLE);
public void sessionCreated(IoSession session) { keepAliveFilter.setRequestInterval(IDLE_TIME);
logger.warn("sessionCreated()... from "+session.getRemoteAddress()+" nid:" + session.getId()); keepAliveFilter.setRequestTimeout(TIME_OUT);
keepAliveFilter.setForwardEvent(true);
acceptor.getFilterChain().addLast("executor", new ExecutorFilter());
acceptor.getFilterChain().addLast("logger", new LoggingFilter());
acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ServerMessageCodecFactory()));
acceptor.getFilterChain().addLast("heartbeat", keepAliveFilter);
acceptor.setHandler(this);
acceptor.bind(new InetSocketAddress(port));
} }
public void messageReceived(IoSession ios, Object message){ public void unbind() {
acceptor.unbind();
}
public void sessionCreated(IoSession session) {
logger.warn("sessionCreated()... from " + session.getRemoteAddress() + " nid:" + session.getId());
}
public void messageReceived(IoSession ios, Object message) {
SentBody body = (SentBody) message; SentBody body = (SentBody) message;
CIMRequestHandler handler = handlers.get(body.getKey()); CIMRequestHandler handler = handlers.get(body.getKey());
if (handler == null) { if (handler == null) {
ReplyBody reply = new ReplyBody(); ReplyBody reply = new ReplyBody();
reply.setKey(body.getKey()); reply.setKey(body.getKey());
reply.setCode(CIMConstant.ReturnCode.CODE_404); reply.setCode(CIMConstant.ReturnCode.CODE_404);
reply.setMessage("KEY:"+body.getKey()+" not defined on server"); reply.setMessage("KEY:" + body.getKey() + " not defined on server");
ios.write(reply); ios.write(reply);
} else { } else {
ReplyBody reply = handler.process(new CIMSession(ios), body); ReplyBody reply = handler.process(new CIMSession(ios), body);
if(reply!=null) if (reply != null) {
{
reply.setKey(body.getKey()); reply.setKey(body.getKey());
ios.write(reply); ios.write(reply);
} }
} }
} }
/** /**
*/ */
public void sessionClosed(IoSession session) { public void sessionClosed(IoSession session) {
CIMSession cimSession =new CIMSession(session); CIMSession cimSession = new CIMSession(session);
logger.warn("sessionClosed()... from "+session.getRemoteAddress()+" nid:"+cimSession.getNid() +",isConnected:"+session.isConnected()); logger.warn("sessionClosed()... from " + session.getRemoteAddress() + " nid:" + cimSession.getNid()
+ ",isConnected:" + session.isConnected());
CIMRequestHandler handler = handlers.get(CIMSESSION_CLOSED_HANDLER_KEY); CIMRequestHandler handler = handlers.get(CIMSESSION_CLOSED_HANDLER_KEY);
if(handler!=null) if (handler != null) {
{
handler.process(cimSession, null); handler.process(cimSession, null);
} }
} }
/** /**
*/ */
public void sessionIdle(IoSession session, IdleStatus status) { public void sessionIdle(IoSession session, IdleStatus status) {
logger.warn("sessionIdle()... from "+session.getRemoteAddress()+" nid:" + session.getId()); logger.warn("sessionIdle()... from " + session.getRemoteAddress() + " nid:" + session.getId());
} }
/** /**
*/ */
public void exceptionCaught(IoSession session, Throwable cause){ public void exceptionCaught(IoSession session, Throwable cause) {
logger.error("exceptionCaught()... from "+session.getRemoteAddress()+" isConnected:"+session.isConnected()+" nid:" + session.getId(),cause); logger.error("exceptionCaught()... from " + session.getRemoteAddress() + " isConnected:" + session.isConnected()
+ " nid:" + session.getId(), cause);
session.closeNow(); session.closeNow();
} }
@ -157,8 +151,6 @@ public class CIMNioSocketAcceptor extends IoHandlerAdapter implements KeepAliveM
public void messageSent(IoSession session, Object message) throws Exception { public void messageSent(IoSession session, Object message) throws Exception {
} }
@Override @Override
public Object getRequest(IoSession session) { public Object getRequest(IoSession session) {
return HeartbeatRequest.getInstance(); return HeartbeatRequest.getInstance();
@ -178,26 +170,23 @@ public class CIMNioSocketAcceptor extends IoHandlerAdapter implements KeepAliveM
public boolean isResponse(IoSession arg0, Object arg1) { public boolean isResponse(IoSession arg0, Object arg1) {
return arg1 instanceof HeartbeatResponse; return arg1 instanceof HeartbeatResponse;
} }
public Map<Long,IoSession> getManagedSessions() public Map<Long, IoSession> getManagedSessions() {
{
return acceptor.getManagedSessions(); return acceptor.getManagedSessions();
} }
public IoSession getManagedSession(Long nid) public IoSession getManagedSession(Long nid) {
{ if (nid == null) {
if(nid == null)
{
return null; return null;
} }
return getManagedSessions().get(nid); return getManagedSessions().get(nid);
} }
public void setAcceptor(IoAcceptor acceptor) { public void setAcceptor(IoAcceptor acceptor) {
this.acceptor = acceptor; this.acceptor = acceptor;
} }
public void setPort(int port) { public void setPort(int port) {
this.port = port; this.port = port;
} }
@ -205,5 +194,5 @@ public class CIMNioSocketAcceptor extends IoHandlerAdapter implements KeepAliveM
public void setHandlers(HashMap<String, CIMRequestHandler> handlers) { public void setHandlers(HashMap<String, CIMRequestHandler> handlers) {
this.handlers = handlers; this.handlers = handlers;
} }
} }

View File

@ -28,8 +28,8 @@ package com.farsunset.cim.sdk.server.handler;
import com.farsunset.cim.sdk.server.model.ReplyBody; import com.farsunset.cim.sdk.server.model.ReplyBody;
import com.farsunset.cim.sdk.server.model.SentBody; import com.farsunset.cim.sdk.server.model.SentBody;
import com.farsunset.cim.sdk.server.session.CIMSession; import com.farsunset.cim.sdk.server.session.CIMSession;
public interface CIMRequestHandler {
ReplyBody process(CIMSession session,SentBody message); public interface CIMRequestHandler {
ReplyBody process(CIMSession session, SentBody message);
} }

View File

@ -27,8 +27,10 @@ import com.farsunset.cim.sdk.server.model.ReplyBody;
import com.farsunset.cim.sdk.server.model.SentBody; import com.farsunset.cim.sdk.server.model.SentBody;
import com.farsunset.cim.sdk.server.model.WebsocketResponse; import com.farsunset.cim.sdk.server.model.WebsocketResponse;
import com.farsunset.cim.sdk.server.session.CIMSession; import com.farsunset.cim.sdk.server.session.CIMSession;
/** /**
* 处理websocket握手请求返回响应的报文给浏览器 * 处理websocket握手请求返回响应的报文给浏览器
*
* @author Iraid * @author Iraid
* *
*/ */

View File

@ -26,35 +26,36 @@ import java.io.UnsupportedEncodingException;
import com.farsunset.cim.sdk.server.constant.CIMConstant; import com.farsunset.cim.sdk.server.constant.CIMConstant;
import com.farsunset.cim.sdk.server.model.feature.EncodeFormatable; import com.farsunset.cim.sdk.server.model.feature.EncodeFormatable;
/** /**
* 服务端心跳请求 * 服务端心跳请求
* *
*/ */
public class HeartbeatRequest implements Serializable,EncodeFormatable { public class HeartbeatRequest implements Serializable, EncodeFormatable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final String TAG = "SERVER_HEARTBEAT_REQUEST"; private static final String TAG = "SERVER_HEARTBEAT_REQUEST";
private static final String CMD_HEARTBEAT_RESPONSE = "SR"; private static final String CMD_HEARTBEAT_RESPONSE = "SR";
private static HeartbeatRequest object = new HeartbeatRequest(); private static HeartbeatRequest object = new HeartbeatRequest();
private HeartbeatRequest(){ private HeartbeatRequest() {
} }
public static HeartbeatRequest getInstance() { public static HeartbeatRequest getInstance() {
return object; return object;
} }
@Override @Override
public byte[] getProtobufBody() { public byte[] getProtobufBody() {
return CMD_HEARTBEAT_RESPONSE.getBytes(); return CMD_HEARTBEAT_RESPONSE.getBytes();
} }
public String toString(){ public String toString() {
return TAG; return TAG;
} }
@Override @Override
public byte[] getJSONBody() { public byte[] getJSONBody() {
try { try {
@ -65,10 +66,9 @@ public class HeartbeatRequest implements Serializable,EncodeFormatable {
return null; return null;
} }
@Override @Override
public byte getDataType() { public byte getDataType() {
return CIMConstant.ProtobufType.S_H_RQ; return CIMConstant.ProtobufType.S_H_RQ;
} }
} }

View File

@ -23,7 +23,6 @@ package com.farsunset.cim.sdk.server.model;
import java.io.Serializable; import java.io.Serializable;
/** /**
* 客户端心跳响应 * 客户端心跳响应
*/ */
@ -42,10 +41,8 @@ public class HeartbeatResponse implements Serializable {
return object; return object;
} }
public String toString() { public String toString() {
return TAG; return TAG;
} }
} }

View File

@ -27,20 +27,19 @@ import com.alibaba.fastjson.JSONObject;
import com.farsunset.cim.sdk.server.constant.CIMConstant; import com.farsunset.cim.sdk.server.constant.CIMConstant;
import com.farsunset.cim.sdk.server.model.feature.EncodeFormatable; import com.farsunset.cim.sdk.server.model.feature.EncodeFormatable;
import com.farsunset.cim.sdk.server.model.proto.MessageProto; import com.farsunset.cim.sdk.server.model.proto.MessageProto;
/** /**
* 消息对象 * 消息对象
*/ */
public class Message implements Serializable,EncodeFormatable { public class Message implements Serializable, EncodeFormatable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 消息类型用户自定义消息类别 * 消息类型用户自定义消息类别
*/ */
private String mid; private String mid;
/** /**
* 消息类型用户自定义消息类别 * 消息类型用户自定义消息类别
*/ */
@ -74,13 +73,11 @@ public class Message implements Serializable,EncodeFormatable {
private String extra; private String extra;
private long timestamp; private long timestamp;
public Message() {
public Message()
{
timestamp = System.currentTimeMillis(); timestamp = System.currentTimeMillis();
} }
public long getTimestamp() { public long getTimestamp() {
return timestamp; return timestamp;
} }
@ -89,14 +86,14 @@ public class Message implements Serializable,EncodeFormatable {
this.timestamp = timestamp; this.timestamp = timestamp;
} }
public String getAction() { public String getAction() {
return action; return action;
} }
public void setAction(String action) { public void setAction(String action) {
this.action = action; this.action = action;
} }
public String getTitle() { public String getTitle() {
return title; return title;
} }
@ -129,7 +126,6 @@ public class Message implements Serializable,EncodeFormatable {
this.receiver = receiver; this.receiver = receiver;
} }
public String getFormat() { public String getFormat() {
return format; return format;
} }
@ -137,17 +133,14 @@ public class Message implements Serializable,EncodeFormatable {
public void setFormat(String format) { public void setFormat(String format) {
this.format = format; this.format = format;
} }
public String getExtra() { public String getExtra() {
return extra; return extra;
} }
public void setExtra(String extra) { public void setExtra(String extra) {
this.extra = extra; this.extra = extra;
} }
public String getMid() { public String getMid() {
return mid; return mid;
@ -156,7 +149,7 @@ public class Message implements Serializable,EncodeFormatable {
public void setMid(String mid) { public void setMid(String mid) {
this.mid = mid; this.mid = mid;
} }
@Override @Override
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
@ -174,8 +167,9 @@ public class Message implements Serializable,EncodeFormatable {
} }
public boolean isNotEmpty(String txt) { public boolean isNotEmpty(String txt) {
return txt != null && txt.trim().length()!=0; return txt != null && txt.trim().length() != 0;
} }
@Override @Override
public byte[] getProtobufBody() { public byte[] getProtobufBody() {
MessageProto.Model.Builder builder = MessageProto.Model.newBuilder(); MessageProto.Model.Builder builder = MessageProto.Model.newBuilder();
@ -188,21 +182,21 @@ public class Message implements Serializable,EncodeFormatable {
/** /**
* 下面字段可能为空 * 下面字段可能为空
*/ */
if(content!=null){ if (content != null) {
builder.setContent(content); builder.setContent(content);
} }
if(title!=null){ if (title != null) {
builder.setTitle(title); builder.setTitle(title);
} }
if(extra!=null){ if (extra != null) {
builder.setExtra(extra); builder.setExtra(extra);
} }
if(format!=null){ if (format != null) {
builder.setFormat(format); builder.setFormat(format);
} }
return builder.build().toByteArray(); return builder.build().toByteArray();
} }
@Override @Override
public byte[] getJSONBody() { public byte[] getJSONBody() {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
@ -224,6 +218,7 @@ public class Message implements Serializable,EncodeFormatable {
} }
return null; return null;
} }
@Override @Override
public byte getDataType() { public byte getDataType() {
return CIMConstant.ProtobufType.MESSAGE; return CIMConstant.ProtobufType.MESSAGE;

View File

@ -31,25 +31,25 @@ import com.alibaba.fastjson.JSONObject;
import com.farsunset.cim.sdk.server.constant.CIMConstant; import com.farsunset.cim.sdk.server.constant.CIMConstant;
import com.farsunset.cim.sdk.server.model.feature.EncodeFormatable; import com.farsunset.cim.sdk.server.model.feature.EncodeFormatable;
import com.farsunset.cim.sdk.server.model.proto.ReplyBodyProto; import com.farsunset.cim.sdk.server.model.proto.ReplyBodyProto;
/** /**
* 请求应答对象 * 请求应答对象
* *
*/ */
public class ReplyBody implements Serializable ,EncodeFormatable{ public class ReplyBody implements Serializable, EncodeFormatable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 请求key * 请求key
*/ */
private String key; private String key;
/** /**
* 返回码 * 返回码
*/ */
private String code; private String code;
/** /**
* 返回说明 * 返回说明
*/ */
@ -60,13 +60,12 @@ public class ReplyBody implements Serializable ,EncodeFormatable{
*/ */
private HashMap<String, String> data = new HashMap<String, String>(); private HashMap<String, String> data = new HashMap<String, String>();
private long timestamp; private long timestamp;
public ReplyBody() public ReplyBody() {
{
timestamp = System.currentTimeMillis(); timestamp = System.currentTimeMillis();
} }
public long getTimestamp() { public long getTimestamp() {
return timestamp; return timestamp;
} }
@ -75,8 +74,6 @@ public class ReplyBody implements Serializable ,EncodeFormatable{
this.timestamp = timestamp; this.timestamp = timestamp;
} }
public String getKey() { public String getKey() {
return key; return key;
} }
@ -86,15 +83,15 @@ public class ReplyBody implements Serializable ,EncodeFormatable{
} }
public void put(String k, String v) { public void put(String k, String v) {
if(v!=null && k!=null){ if (v != null && k != null) {
data.put(k, v); data.put(k, v);
} }
} }
public void putAll(Map<String, String> map) { public void putAll(Map<String, String> map) {
data.putAll(map); data.putAll(map);
} }
public String get(String k) { public String get(String k) {
return data.get(k); return data.get(k);
} }
@ -111,7 +108,7 @@ public class ReplyBody implements Serializable ,EncodeFormatable{
this.message = message; this.message = message;
} }
public Set<String> getKeySet() { public Set<String> getKeySet() {
return data.keySet(); return data.keySet();
} }
@ -124,45 +121,45 @@ public class ReplyBody implements Serializable ,EncodeFormatable{
} }
@Override @Override
public String toString() public String toString() {
{
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("#ReplyBody#").append("\n"); buffer.append("#ReplyBody#").append("\n");
buffer.append("key:").append(this.getKey()).append("\n"); buffer.append("key:").append(this.getKey()).append("\n");
buffer.append("timestamp:").append(timestamp).append("\n"); buffer.append("timestamp:").append(timestamp).append("\n");
buffer.append("code:").append(code).append("\n"); buffer.append("code:").append(code).append("\n");
if(!data.isEmpty()){ if (!data.isEmpty()) {
buffer.append("data{").append("\n"); buffer.append("data{").append("\n");
for(String key:getKeySet()) for (String key : getKeySet()) {
{
buffer.append(key).append(":").append(this.get(key)).append("\n"); buffer.append(key).append(":").append(this.get(key)).append("\n");
} }
buffer.append("}"); buffer.append("}");
} }
return buffer.toString(); return buffer.toString();
} }
@Override @Override
public byte[] getProtobufBody() { public byte[] getProtobufBody() {
ReplyBodyProto.Model.Builder builder = ReplyBodyProto.Model.newBuilder(); ReplyBodyProto.Model.Builder builder = ReplyBodyProto.Model.newBuilder();
builder.setCode(code); builder.setCode(code);
if(message!=null){ if (message != null) {
builder.setMessage(message); builder.setMessage(message);
} }
if(!data.isEmpty()){ if (!data.isEmpty()) {
builder.putAllData(data); builder.putAllData(data);
} }
builder.setKey(key); builder.setKey(key);
builder.setTimestamp(timestamp); builder.setTimestamp(timestamp);
return builder.build().toByteArray(); return builder.build().toByteArray();
} }
@Override @Override
public byte getDataType() { public byte getDataType() {
return CIMConstant.ProtobufType.REPLYBODY; return CIMConstant.ProtobufType.REPLYBODY;
} }
@Override @Override
public byte[] getJSONBody() { public byte[] getJSONBody() {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();

View File

@ -25,6 +25,7 @@ import java.io.Serializable;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
/** /**
* java |android 客户端请求结构 * java |android 客户端请求结构
* *
@ -59,43 +60,41 @@ public class SentBody implements Serializable {
this.key = key; this.key = key;
} }
public void remove(String k) { public void remove(String k) {
data.remove(k); data.remove(k);
} }
public void put(String k, String v) { public void put(String k, String v) {
if(v!=null && k!=null){ if (v != null && k != null) {
data.put(k, v); data.put(k, v);
} }
} }
public void putAll(Map<String, String> map) { public void putAll(Map<String, String> map) {
data.putAll(map); data.putAll(map);
} }
public Set<String> getKeySet() { public Set<String> getKeySet() {
return data.keySet(); return data.keySet();
} }
@Override @Override
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("#SentBody#").append("\n");; buffer.append("#SentBody#").append("\n");
;
buffer.append("key:").append(key).append("\n"); buffer.append("key:").append(key).append("\n");
buffer.append("timestamp:").append(timestamp).append("\n"); buffer.append("timestamp:").append(timestamp).append("\n");
if(!data.isEmpty()){ if (!data.isEmpty()) {
buffer.append("data{").append("\n"); buffer.append("data{").append("\n");
for(String key:getKeySet()) for (String key : getKeySet()) {
{
buffer.append(key).append(":").append(this.get(key)).append("\n"); buffer.append(key).append(":").append(this.get(key)).append("\n");
} }
buffer.append("}"); buffer.append("}");
} }
return buffer.toString(); return buffer.toString();
} }
} }

View File

@ -22,26 +22,28 @@
package com.farsunset.cim.sdk.server.model; package com.farsunset.cim.sdk.server.model;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
/** /**
*websocket握手响应结果 * websocket握手响应结果
* *
*/ */
public class WebsocketResponse{ public class WebsocketResponse {
private String token; private String token;
public WebsocketResponse(String token) { public WebsocketResponse(String token) {
this.token = token; this.token = token;
} }
public byte[] getBytes() { public byte[] getBytes() {
try { try {
return toString().getBytes("UTF-8"); return toString().getBytes("UTF-8");
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
e.printStackTrace(); e.printStackTrace();
} }
return null; return null;
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
@ -55,7 +57,7 @@ public class WebsocketResponse{
builder.append("\r\n"); builder.append("\r\n");
builder.append("\r\n"); builder.append("\r\n");
return builder.toString(); return builder.toString();
} }
} }

View File

@ -20,11 +20,14 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.server.model.feature; package com.farsunset.cim.sdk.server.model.feature;
/** /**
* 需要向另一端发送的结构体 * 需要向另一端发送的结构体
*/ */
public interface EncodeFormatable { public interface EncodeFormatable {
byte[] getProtobufBody(); byte[] getProtobufBody();
byte[] getJSONBody(); byte[] getJSONBody();
byte getDataType(); byte getDataType();
} }

View File

@ -35,56 +35,53 @@ import com.farsunset.cim.sdk.server.constant.CIMConstant;
* IoSession包装类,集群时 将此对象存入表中 * IoSession包装类,集群时 将此对象存入表中
*/ */
public class CIMSession implements Serializable{ public class CIMSession implements Serializable {
/** /**
* *
*/ */
private transient static final long serialVersionUID = 1L; private transient static final long serialVersionUID = 1L;
public transient static String ID = "ID"; public transient static String ID = "ID";
public transient static String HOST = "HOST"; public transient static String HOST = "HOST";
public transient static final int STATUS_ENABLED = 0; public transient static final int STATUS_ENABLED = 0;
public transient static final int STATUS_DISABLED = 1; public transient static final int STATUS_DISABLED = 1;
public transient static final int APNS_ON=1; public transient static final int APNS_ON = 1;
public transient static final int APNS_OFF=0; public transient static final int APNS_OFF = 0;
public transient static String CHANNEL_IOS = "ios"; public transient static String CHANNEL_IOS = "ios";
public transient static String CHANNEL_ANDROID = "android"; public transient static String CHANNEL_ANDROID = "android";
public transient static String CHANNEL_WINDOWS = "windows"; public transient static String CHANNEL_WINDOWS = "windows";
public transient static String CHANNEL_WP = "wp"; public transient static String CHANNEL_WP = "wp";
public transient static String CHANNEL_BROWSER = "browser"; public transient static String CHANNEL_BROWSER = "browser";
private transient IoSession session; private transient IoSession session;
private String gid;//session全局ID private String gid;// session全局ID
private Long nid;//session在本台服务器上的ID private Long nid;// session在本台服务器上的ID
private String deviceId;//客户端ID (设备号码+应用包名),ios为devicetoken private String deviceId;// 客户端ID (设备号码+应用包名),ios为devicetoken
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 clientVersion;//终端应用版本 private String clientVersion;// 终端应用版本
private String systemVersion;//终端系统版本 private String systemVersion;// 终端系统版本
private String packageName;//终端应用包名 private String packageName;// 终端应用包名
private Long bindTime;//登录时间 private Long bindTime;// 登录时间
private Long heartbeat;//心跳时间 private Long heartbeat;// 心跳时间
private Double longitude;//经度 private Double longitude;// 经度
private Double latitude;//维度 private Double latitude;// 维度
private String location;//位置 private String location;// 位置
private int apnsAble;//apns推送状态 private int apnsAble;// apns推送状态
private int status;// 状态 private int status;// 状态
public CIMSession(IoSession session) { public CIMSession(IoSession session) {
this.session = session; this.session = session;
this.nid = session.getId(); this.nid = session.getId();
} }
public CIMSession() public CIMSession() {
{
} }
public String getAccount() { public String getAccount() {
return account; return account;
@ -92,15 +89,10 @@ public class CIMSession implements Serializable{
public void setAccount(String account) { public void setAccount(String account) {
this.account = account; this.account = account;
setAttribute(CIMConstant.SESSION_KEY, account); setAttribute(CIMConstant.SESSION_KEY, account);
} }
public Double getLongitude() { public Double getLongitude() {
return longitude; return longitude;
} }
@ -133,9 +125,9 @@ public class CIMSession implements Serializable{
} }
public void setGid(String gid) { public void setGid(String gid) {
this.gid = gid; this.gid = gid;
setAttribute("gid", gid); setAttribute("gid", gid);
} }
@ -151,14 +143,13 @@ public class CIMSession implements Serializable{
return deviceId; return deviceId;
} }
public String getChannel() { public String getChannel() {
return channel; return channel;
} }
public void setChannel(String channel) { public void setChannel(String channel) {
this.channel = channel; this.channel = channel;
setAttribute("channel", channel); setAttribute("channel", channel);
} }
@ -168,35 +159,29 @@ public class CIMSession implements Serializable{
public void setDeviceModel(String deviceModel) { public void setDeviceModel(String deviceModel) {
this.deviceModel = deviceModel; this.deviceModel = deviceModel;
setAttribute("deviceModel", deviceModel); setAttribute("deviceModel", deviceModel);
} }
public void setDeviceId(String deviceId) { public void setDeviceId(String deviceId) {
this.deviceId = deviceId; this.deviceId = deviceId;
setAttribute("deviceId", deviceId); setAttribute("deviceId", deviceId);
} }
public String getHost() { public String getHost() {
return host; return host;
} }
public Long getBindTime() { public Long getBindTime() {
return bindTime; return bindTime;
} }
public void setBindTime(Long bindTime) { public void setBindTime(Long bindTime) {
this.bindTime = bindTime; this.bindTime = bindTime;
setAttribute("bindTime", bindTime); setAttribute("bindTime", bindTime);
} }
public String getClientVersion() { public String getClientVersion() {
return clientVersion; return clientVersion;
} }
@ -206,10 +191,6 @@ public class CIMSession implements Serializable{
setAttribute("clientVersion", clientVersion); setAttribute("clientVersion", clientVersion);
} }
public String getSystemVersion() { public String getSystemVersion() {
return systemVersion; return systemVersion;
} }
@ -230,13 +211,10 @@ public class CIMSession implements Serializable{
public void setHost(String host) { public void setHost(String host) {
this.host = host; this.host = host;
setAttribute("host", host); setAttribute("host", host);
} }
public int getApnsAble() { public int getApnsAble() {
return apnsAble; return apnsAble;
} }
@ -255,64 +233,58 @@ public class CIMSession implements Serializable{
setAttribute("status", status); setAttribute("status", status);
} }
public void setAttribute(String key, Object value) { public void setAttribute(String key, Object value) {
if(session!=null) if (session != null)
session.setAttribute(key, value); session.setAttribute(key, value);
} }
public boolean containsAttribute(String key) { public boolean containsAttribute(String key) {
if(session!=null) if (session != null)
return session.containsAttribute(key); return session.containsAttribute(key);
return false; return false;
} }
public Object getAttribute(String key) { public Object getAttribute(String key) {
if(session!=null) if (session != null)
return session.getAttribute(key); return session.getAttribute(key);
return null; return null;
} }
public void removeAttribute(String key) { public void removeAttribute(String key) {
if(session!=null) if (session != null)
session.removeAttribute(key); session.removeAttribute(key);
} }
public SocketAddress getRemoteAddress() { public SocketAddress getRemoteAddress() {
if(session!=null) if (session != null)
return session.getRemoteAddress(); return session.getRemoteAddress();
return null; return null;
} }
public boolean write(Object msg) { public boolean write(Object msg) {
if(session!=null) if (session != null) {
{ WriteFuture future = session.write(msg);
WriteFuture future = session.write(msg); future.awaitUninterruptibly(10 * 1000);
future.awaitUninterruptibly(10 * 1000);
return future.isWritten(); return future.isWritten();
} }
return false; return false;
} }
public boolean isConnected() { public boolean isConnected() {
if(session != null) if (session != null) {
{
return session.isConnected(); return session.isConnected();
} }
if(!isLocalhost()) if (!isLocalhost()) {
{
return status == STATUS_ENABLED; return status == STATUS_ENABLED;
} }
return false; return false;
} }
public boolean isLocalhost() public boolean isLocalhost() {
{
try { try {
String ip = InetAddress.getLocalHost().getHostAddress(); String ip = InetAddress.getLocalHost().getHostAddress();
return ip.equals(host); return ip.equals(host);
@ -320,20 +292,18 @@ public class CIMSession implements Serializable{
e.printStackTrace(); e.printStackTrace();
} }
return false; return false;
} }
public void closeNow() { public void closeNow() {
if(session!=null) if (session != null)
session.closeNow(); session.closeNow();
} }
public void closeOnFlush() { public void closeOnFlush() {
if(session!=null) if (session != null)
session.closeOnFlush(); session.closeOnFlush();
} }
public void setPackageName(String packageName) { public void setPackageName(String packageName) {
this.packageName = packageName; this.packageName = packageName;
@ -343,39 +313,37 @@ public class CIMSession implements Serializable{
public String getPackageName() { public String getPackageName() {
return packageName; return packageName;
} }
public int hashCode() {
public int hashCode(){
return (deviceId + nid + host).hashCode(); return (deviceId + nid + host).hashCode();
} }
public boolean equals(Object o) { public boolean equals(Object o) {
if(o instanceof CIMSession){ if (o instanceof CIMSession) {
return hashCode() == o.hashCode(); return hashCode() == o.hashCode();
} }
return false; return false;
} }
public boolean fromOtherDevice(Object o) { public boolean fromOtherDevice(Object o) {
if (o instanceof CIMSession) { if (o instanceof CIMSession) {
CIMSession t = (CIMSession) o; CIMSession t = (CIMSession) o;
if(t.deviceId!=null && deviceId!=null) if (t.deviceId != null && deviceId != null) {
{
return !t.deviceId.equals(deviceId); return !t.deviceId.equals(deviceId);
} }
} }
return false; return false;
} }
public boolean fromCurrentDevice(Object o) { public boolean fromCurrentDevice(Object o) {
return !fromOtherDevice(o); return !fromOtherDevice(o);
} }
public void setIoSession(IoSession session) { public void setIoSession(IoSession session) {
this.session = session; this.session = session;
} }
@ -383,30 +351,26 @@ public class CIMSession implements Serializable{
public IoSession getIoSession() { public IoSession getIoSession() {
return session; return session;
} }
public String toString() {
StringBuffer buffer = new StringBuffer();
public String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append("{"); buffer.append("{");
buffer.append("\"").append("gid").append("\":").append("\"").append(gid).append("\"").append(","); buffer.append("\"").append("gid").append("\":").append("\"").append(gid).append("\"").append(",");
buffer.append("\"").append("nid").append("\":").append(nid).append(","); buffer.append("\"").append("nid").append("\":").append(nid).append(",");
buffer.append("\"").append("deviceId").append("\":").append("\"").append(deviceId).append("\"").append(","); buffer.append("\"").append("deviceId").append("\":").append("\"").append(deviceId).append("\"").append(",");
buffer.append("\"").append("host").append("\":").append("\"").append(host).append("\"").append(","); buffer.append("\"").append("host").append("\":").append("\"").append(host).append("\"").append(",");
buffer.append("\"").append("account").append("\":").append("\"").append(account).append("\"").append(","); buffer.append("\"").append("account").append("\":").append("\"").append(account).append("\"").append(",");
buffer.append("\"").append("channel").append("\":").append("\"").append(channel).append("\"").append(","); buffer.append("\"").append("channel").append("\":").append("\"").append(channel).append("\"").append(",");
buffer.append("\"").append("deviceModel").append("\":").append("\"").append(deviceModel).append("\"").append(","); buffer.append("\"").append("deviceModel").append("\":").append("\"").append(deviceModel).append("\"")
.append(",");
buffer.append("\"").append("status").append("\":").append(status).append(","); buffer.append("\"").append("status").append("\":").append(status).append(",");
buffer.append("\"").append("apnsAble").append("\":").append(apnsAble).append(","); buffer.append("\"").append("apnsAble").append("\":").append(apnsAble).append(",");
buffer.append("\"").append("bindTime").append("\":").append(bindTime).append(","); buffer.append("\"").append("bindTime").append("\":").append(bindTime).append(",");
buffer.append("\"").append("heartbeat").append("\":").append(heartbeat); buffer.append("\"").append("heartbeat").append("\":").append(heartbeat);
buffer.append("}"); buffer.append("}");
return buffer.toString(); return buffer.toString();
} }
} }

View File

@ -20,6 +20,7 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.server.session; package com.farsunset.cim.sdk.server.session;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -27,70 +28,57 @@ import java.util.concurrent.atomic.AtomicInteger;
import com.farsunset.cim.sdk.server.constant.CIMConstant; import com.farsunset.cim.sdk.server.constant.CIMConstant;
/** /**
* 自带默认 session管理实现 各位可以自行实现 AbstractSessionManager接口来实现自己的 session管理 * 自带默认 session管理实现 各位可以自行实现 AbstractSessionManager接口来实现自己的 session管理 服务器集群时
*服务器集群时 须要将CIMSession 信息存入数据库或者nosql 第三方存储空间中便于所有服务器都可以访问 * 须要将CIMSession 信息存入数据库或者nosql 第三方存储空间中便于所有服务器都可以访问
*/ */
public class DefaultSessionManager implements SessionManager{ public class DefaultSessionManager implements SessionManager {
private static HashMap<String, CIMSession> sessions = new HashMap<String, CIMSession>();
private static HashMap<String,CIMSession> sessions =new HashMap<String,CIMSession>(); private static final AtomicInteger connectionsCounter = new AtomicInteger(0);
private static final AtomicInteger connectionsCounter = new AtomicInteger(0);
/** /**
* *
*/ */
public void add(CIMSession session) { public void add(CIMSession session) {
if(session!=null) if (session != null) {
{ session.setAttribute(CIMConstant.SESSION_KEY, session.getAccount());
session.setAttribute(CIMConstant.SESSION_KEY, session.getAccount()); sessions.put(session.getAccount(), session);
sessions.put(session.getAccount(), session); connectionsCounter.incrementAndGet();
connectionsCounter.incrementAndGet(); }
}
}
}
public CIMSession get(String account) {
return sessions.get(account);
}
public CIMSession get(String account) {
public List<CIMSession> queryAll() {
List<CIMSession> list = new ArrayList<CIMSession>();
list.addAll(sessions.values());
return list;
}
public void remove(CIMSession session) {
sessions.remove(session.getAttribute(CIMConstant.SESSION_KEY));
}
return sessions.get(account);
public void remove(String account) { }
sessions.remove(account);
}
public boolean containsCIMSession(String account)
{
return sessions.containsKey(account);
}
public List<CIMSession> queryAll() {
List<CIMSession> list = new ArrayList<CIMSession>();
list.addAll(sessions.values());
return list;
}
public void remove(CIMSession session) {
sessions.remove(session.getAttribute(CIMConstant.SESSION_KEY));
}
public void remove(String account) {
sessions.remove(account);
}
public boolean containsCIMSession(String account) {
return sessions.containsKey(account);
}
@Override @Override
public void update(CIMSession session) { public void update(CIMSession session) {
sessions.put(session.getAccount(), session); sessions.put(session.getAccount(), session);
} }
} }

View File

@ -23,43 +23,42 @@ package com.farsunset.cim.sdk.server.session;
import java.util.List; import java.util.List;
/** /**
* 客户端的 session管理接口 * 客户端的 session管理接口 可自行实现此接口管理session
* 可自行实现此接口管理session
*/ */
public interface SessionManager {
public interface SessionManager {
/** /**
* 添加新的session * 添加新的session
*/ */
public void add(CIMSession session); public void add(CIMSession session);
/** /**
* 更新session * 更新session
*/ */
public void update(CIMSession session); public void update(CIMSession session);
/** /**
* *
* @param account 客户端session的 key 一般可用 用户账号来对应session * @param account
* 客户端session的 key 一般可用 用户账号来对应session
* @return * @return
*/ */
CIMSession get(String account); CIMSession get(String account);
/** /**
* 获取所有session * 获取所有session
*
* @return * @return
*/ */
public List<CIMSession> queryAll(); public List<CIMSession> queryAll();
/**
/**
* 删除session * 删除session
*
* @param session * @param session
*/ */
public void remove(String account); public void remove(String account);
} }

View File

@ -5,6 +5,8 @@ var SDK_VERSION = "1.0.0";
var SDK_CHANNEL = "browser"; var SDK_CHANNEL = "browser";
var APP_PACKAGE = "com.farsunset.webcim"; var APP_PACKAGE = "com.farsunset.webcim";
var ACCOUNT; var ACCOUNT;
const ACTION_999 = "999";//特殊的消息类型,代表被服务端强制下线
var socket; var socket;
var manualStop = false; var manualStop = false;
var CIMWebBridge = new Object(); var CIMWebBridge = new Object();
@ -36,7 +38,13 @@ CIMWebBridge.stop = function(){
manualStop = true; manualStop = true;
socket.close(); socket.close();
}; };
CIMWebBridge.resume = function(){
manualStop = false;
CIMWebBridge.connection();
};
CIMWebBridge.innerOnConnectionSuccessed = function(){ CIMWebBridge.innerOnConnectionSuccessed = function(){
if(typeof onConnectionSuccessed != 'undefined' && onConnectionSuccessed instanceof Function){ if(typeof onConnectionSuccessed != 'undefined' && onConnectionSuccessed instanceof Function){
onConnectionSuccessed(); onConnectionSuccessed();
@ -53,12 +61,13 @@ CIMWebBridge.innerOnMessageReceived = function(e){
*/ */
if(data == CMD_HEARTBEAT_REQUEST){ if(data == CMD_HEARTBEAT_REQUEST){
socket.send(CMD_HEARTBEAT_RESPONSE); socket.send(CMD_HEARTBEAT_RESPONSE);
return return;
} }
var json = JSON.parse(data); var json = JSON.parse(data);
if(json.contentType == "Message" && typeof onMessageReceived != 'undefined' && onMessageReceived instanceof Function){ if(json.contentType == "Message"){
onMessageReceived(json); onInterceptMessageReceived(json);
return;
} }
if(json.contentType == "ReplyBody" && typeof onReplyReceived != 'undefined' && onReplyReceived instanceof Function){ if(json.contentType == "ReplyBody" && typeof onReplyReceived != 'undefined' && onReplyReceived instanceof Function){
@ -76,6 +85,17 @@ CIMWebBridge.sendRequest = function(body){
socket.send(json); socket.send(json);
}; };
function onInterceptMessageReceived(message){
//被强制下线之后,不再继续连接服务端
if(message.action == ACTION_999){
manualStop = true;
}
//收到消息后,将消息发送给页面
if(onMessageReceived instanceof Function){
onMessageReceived(message);
}
}
function getBrowser() { function getBrowser() {
var explorer = window.navigator.userAgent.toLowerCase() ; var explorer = window.navigator.userAgent.toLowerCase() ;
// ie // ie

View File

@ -49,6 +49,11 @@
function onMessageReceived(message) function onMessageReceived(message)
{ {
if(message.acction == ACTION_999){
doHideDialog('MessageDialog');
doShowDialog('LoginDialog');
return ;
}
$("#messageList").append("<div class='alert alert-info' >"+message.content+"</div>"); $("#messageList").append("<div class='alert alert-info' >"+message.content+"</div>");
} }

View File

@ -21,7 +21,6 @@
*/ */
package com.farsunset.cim.admin.action; package com.farsunset.cim.admin.action;
import java.io.IOException; import java.io.IOException;
import org.apache.struts2.ServletActionContext; import org.apache.struts2.ServletActionContext;
@ -32,35 +31,31 @@ import com.farsunset.cim.sdk.server.model.Message;
import com.farsunset.cim.sdk.server.session.DefaultSessionManager; import com.farsunset.cim.sdk.server.session.DefaultSessionManager;
import com.farsunset.cim.util.ContextHolder; import com.farsunset.cim.util.ContextHolder;
import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ActionSupport;
public class SessionAction extends ActionSupport { public class SessionAction extends ActionSupport {
/** /**
* *
*/ */
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public String list() {
ServletActionContext.getRequest().setAttribute("sessionList",
((DefaultSessionManager) ContextHolder.getBean("CIMSessionManager")).queryAll());
public String list()
{ return "list";
ServletActionContext.getRequest().setAttribute("sessionList", ((DefaultSessionManager) ContextHolder.getBean("CIMSessionManager")).queryAll());
return "list";
} }
public void offline() throws IOException public void offline() throws IOException {
{
String account = ServletActionContext.getRequest().getParameter("account");
String account = ServletActionContext.getRequest().getParameter("account"); Message msg = new Message();
Message msg = new Message(); msg.setAction(CIMConstant.MessageAction.ACTION_999);// 强行下线消息类型
msg.setAction(CIMConstant.MessageAction.ACTION_999);//强行下线消息类型 msg.setReceiver(account);
msg.setReceiver(account);
// 向客户端 发送消息
//向客户端 发送消息 ContextHolder.getBean(SystemMessagePusher.class).push(msg);
ContextHolder.getBean(SystemMessagePusher.class).push(msg);
} }
} }

View File

@ -37,108 +37,92 @@ import com.google.gson.Gson;
import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven; import com.opensymphony.xwork2.ModelDriven;
/** /**
* *
* @author farsunset (3979434@qq.com) * @author farsunset (3979434@qq.com)
*/ */
public class MessageAction extends ActionSupport implements ModelDriven<Message>{ public class MessageAction extends ActionSupport implements ModelDriven<Message> {
/** /**
* *
*/ */
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
Message message = new Message(); Message message = new Message();
/** /**
* 关于http参数获取 struts2 的模型驱动 比如 http 参数 sender=xiaomao&receiver=xiaogou * 关于http参数获取 struts2 的模型驱动 比如 http 参数 sender=xiaomao&receiver=xiaogou
* struts自动会将参数的值 存入getModel()返回的对象的对应属性中即xiaomao会存入message.sender属性,xiaogou会存入message.receiver属性 * struts自动会将参数的值
* 省去了request.getParameter("sender")方式获取参数如果参数名在getModel()返回的对象中不存在则需要用request.getParameter()获取 * 存入getModel()返回的对象的对应属性中即xiaomao会存入message.sender属性,xiaogou会存入message.receiver属性
* 其他相关*Action.java中 同理这里做统一说明! * 省去了request.getParameter("sender")方式获取参数如果参数名在getModel()返回的对象中不存在则需要用request.getParameter()获取
*/ * 其他相关*Action.java中 同理这里做统一说明!
public String send() throws Exception { */
public String send() throws Exception {
HashMap<String,Object> datamap = new HashMap<String,Object>();
HashMap<String,String> data = new HashMap<String,String>(); HashMap<String, Object> datamap = new HashMap<String, Object>();
HashMap<String, String> data = new HashMap<String, String>();
ServletActionContext.getResponse().setContentType("text/json;charset=UTF-8"); ServletActionContext.getResponse().setContentType("text/json;charset=UTF-8");
datamap.put("code", 200); datamap.put("code", 200);
try{ try {
checkParams(); checkParams();
message.setMid(StringUtil.getUUID()); message.setMid(StringUtil.getUUID());
if(Constants.MessageType.TYPE_2.equals(message.getAction())) if (Constants.MessageType.TYPE_2.equals(message.getAction())) {
{ // 向客户端 发送消息
//向客户端 发送消息 ContextHolder.getBean(SystemMessagePusher.class).push(message);
ContextHolder.getBean(SystemMessagePusher.class).push(message); } else {
}else // 向客户端 发送消息
{ ((DefaultMessagePusher) ContextHolder.getBean("messagePusher")).push(message);
//向客户端 发送消息
((DefaultMessagePusher)ContextHolder.getBean("messagePusher")).push(message);
} }
data.put("id", message.getMid()); data.put("id", message.getMid());
data.put("createTime", String.valueOf(message.getTimestamp())); data.put("createTime", String.valueOf(message.getTimestamp()));
datamap.put("data", data); datamap.put("data", data);
}catch(Exception e){ } catch (Exception e) {
datamap.put("code", 500); datamap.put("code", 500);
e.printStackTrace(); e.printStackTrace();
} }
ServletActionContext.getResponse().getWriter().print(new Gson().toJson(datamap));
return null;
}
ServletActionContext.getResponse().getWriter().print(new Gson().toJson(datamap));
/** return null;
* 文件由客户端发往阿里云 OSS 存储 }
* @param messageServiceImpl
*/ /**
/* private void fileHandler(Message mo, HttpServletRequest request) throws IOException * 文件由客户端发往阿里云 OSS 存储
{ *
if(request instanceof MultiPartRequestWrapper){ * @param messageServiceImpl
MultiPartRequestWrapper pr = (MultiPartRequestWrapper) request; */
if(pr.getFiles("file")!=null) /*
{ * private void fileHandler(Message mo, HttpServletRequest request) throws
File file = pr.getFiles("file")[0]; * IOException { if(request instanceof MultiPartRequestWrapper){
* MultiPartRequestWrapper pr = (MultiPartRequestWrapper) request;
String fileType = request.getParameter("fileType"); * if(pr.getFiles("file")!=null) { File file = pr.getFiles("file")[0];
String dir = dirMap.get(fileType); *
if(StringUtils.isEmpty(dir)) * String fileType = request.getParameter("fileType"); String dir =
{ * dirMap.get(fileType); if(StringUtils.isEmpty(dir)) { throw new
throw new IllegalArgumentException("fileType:" +fileType+" 未定义" ); * IllegalArgumentException("fileType:" +fileType+" 未定义" );
*
} * } String path = request.getSession().getServletContext().getRealPath(dir);
String path = request.getSession().getServletContext().getRealPath(dir); * String uuid=UUID.randomUUID().toString().replaceAll("-", ""); File des = new
String uuid=UUID.randomUUID().toString().replaceAll("-", ""); * File(path+"/"+uuid); FileUtil.copyFile(file, des); mo.setFile(dir+"/"+uuid);
File des = new File(path+"/"+uuid); * mo.setFileType(fileType); } }
FileUtil.copyFile(file, des); *
mo.setFile(dir+"/"+uuid); * }
mo.setFileType(fileType); */
}
} private void checkParams() throws ServletRequestBindingException {
}*/ if (StringUtils.isEmpty(message.getReceiver())) {
throw new IllegalArgumentException("receiver 不能为空!");
private void checkParams() throws ServletRequestBindingException }
{ }
if(StringUtils.isEmpty(message.getReceiver()))
{
throw new IllegalArgumentException("receiver 不能为空!");
}
}
@Override @Override
public Message getModel() { public Message getModel() {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return message; return message;
} }
} }

View File

@ -34,29 +34,28 @@ import com.farsunset.cim.sdk.server.session.CIMSession;
import com.farsunset.cim.sdk.server.session.DefaultSessionManager; import com.farsunset.cim.sdk.server.session.DefaultSessionManager;
import com.farsunset.cim.util.ContextHolder; import com.farsunset.cim.util.ContextHolder;
import com.farsunset.cim.util.StringUtil; import com.farsunset.cim.util.StringUtil;
/** /**
* 账号绑定实现 * 账号绑定实现
* *
*/ */
public class BindHandler implements CIMRequestHandler { public class BindHandler implements CIMRequestHandler {
protected final Logger logger = Logger.getLogger(BindHandler.class); protected final Logger logger = Logger.getLogger(BindHandler.class);
public ReplyBody process(CIMSession newSession, SentBody message) { public ReplyBody process(CIMSession newSession, SentBody message) {
DefaultSessionManager sessionManager = ((DefaultSessionManager) ContextHolder.getBean("CIMSessionManager")); DefaultSessionManager sessionManager = ((DefaultSessionManager) ContextHolder.getBean("CIMSessionManager"));
ReplyBody reply = new ReplyBody(); ReplyBody reply = new ReplyBody();
reply.setCode(CIMConstant.ReturnCode.CODE_200); reply.setCode(CIMConstant.ReturnCode.CODE_200);
try { try {
String account = message.get("account"); String account = message.get("account");
newSession.setGid(StringUtil.getUUID()); newSession.setGid(StringUtil.getUUID());
newSession.setAccount(account); newSession.setAccount(account);
newSession.setDeviceId(message.get("deviceId")); newSession.setDeviceId(message.get("deviceId"));
newSession.setHost(InetAddress.getLocalHost().getHostAddress()); newSession.setHost(InetAddress.getLocalHost().getHostAddress());
newSession.setChannel( message.get("channel")); newSession.setChannel(message.get("channel"));
newSession.setDeviceModel(message.get("device")); newSession.setDeviceModel(message.get("device"));
newSession.setClientVersion(message.get("version")); newSession.setClientVersion(message.get("version"));
newSession.setSystemVersion(message.get("osVersion")); newSession.setSystemVersion(message.get("osVersion"));
@ -65,72 +64,61 @@ public class BindHandler implements CIMRequestHandler {
/** /**
* 由于客户端断线服务端可能会无法获知的情况客户端重连时需要关闭旧的连接 * 由于客户端断线服务端可能会无法获知的情况客户端重连时需要关闭旧的连接
*/ */
CIMSession oldSession = sessionManager.get(account); CIMSession oldSession = sessionManager.get(account);
// 如果是账号已经在另一台终端登录则让另一个终端下线 // 如果是账号已经在另一台终端登录则让另一个终端下线
if (newSession.fromOtherDevice(oldSession)) { if (newSession.fromOtherDevice(oldSession)) {
sendForceOfflineMessage(oldSession, account,newSession.getDeviceModel()); sendForceOfflineMessage(oldSession, account, newSession.getDeviceModel());
} }
//如果是重复连接则直接返回 // 如果是重复连接则直接返回
if (newSession.equals(oldSession)) { if (newSession.equals(oldSession)) {
oldSession.setStatus(CIMSession.STATUS_ENABLED); oldSession.setStatus(CIMSession.STATUS_ENABLED);
sessionManager.update(oldSession); sessionManager.update(oldSession);
reply.put("sid", oldSession.getGid());
return reply; return reply;
} }
closeQuietly(oldSession); closeQuietly(oldSession);
// 第一次设置心跳时间为登录时间
//第一次设置心跳时间为登录时间
newSession.setBindTime(System.currentTimeMillis()); newSession.setBindTime(System.currentTimeMillis());
newSession.setHeartbeat(System.currentTimeMillis()); newSession.setHeartbeat(System.currentTimeMillis());
sessionManager.add(newSession); sessionManager.add(newSession);
} catch (Exception e) { } catch (Exception e) {
reply.setCode(CIMConstant.ReturnCode.CODE_500); reply.setCode(CIMConstant.ReturnCode.CODE_500);
e.printStackTrace(); e.printStackTrace();
} }
logger.debug("bind :account:" +message.get("account")+"-----------------------------" +reply.getCode()); logger.debug("bind :account:" + message.get("account") + "-----------------------------" + reply.getCode());
reply.put("sid", newSession.getGid());
return reply; return reply;
} }
private void sendForceOfflineMessage(CIMSession oldSession, String account, String deviceModel) {
private void sendForceOfflineMessage(CIMSession oldSession, String account,String deviceModel) {
Message msg = new Message(); Message msg = new Message();
msg.setMid(String.valueOf(System.currentTimeMillis())); msg.setMid(String.valueOf(System.currentTimeMillis()));
msg.setAction(CIMConstant.MessageAction.ACTION_999);// 强行下线消息类型 msg.setAction(CIMConstant.MessageAction.ACTION_999);// 强行下线消息类型
msg.setReceiver(account); msg.setReceiver(account);
msg.setContent(deviceModel); msg.setContent(deviceModel);
closeQuietly(oldSession, msg);
closeQuietly(oldSession,msg);
ContextHolder.getBean(SystemMessagePusher.class).push(msg);
if (!oldSession.isLocalhost()) {
ContextHolder.getBean(SystemMessagePusher.class).push(msg);
}
} }
// 同一设备切换网络时关闭旧的连接
//同一设备切换网络时关闭旧的连接 private void closeQuietly(CIMSession oldSession) {
private void closeQuietly(CIMSession oldSession){ if (oldSession != null && oldSession.isConnected()) {
if(oldSession!=null && oldSession.isConnected()){
oldSession.removeAttribute(CIMConstant.SESSION_KEY); oldSession.removeAttribute(CIMConstant.SESSION_KEY);
oldSession.closeNow(); oldSession.closeNow();
} }
} }
//不同设备同一账号登录时关闭旧的连接 // 不同设备同一账号登录时关闭旧的连接
private void closeQuietly(CIMSession oldSession,Message msg){ private void closeQuietly(CIMSession oldSession, Message msg) {
if (oldSession.isConnected()) { if (oldSession.isConnected()) {
oldSession.write(msg); oldSession.write(msg);
oldSession.removeAttribute(CIMConstant.SESSION_KEY); oldSession.removeAttribute(CIMConstant.SESSION_KEY);

View File

@ -41,18 +41,16 @@ public class SessionClosedHandler implements CIMRequestHandler {
public ReplyBody process(CIMSession ios, SentBody message) { public ReplyBody process(CIMSession ios, SentBody message) {
Object account =ios.getAttribute(CIMConstant.SESSION_KEY); Object account = ios.getAttribute(CIMConstant.SESSION_KEY);
if(account == null){ if (account == null) {
return null; return null;
} }
DefaultSessionManager sessionManager = ((DefaultSessionManager) ContextHolder.getBean("CIMSessionManager")); DefaultSessionManager sessionManager = ((DefaultSessionManager) ContextHolder.getBean("CIMSessionManager"));
ios.removeAttribute(CIMConstant.SESSION_KEY); ios.removeAttribute(CIMConstant.SESSION_KEY);
sessionManager.remove(account.toString()); sessionManager.remove(account.toString());
return null; return null;
} }
} }

View File

@ -23,20 +23,17 @@ package com.farsunset.cim.push;
import com.farsunset.cim.sdk.server.model.Message; import com.farsunset.cim.sdk.server.model.Message;
/** /**
* 消息发送实接口 * 消息发送实接口
* *
*/ */
public interface CIMMessagePusher { public interface CIMMessagePusher {
/**
* 向用户发送消息
/** *
* 向用户发送消息 * @param msg
* @param msg */
*/
public void push(Message msg); public void push(Message msg);
} }

View File

@ -29,68 +29,62 @@ import com.farsunset.cim.sdk.server.session.DefaultSessionManager;
* 消息发送实现类 * 消息发送实现类
* *
*/ */
public class DefaultMessagePusher implements CIMMessagePusher { public class DefaultMessagePusher implements CIMMessagePusher {
private DefaultSessionManager sessionManager; private DefaultSessionManager sessionManager;
public void setSessionManager(DefaultSessionManager sessionManager) {
public void setSessionManager(DefaultSessionManager sessionManager) {
this.sessionManager = sessionManager; this.sessionManager = sessionManager;
} }
/** /**
* 向用户发送消息 * 向用户发送消息
* @param msg *
*/ * @param msg
*/
public void push(Message msg) { public void push(Message msg) {
CIMSession session = sessionManager.get(msg.getReceiver()); CIMSession session = sessionManager.get(msg.getReceiver());
/* /*
* 服务器集群时可以在此 * 服务器集群时可以在此 判断当前session是否连接于本台服务器如果是继续往下走如果不是将此消息发往当前session连接的服务器并
* 判断当前session是否连接于本台服务器如果是继续往下走如果不是将此消息发往当前session连接的服务器并 return * return if(session!=null&&!session.isLocalhost()){//判断当前session是否连接于本台服务器如不是
* if(session!=null&&!session.isLocalhost()){//判断当前session是否连接于本台服务器如不是
* //发往目标服务器处理 * //发往目标服务器处理
* MessageDispatcher.execute(MessageUtil.transform(msg),session.getHost()); * MessageDispatcher.execute(MessageUtil.transform(msg),session.getHost());
* return; * return; }
* }
*/ */
if (session != null && session.isConnected()) { if (session != null && session.isConnected()) {
session.write(msg); session.write(msg);
return; return;
} }
// 如果用户标示了APNS ON 说明这是ios设备需要使用apns发送 // 如果用户标示了APNS ON 说明这是ios设备需要使用apns发送
if (session != null && session.getApnsAble() == CIMSession.APNS_ON) { if (session != null && session.getApnsAble() == CIMSession.APNS_ON) {
apnsPush(1,msg.getContent(),session.getDeviceId()); apnsPush(1, msg.getContent(), session.getDeviceId());
} }
} }
/** /**
* 引入javaapns相关jar * 引入javaapns相关jar
*
* @param badge * @param badge
* @param content * @param content
* @param token * @param token
*/ */
private void apnsPush(int badge,String content,String token){ private void apnsPush(int badge, String content, String token) {
/*String password = "password"; /*
String keystore = "p12 文件 绝对路径"; * String password = "password"; String keystore = "p12 文件 绝对路径"; boolean
boolean isDebug = true; * isDebug = true;
*
PushNotificationPayload payload = PushNotificationPayload.complex(); * PushNotificationPayload payload = PushNotificationPayload.complex(); try {
try { * payload.addAlert(content); payload.addBadge(1); payload.addSound("default");
payload.addAlert(content); * Push.payload(payload, keystore, password, isDebug, token);
payload.addBadge(1); *
payload.addSound("default"); * } catch (Exception e) { e.printStackTrace(); }
Push.payload(payload, keystore, password, isDebug, token); */
} catch (Exception e) {
e.printStackTrace();
}*/
} }
} }

View File

@ -22,15 +22,14 @@
package com.farsunset.cim.push; package com.farsunset.cim.push;
import com.farsunset.cim.sdk.server.model.Message; import com.farsunset.cim.sdk.server.model.Message;
public class SystemMessagePusher extends DefaultMessagePusher{
public class SystemMessagePusher extends DefaultMessagePusher {
@Override @Override
public void push(Message message){ public void push(Message message) {
message.setSender("system"); message.setSender("system");
super.push(message); super.push(message);
} }
} }

View File

@ -25,47 +25,41 @@ import java.util.List;
import com.farsunset.cim.sdk.server.session.CIMSession; import com.farsunset.cim.sdk.server.session.CIMSession;
import com.farsunset.cim.sdk.server.session.SessionManager; import com.farsunset.cim.sdk.server.session.SessionManager;
/** /**
* 集群 session管理实现示例 各位可以自行实现 AbstractSessionManager接口来实现自己的 session管理 * 集群 session管理实现示例 各位可以自行实现 AbstractSessionManager接口来实现自己的 session管理 服务器集群时
*服务器集群时 须要将CIMSession 信息存入数据库或者nosql 第三方存储空间中便于所有服务器都可以访问 * 须要将CIMSession 信息存入数据库或者nosql 第三方存储空间中便于所有服务器都可以访问
*/ */
public class ClusterSessionManager implements SessionManager{ public class ClusterSessionManager implements SessionManager {
public CIMSession get(String account) {
// 这里查询数据库
public CIMSession get(String account) { /*
* CIMSession session = database.getSession(account);
//这里查询数据库 * session.setIoSession(ContextHolder.getBean(CIMNioSocketAcceptor.class).
/*CIMSession session = database.getSession(account); * getManagedSessions().get(session.getNid())); return session;
session.setIoSession(ContextHolder.getBean(CIMNioSocketAcceptor.class).getManagedSessions().get(session.getNid())); */
return session;*/ return null;
return null; }
}
@Override @Override
public List<CIMSession> queryAll() { public List<CIMSession> queryAll() {
return null; return null;
} }
@Override @Override
public void remove(String account) { public void remove(String account) {
}
}
@Override @Override
public void update(CIMSession session) { public void update(CIMSession session) {
} }
@Override @Override
public void add(CIMSession arg0) { public void add(CIMSession arg0) {
} }
} }

View File

@ -23,49 +23,47 @@ package com.farsunset.cim.util;
public interface Constants { public interface Constants {
public class Common {
public class Common{ public final static String STATUS_1 = "1";
public final static String STATUS_1="1"; public final static String STATUS_0 = "0";
public final static String STATUS_0="0"; public final static String STATUS_2 = "2";
public final static String STATUS_2="2"; public final static String STATUS_3 = "3";
public final static String STATUS_3="3"; public final static String TYPR_1 = "1";
public final static String TYPR_1="1"; public final static String TYPR_2 = "2";
public final static String TYPR_2="2";
public final static String TYPR_9 = "9"; public final static String TYPR_9 = "9";
}
public class User{
public final static Integer SUCCESS_CODE=1;
public final static Integer ERROR_CODE=0;
public final static String User="User";
} }
public class RequestParam public class User {
{ public final static Integer SUCCESS_CODE = 1;
public final static String CURRENTPAGE="currentPage"; public final static Integer ERROR_CODE = 0;
public final static String TYPE="type"; public final static String User = "User";
}
public class RequestParam {
public final static String CURRENTPAGE = "currentPage";
public final static String TYPE = "type";
public static final String SIZE = "size"; public static final String SIZE = "size";
}
public class Number{
public final static Integer INT_0=0;
public final static Integer INT_10=10;
public final static Integer INT_403=403;
} }
public static interface MessageType{ public class Number {
public final static Integer INT_0 = 0;
//用户之间的普通消息 public final static Integer INT_10 = 10;
public static final String TYPE_0 = "0"; public final static Integer INT_403 = 403;
//系统向用户发送的普通消息
public static final String TYPE_2 = "2";
} }
public static interface MessageType {
// 用户之间的普通消息
public static final String TYPE_0 = "0";
// 系统向用户发送的普通消息
public static final String TYPE_2 = "2";
}
} }

View File

@ -24,25 +24,22 @@ package com.farsunset.cim.util;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
public class ContextHolder implements ApplicationContextAware{
private static ApplicationContext context; public class ContextHolder implements ApplicationContextAware {
public static Object getBean(String name)
{
return context.getBean(name);
}
public static <T> T getBean(Class<T> c)
{
return context.getBean(c);
}
private static ApplicationContext context;
public static Object getBean(String name) {
return context.getBean(name);
}
public static <T> T getBean(Class<T> c) {
return context.getBean(c);
}
@Override @Override
public void setApplicationContext(ApplicationContext applicationContext) public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
throws BeansException {
context = applicationContext; context = applicationContext;
} }
} }

View File

@ -20,6 +20,7 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.util; package com.farsunset.cim.util;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
@ -39,56 +40,48 @@ import org.apache.http.util.EntityUtils;
import com.farsunset.cim.sdk.server.model.Message; import com.farsunset.cim.sdk.server.model.Message;
public class MessageDispatcher {
private static BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
public class MessageDispatcher { private static ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 5, 20, TimeUnit.SECONDS, queue);;
private static BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
private static ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 5, 20, TimeUnit.SECONDS,queue);;
final static String sendUrl = "http://%1$s:8080/cim-servier/cgi/message_send.api"; final static String sendUrl = "http://%1$s:8080/cim-servier/cgi/message_send.api";
public static void execute(final Message msg,final String ip) public static void execute(final Message msg, final String ip) {
{ executor.execute(new Runnable() {
executor.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {
httpPost(String.format(sendUrl,ip),msg); httpPost(String.format(sendUrl, ip), msg);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
}); });
} }
private static String httpPost(String url, Message msg) throws Exception {
private static String httpPost(String url,Message msg) throws Exception
{
CloseableHttpClient httpclient = HttpClients.createDefault(); CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url); HttpPost httpPost = new HttpPost(url);
List <NameValuePair> nvps = new ArrayList <NameValuePair>(); List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("mid", msg.getMid())); nvps.add(new BasicNameValuePair("mid", msg.getMid()));
nvps.add(new BasicNameValuePair("extra", msg.getExtra())); nvps.add(new BasicNameValuePair("extra", msg.getExtra()));
nvps.add(new BasicNameValuePair("action", msg.getAction())); nvps.add(new BasicNameValuePair("action", msg.getAction()));
nvps.add(new BasicNameValuePair("title", msg.getTitle())); nvps.add(new BasicNameValuePair("title", msg.getTitle()));
nvps.add(new BasicNameValuePair("content",msg.getContent())); nvps.add(new BasicNameValuePair("content", msg.getContent()));
nvps.add(new BasicNameValuePair("sender", msg.getSender())); nvps.add(new BasicNameValuePair("sender", msg.getSender()));
nvps.add(new BasicNameValuePair("receiver",msg.getReceiver())); nvps.add(new BasicNameValuePair("receiver", msg.getReceiver()));
nvps.add(new BasicNameValuePair("timestamp",String.valueOf(msg.getTimestamp()))); nvps.add(new BasicNameValuePair("timestamp", String.valueOf(msg.getTimestamp())));
httpPost.setEntity(new UrlEncodedFormEntity(nvps)); httpPost.setEntity(new UrlEncodedFormEntity(nvps));
CloseableHttpResponse response2 = httpclient.execute(httpPost); CloseableHttpResponse response2 = httpclient.execute(httpPost);
String data = null; String data = null;
try { try {
System.out.println(response2.getStatusLine()); System.out.println(response2.getStatusLine());
HttpEntity entity2 = response2.getEntity(); HttpEntity entity2 = response2.getEntity();
data = EntityUtils.toString(entity2); data = EntityUtils.toString(entity2);
} finally { } finally {
response2.close(); response2.close();
} }
return data;
return data;
} }
} }

View File

@ -25,44 +25,38 @@ import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.UUID; import java.util.UUID;
public class StringUtil { public class StringUtil {
public static boolean isEmpty(Object obj) {
public static boolean isEmpty(Object obj) if (null == obj)
{
if(null == obj)
return true; return true;
if("".equals(obj.toString().trim())) if ("".equals(obj.toString().trim())) {
{
return true; return true;
} }
return false; return false;
} }
public static boolean isNotEmpty(Object obj) public static boolean isNotEmpty(Object obj) {
{
return !isEmpty(obj); return !isEmpty(obj);
} }
public static String getSequenceId()
{ public static String getSequenceId() {
String mark = String.valueOf(System.currentTimeMillis()); String mark = String.valueOf(System.currentTimeMillis());
return mark; return mark;
} }
public static String getCurrentlyDateTime() { public static String getCurrentlyDateTime() {
SimpleDateFormat dateFormat = new SimpleDateFormat( SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
"yyyyMMddHHmmss");
return dateFormat.format(new Date()); return dateFormat.format(new Date());
} }
public static String transformDateTime(long t) { public static String transformDateTime(long t) {
Date date = new Date(t); Date date = new Date(t);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return dateFormat.format(date); return dateFormat.format(date);
} }
public static String getCurrentlyDate() { public static String getCurrentlyDate() {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
return dateFormat.format(new Date()); return dateFormat.format(new Date());
@ -72,6 +66,5 @@ public class StringUtil {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return UUID.randomUUID().toString().replaceAll("-", ""); return UUID.randomUUID().toString().replaceAll("-", "");
} }
} }

View File

@ -26,86 +26,76 @@ import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
class CIMCacheManager {
class CIMCacheManager {
public static final String CIM_CONFIG_INFO = "CIM_CONFIG_INFO";
public static final String CIM_CONFIG_INFO = "CIM_CONFIG_INFO";
public static final String KEY_ACCOUNT = "KEY_ACCOUNT"; public static final String KEY_ACCOUNT = "KEY_ACCOUNT";
public static final String KEY_DEVICE_ID = "KEY_DEVICE_ID"; public static final String KEY_DEVICE_ID = "KEY_DEVICE_ID";
public static final String KEY_MANUAL_STOP = "KEY_MANUAL_STOP"; public static final String KEY_MANUAL_STOP = "KEY_MANUAL_STOP";
public static final String KEY_CIM_DESTROYED = "KEY_CIM_DESTROYED"; public static final String KEY_CIM_DESTROYED = "KEY_CIM_DESTROYED";
public static final String KEY_CIM_SERVIER_HOST = "KEY_CIM_SERVIER_HOST"; public static final String KEY_CIM_SERVIER_HOST = "KEY_CIM_SERVIER_HOST";
public static final String KEY_CIM_SERVIER_PORT = "KEY_CIM_SERVIER_PORT"; public static final String KEY_CIM_SERVIER_PORT = "KEY_CIM_SERVIER_PORT";
public static final String KEY_CIM_CONNECTION_STATE = "KEY_CIM_CONNECTION_STATE"; public static final String KEY_CIM_CONNECTION_STATE = "KEY_CIM_CONNECTION_STATE";
public static void remove(Context context, String key) {
public static void remove(Context context ,String key) ContentResolver resolver = context.getContentResolver();
{
ContentResolver resolver = context.getContentResolver();
resolver.delete(Uri.parse(CIMCacheProvider.CONTENT_URI), key, null); resolver.delete(Uri.parse(CIMCacheProvider.CONTENT_URI), key, null);
} }
public static void putString(Context context, String key, String value) {
public static void putString(Context context ,String key,String value) ContentResolver resolver = context.getContentResolver();
{ ContentValues values = new ContentValues();
values.put("value", value);
ContentResolver resolver = context.getContentResolver(); values.put("key", key);
ContentValues values = new ContentValues(); resolver.insert(Uri.parse(CIMCacheProvider.CONTENT_URI), values);
values.put("value", value);
values.put("key", key);
resolver.insert(Uri.parse(CIMCacheProvider.CONTENT_URI), values);
} }
public static String getString(Context context ,String key) public static String getString(Context context, String key) {
{
String value = null; String value = null;
ContentResolver resolver = context.getContentResolver(); ContentResolver resolver = context.getContentResolver();
Cursor cursor = resolver.query(Uri.parse(CIMCacheProvider.CONTENT_URI), new String[]{key}, null,null,null); Cursor cursor = resolver.query(Uri.parse(CIMCacheProvider.CONTENT_URI), new String[] { key }, null, null, null);
if (cursor!=null && cursor.moveToFirst()) if (cursor != null && cursor.moveToFirst()) {
{
value = cursor.getString(0); value = cursor.getString(0);
cursor.close(); cursor.close();
} }
closeQuietly(cursor); closeQuietly(cursor);
return value; return value;
} }
private static void closeQuietly(Cursor cursor){ private static void closeQuietly(Cursor cursor) {
try{ try {
if(cursor!=null) if (cursor != null)
cursor.close(); cursor.close();
}catch(Exception e){} } catch (Exception e) {
}
} }
public static void putBoolean(Context context,String key,boolean value) public static void putBoolean(Context context, String key, boolean value) {
{ putString(context, key, Boolean.toString(value));
putString(context,key,Boolean.toString(value));
} }
public static boolean getBoolean(Context context,String key) public static boolean getBoolean(Context context, String key) {
{ String value = getString(context, key);
String value = getString(context,key); return value == null ? false : Boolean.parseBoolean(value);
return value == null?false:Boolean.parseBoolean(value);
} }
public static void putInt(Context context, String key, int value) {
public static void putInt(Context context,String key,int value) putString(context, key, String.valueOf(value));
{
putString(context,key, String.valueOf(value));
} }
public static int getInt(Context context,String key) public static int getInt(Context context, String key) {
{ String value = getString(context, key);
String value = getString(context,key); return value == null ? 0 : Integer.parseInt(value);
return value == null?0:Integer.parseInt(value);
} }
} }

View File

@ -29,13 +29,12 @@ import android.database.MatrixCursor;
import android.net.Uri; import android.net.Uri;
public class CIMCacheProvider extends ContentProvider { public class CIMCacheProvider extends ContentProvider {
public static final String CONTENT_URI="content://com.farsunset.cim.provider"; public static final String CONTENT_URI = "content://com.farsunset.cim.provider";
static final String MODEL_KEY = "PRIVATE_CIM_CONFIG"; static final String MODEL_KEY = "PRIVATE_CIM_CONFIG";
@Override @Override
public int delete(Uri arg0, String key, String[] arg2) { public int delete(Uri arg0, String key, String[] arg2) {
getContext().getSharedPreferences(MODEL_KEY, Context.MODE_PRIVATE).edit().remove(key).apply(); getContext().getSharedPreferences(MODEL_KEY, Context.MODE_PRIVATE).edit().remove(key).apply();
return 0; return 0;
} }
@ -48,7 +47,7 @@ public class CIMCacheProvider extends ContentProvider {
public Uri insert(Uri arg0, ContentValues values) { public Uri insert(Uri arg0, ContentValues values) {
String key = values.getAsString("key"); String key = values.getAsString("key");
String value = values.getAsString("value"); String value = values.getAsString("value");
getContext().getSharedPreferences(MODEL_KEY, Context.MODE_PRIVATE).edit().putString(key, value).apply(); getContext().getSharedPreferences(MODEL_KEY, Context.MODE_PRIVATE).edit().putString(key, value).apply();
return null; return null;
} }
@ -59,9 +58,9 @@ public class CIMCacheProvider extends ContentProvider {
@Override @Override
public Cursor query(Uri arg0, String[] arg1, String key, String[] arg3, String arg4) { public Cursor query(Uri arg0, String[] arg1, String key, String[] arg3, String arg4) {
MatrixCursor cursor = new MatrixCursor(new String[]{"value"}); MatrixCursor cursor = new MatrixCursor(new String[] { "value" });
String value = getContext().getSharedPreferences(MODEL_KEY, Context.MODE_PRIVATE).getString(arg1[0], null); String value = getContext().getSharedPreferences(MODEL_KEY, Context.MODE_PRIVATE).getString(arg1[0], null);
cursor.addRow(new Object[]{value}); cursor.addRow(new Object[] { value });
return cursor; return cursor;
} }
@ -70,5 +69,4 @@ public class CIMCacheProvider extends ContentProvider {
return 0; return 0;
} }
} }

View File

@ -1,170 +0,0 @@
/**
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
class CIMCacheToolkit extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "CIM_CONFIG_INFO.db";
private static final int DATABASE_VERSION = 20160406;
private static final String TABLE_NAME = "T_CIM_CONFIG";
private static CIMCacheToolkit toolkit;
private static final String TABLE_SQL = "CREATE TABLE IF NOT EXISTS "+TABLE_NAME+" (KEY VARCHAR(64) PRIMARY KEY,VALUE TEXT)";
private static final String DELETE_SQL = "DELETE FROM "+TABLE_NAME+" WHERE KEY = ?";
private static final String QUERY_SQL = "SELECT VALUE FROM "+TABLE_NAME+" WHERE KEY = ?";
private SQLiteDatabase mSQLiteDatabase;
public static final String CIM_CONFIG_INFO = "CIM_CONFIG_INFO";
public static final String KEY_ACCOUNT = "KEY_ACCOUNT";
public static final String KEY_MANUAL_STOP = "KEY_MANUAL_STOP";
public static final String KEY_CIM_DESTROYED = "KEY_CIM_DESTROYED";
public static final String KEY_CIM_SERVIER_HOST = "KEY_CIM_SERVIER_HOST";
public static final String KEY_CIM_SERVIER_PORT = "KEY_CIM_SERVIER_PORT";
public static final String KEY_CIM_CONNECTION_STATE = "KEY_CIM_CONNECTION_STATE";
public synchronized static CIMCacheToolkit getInstance(Context context){
if(toolkit==null){
toolkit = new CIMCacheToolkit(context);
}
return toolkit;
}
public CIMCacheToolkit(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
public CIMCacheToolkit(Context context){
this(context, DATABASE_NAME,null, DATABASE_VERSION);
}
public synchronized void remove(String key)
{
getSQLiteDatabase().execSQL(DELETE_SQL,new String[]{key});
}
public synchronized void putString(String key,String value)
{
ContentValues values = new ContentValues();
values.put("VALUE", value);
int result = getSQLiteDatabase().updateWithOnConflict(TABLE_NAME, values, "KEY=?",new String[]{key},SQLiteDatabase.CONFLICT_FAIL);
if(result<=0){
values.put("KEY", key);
getSQLiteDatabase().insert(TABLE_NAME, null, values);
}
}
public synchronized String getString(String key)
{
String value = null;
Cursor cursor = getSQLiteDatabase().rawQuery(QUERY_SQL, new String[]{key});
if (cursor!=null)
{
if(cursor.moveToFirst()){
value = cursor.getString(0);
}
cursor.close();
}
return value;
}
public void putBoolean(String key,boolean value)
{
putString(key,Boolean.toString(value));
}
public boolean getBoolean(String key)
{
String value = getString(key);
return value == null?false:Boolean.parseBoolean(value);
}
public void putInt(String key,int value)
{
putString(key, String.valueOf(value));
}
public int getInt(String key)
{
String value = getString(key);
return value == null?0:Integer.parseInt(value);
}
@Override
public void onCreate(SQLiteDatabase database) {
database.execSQL(TABLE_SQL);
}
public static synchronized void destroy(){
if (toolkit!=null){
try{toolkit.mSQLiteDatabase.close();}catch(Exception e){}
try{toolkit.close();}catch(Exception e){}
}
toolkit = null;
}
private SQLiteDatabase getSQLiteDatabase(){
if(mSQLiteDatabase!=null){
return mSQLiteDatabase;
}else
{
mSQLiteDatabase = getWritableDatabase();
}
return mSQLiteDatabase;
}
@Override
public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
}
}

View File

@ -20,6 +20,7 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.android; package com.farsunset.cim.sdk.android;
import java.util.Random; import java.util.Random;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@ -64,22 +65,20 @@ import com.farsunset.cim.sdk.android.model.SentBody;
class CIMConnectorManager extends SimpleChannelInboundHandler<Object> { class CIMConnectorManager extends SimpleChannelInboundHandler<Object> {
private final String TAG = CIMConnectorManager.class.getSimpleName(); private final String TAG = CIMConnectorManager.class.getSimpleName();
private final int CONNECT_TIMEOUT = 10 * 1000;// private final int CONNECT_TIMEOUT = 10 * 1000;//
private final int WRITE_TIMEOUT = 10 * 1000;// private final int WRITE_TIMEOUT = 10 * 1000;//
private final int READ_IDLE_TIME = 120;// private final int READ_IDLE_TIME = 120;//
private final int HEARBEAT_TIME_OUT = (READ_IDLE_TIME + 20) * 1000;// 收到服务端心跳请求超时时间 毫秒 private final int HEARBEAT_TIME_OUT = (READ_IDLE_TIME + 20) * 1000;// 收到服务端心跳请求超时时间 毫秒
private final String KEY_LAST_HEART_TIME = "KEY_LAST_HEART_TIME" ; private final String KEY_LAST_HEART_TIME = "KEY_LAST_HEART_TIME";
private Bootstrap bootstrap; private Bootstrap bootstrap;
private EventLoopGroup loopGroup ; private EventLoopGroup loopGroup;
private Channel channel;; private Channel channel;;
private ExecutorService executor = Executors.newFixedThreadPool(1); private ExecutorService executor = Executors.newFixedThreadPool(1);
private Context context; private Context context;
private static CIMConnectorManager manager;
private static CIMConnectorManager manager;
private CIMConnectorManager(Context ctx) { private CIMConnectorManager(Context ctx) {
context = ctx; context = ctx;
@ -88,19 +87,19 @@ class CIMConnectorManager extends SimpleChannelInboundHandler<Object> {
loopGroup = new NioEventLoopGroup(); loopGroup = new NioEventLoopGroup();
bootstrap.group(loopGroup); bootstrap.group(loopGroup);
bootstrap.channel(NioSocketChannel.class); bootstrap.channel(NioSocketChannel.class);
bootstrap.option(ChannelOption.TCP_NODELAY, true); bootstrap.option(ChannelOption.TCP_NODELAY, true);
bootstrap.option(ChannelOption.SO_KEEPALIVE, true); bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, CONNECT_TIMEOUT); bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, CONNECT_TIMEOUT);
bootstrap.handler(new ChannelInitializer<SocketChannel>() { bootstrap.handler(new ChannelInitializer<SocketChannel>() {
@Override @Override
public void initChannel(SocketChannel ch) throws Exception { public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ClientMessageDecoder()); ch.pipeline().addLast(new ClientMessageDecoder());
ch.pipeline().addLast(new ClientMessageEncoder()); ch.pipeline().addLast(new ClientMessageEncoder());
ch.pipeline().addLast(new IdleStateHandler(READ_IDLE_TIME,0,0)); ch.pipeline().addLast(new IdleStateHandler(READ_IDLE_TIME, 0, 0));
ch.pipeline().addLast(CIMConnectorManager.this); ch.pipeline().addLast(CIMConnectorManager.this);
} }
}); });
} }
@ -112,87 +111,84 @@ class CIMConnectorManager extends SimpleChannelInboundHandler<Object> {
} }
private synchronized void syncConnection( String host, int port) { private synchronized void syncConnection(String host, int port) {
if(isConnected()){ if (isConnected()) {
return ; return;
} }
try { try {
Log.i(TAG, "****************CIM正在连接服务器 "+host+":"+port+"......"); Log.i(TAG, "****************CIM正在连接服务器 " + host + ":" + port + "......");
ChannelFuture channelFuture = bootstrap.connect(host, port).syncUninterruptibly(); ChannelFuture channelFuture = bootstrap.connect(host, port).syncUninterruptibly();
channel = channelFuture.channel(); channel = channelFuture.channel();
} catch (Exception e) { } catch (Exception e) {
long interval = CIMConstant.RECONN_INTERVAL_TIME - (5*1000 - new Random().nextInt(15*1000)); long interval = CIMConstant.RECONN_INTERVAL_TIME - (5 * 1000 - new Random().nextInt(15 * 1000));
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED); intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED);
intent.putExtra(Exception.class.getName(), e.getClass().getSimpleName()); intent.putExtra(Exception.class.getName(), e.getClass().getSimpleName());
intent.putExtra("interval", interval); intent.putExtra("interval", interval);
context.sendBroadcast(intent); context.sendBroadcast(intent);
Log.e(TAG, "****************CIM连接服务器失败 "+host+":"+port+"......将在"+interval/1000+"秒后重新尝试连接"); Log.e(TAG, "****************CIM连接服务器失败 " + host + ":" + port + "......将在" + interval / 1000 + "秒后重新尝试连接");
} }
} }
public void connect(final String host, final int port) { public void connect(final String host, final int port) {
if (!isNetworkConnected(context)) { if (!isNetworkConnected(context)) {
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED); intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED);
intent.putExtra(Exception.class.getName(), NetworkDisabledException.class.getSimpleName()); intent.putExtra(Exception.class.getName(), NetworkDisabledException.class.getSimpleName());
context.sendBroadcast(intent); context.sendBroadcast(intent);
return; return;
} }
executor.execute(new Runnable() { executor.execute(new Runnable() {
public void run() public void run() {
{
syncConnection(host, port); syncConnection(host, port);
} }
}); });
} }
public synchronized void send(SentBody body) { public synchronized void send(SentBody body) {
boolean isSuccessed = false; boolean isSuccessed = false;
String exceptionName = SessionClosedException.class.getSimpleName(); String exceptionName = SessionClosedException.class.getSimpleName();
if(channel!=null && channel.isActive()) if (channel != null && channel.isActive()) {
{
ChannelFuture future = channel.writeAndFlush(body); ChannelFuture future = channel.writeAndFlush(body);
isSuccessed = future.awaitUninterruptibly(WRITE_TIMEOUT); isSuccessed = future.awaitUninterruptibly(WRITE_TIMEOUT);
if(!isSuccessed && future.cause()!=null){ if (!isSuccessed && future.cause() != null) {
exceptionName = future.cause().getClass().getSimpleName(); exceptionName = future.cause().getClass().getSimpleName();
} }
} }
if(!isSuccessed){ if (!isSuccessed) {
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_SENT_FAILED); intent.setAction(CIMConstant.IntentAction.ACTION_SENT_FAILED);
intent.putExtra(Exception.class.getName(),exceptionName); intent.putExtra(Exception.class.getName(), exceptionName);
intent.putExtra(SentBody.class.getName(), body); intent.putExtra(SentBody.class.getName(), body);
context.sendBroadcast(intent); context.sendBroadcast(intent);
}else } else {
{
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_SENT_SUCCESSED); intent.setAction(CIMConstant.IntentAction.ACTION_SENT_SUCCESSED);
intent.putExtra(SentBody.class.getName(), (SentBody) body); intent.putExtra(SentBody.class.getName(), (SentBody) body);
context.sendBroadcast(intent); context.sendBroadcast(intent);
} }
} }
public void destroy() { public void destroy() {
if (channel != null) { if (channel != null) {
channel.close(); channel.close();
} }
@ -200,7 +196,7 @@ class CIMConnectorManager extends SimpleChannelInboundHandler<Object> {
if (loopGroup != null) { if (loopGroup != null) {
loopGroup.shutdownGracefully(); loopGroup.shutdownGracefully();
} }
manager = null; manager = null;
} }
@ -208,40 +204,35 @@ class CIMConnectorManager extends SimpleChannelInboundHandler<Object> {
if (channel == null) { if (channel == null) {
return false; return false;
} }
return channel.isActive() ; return channel.isActive();
} }
public void closeSession() {
if (channel != null) {
public void closeSession()
{
if(channel!=null)
{
channel.close(); channel.close();
} }
} }
@Override @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception { public void channelActive(ChannelHandlerContext ctx) throws Exception {
Log.i(TAG, "****************CIM连接服务器成功:" + ctx.channel().localAddress() + " NID:"
Log.i(TAG, "****************CIM连接服务器成功:"+ctx.channel().localAddress()+" NID:"+ctx.channel().id().asShortText()); + ctx.channel().id().asShortText());
setLastHeartbeatTime(ctx.channel()); setLastHeartbeatTime(ctx.channel());
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_SUCCESSED); intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_SUCCESSED);
context.sendBroadcast(intent); context.sendBroadcast(intent);
} }
@Override
public void channelInactive(ChannelHandlerContext ctx) {
Log.e(TAG, "****************CIM与服务器断开连接:"+ctx.channel().localAddress()+" NID:"+ctx.channel().id().asShortText()); @Override
public void channelInactive(ChannelHandlerContext ctx) {
Log.e(TAG, "****************CIM与服务器断开连接:" + ctx.channel().localAddress() + " NID:"
+ ctx.channel().id().asShortText());
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED); intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED);
context.sendBroadcast(intent); context.sendBroadcast(intent);
@ -249,36 +240,35 @@ class CIMConnectorManager extends SimpleChannelInboundHandler<Object> {
} }
@Override @Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) { public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
/** /**
* 用于解决wifi情况下偶而路由器与服务器断开连接时客户端并没及时收到关闭事件 * 用于解决wifi情况下偶而路由器与服务器断开连接时客户端并没及时收到关闭事件 导致这样的情况下当前连接无效也不会重连的问题
* 导致这样的情况下当前连接无效也不会重连的问题
* *
*/ */
if (evt instanceof IdleStateEvent && ((IdleStateEvent) evt).state().equals(IdleState.READER_IDLE)) if (evt instanceof IdleStateEvent && ((IdleStateEvent) evt).state().equals(IdleState.READER_IDLE)) {
{ Log.d(TAG, "****************CIM " + IdleState.READER_IDLE + ":" + ctx.channel().localAddress() + " NID:"
Log.d(TAG, "****************CIM "+IdleState.READER_IDLE+":"+ctx.channel().localAddress()+" NID:"+ctx.channel().id().asShortText()); + ctx.channel().id().asShortText());
Long lastTime = getLastHeartbeatTime(ctx.channel()); Long lastTime = getLastHeartbeatTime(ctx.channel());
if(lastTime != null && System.currentTimeMillis() - lastTime > HEARBEAT_TIME_OUT) if (lastTime != null && System.currentTimeMillis() - lastTime > HEARBEAT_TIME_OUT) {
{ channel.close();
channel.close(); Log.e(TAG, "****************CIM心跳超时 ,即将重新连接......" + " NID:" + ctx.channel().id().asShortText());
Log.e(TAG, "****************CIM心跳超时 ,即将重新连接......"+" NID:"+ctx.channel().id().asShortText()); }
} }
}
} }
@Override @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
Log.e(TAG, "****************CIM连接出现未知异常:"+ctx.channel().localAddress()+" NID:"+ctx.channel().id().asShortText()); Log.e(TAG, "****************CIM连接出现未知异常:" + ctx.channel().localAddress() + " NID:"
+ ctx.channel().id().asShortText());
if(cause!=null && cause.getMessage()!=null){
if (cause != null && cause.getMessage() != null) {
Log.e(TAG, cause.getMessage()); Log.e(TAG, cause.getMessage());
} }
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_UNCAUGHT_EXCEPTION); intent.setAction(CIMConstant.IntentAction.ACTION_UNCAUGHT_EXCEPTION);
intent.putExtra(Exception.class.getName(), cause.getClass().getSimpleName()); intent.putExtra(Exception.class.getName(), cause.getClass().getSimpleName());
@ -286,49 +276,48 @@ class CIMConnectorManager extends SimpleChannelInboundHandler<Object> {
} }
@Override @Override
public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception{ public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof Message) { if (msg instanceof Message) {
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED); intent.setAction(CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED);
intent.putExtra(Message.class.getName(), (Message) msg); intent.putExtra(Message.class.getName(), (Message) msg);
context.sendBroadcast(intent); context.sendBroadcast(intent);
} }
if (msg instanceof ReplyBody) { if (msg instanceof ReplyBody) {
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_REPLY_RECEIVED); intent.setAction(CIMConstant.IntentAction.ACTION_REPLY_RECEIVED);
intent.putExtra(ReplyBody.class.getName(), (ReplyBody) msg); intent.putExtra(ReplyBody.class.getName(), (ReplyBody) msg);
context.sendBroadcast(intent); context.sendBroadcast(intent);
} }
//收到服务端发来的心跳请求命令则马上回应服务器 // 收到服务端发来的心跳请求命令则马上回应服务器
if (msg instanceof HeartbeatRequest) { if (msg instanceof HeartbeatRequest) {
ctx.writeAndFlush(HeartbeatResponse.getInstance()); ctx.writeAndFlush(HeartbeatResponse.getInstance());
setLastHeartbeatTime(ctx.channel()); setLastHeartbeatTime(ctx.channel());
} }
} }
private void setLastHeartbeatTime(Channel channel) private void setLastHeartbeatTime(Channel channel) {
{
channel.attr(AttributeKey.valueOf(KEY_LAST_HEART_TIME)).set(System.currentTimeMillis()); channel.attr(AttributeKey.valueOf(KEY_LAST_HEART_TIME)).set(System.currentTimeMillis());
} }
private Long getLastHeartbeatTime(Channel channel) private Long getLastHeartbeatTime(Channel channel) {
{
return (Long) channel.attr(AttributeKey.valueOf(KEY_LAST_HEART_TIME)).get(); return (Long) channel.attr(AttributeKey.valueOf(KEY_LAST_HEART_TIME)).get();
} }
public static boolean isNetworkConnected(Context context) { public static boolean isNetworkConnected(Context context) {
try { try {
ConnectivityManager nw = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); ConnectivityManager nw = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = nw.getActiveNetworkInfo(); NetworkInfo networkInfo = nw.getActiveNetworkInfo();
return networkInfo != null; return networkInfo != null;
} catch (Exception e) {} } catch (Exception e) {
}
return false; return false;
} }
} }

View File

@ -21,7 +21,6 @@
*/ */
package com.farsunset.cim.sdk.android; package com.farsunset.cim.sdk.android;
import com.farsunset.cim.sdk.android.constant.CIMConstant; import com.farsunset.cim.sdk.android.constant.CIMConstant;
import com.farsunset.cim.sdk.android.exception.SessionClosedException; import com.farsunset.cim.sdk.android.exception.SessionClosedException;
import com.farsunset.cim.sdk.android.model.Message; import com.farsunset.cim.sdk.android.model.Message;
@ -33,207 +32,185 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
/** /**
* 消息入口所有消息都会经过这里 * 消息入口所有消息都会经过这里
*/ */
public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver{ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver {
protected Context context; protected Context context;
@Override @Override
public void onReceive(Context ctx, Intent intent) { public void onReceive(Context ctx, Intent intent) {
context = ctx; context = ctx;
/*
* 操作事件广播用于提高service存活率
*/
if(intent.getAction().equals(Intent.ACTION_USER_PRESENT)
||intent.getAction().equals(Intent.ACTION_POWER_CONNECTED)
||intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED))
{
startPushService();
}
/* /*
* 设备网络状态变化事件 * 操作事件广播用于提高service存活率
*/ */
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_NETWORK_CHANGED)) if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)
{ || intent.getAction().equals(Intent.ACTION_POWER_CONNECTED)
ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); || intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED)) {
onDevicesNetworkChanged(connectivityManager.getActiveNetworkInfo()); startPushService();
} }
/* /*
* cim断开服务器事件 * 设备网络状态变化事件
*/ */
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED)) if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_NETWORK_CHANGED)) {
{ ConnectivityManager connectivityManager = (ConnectivityManager) context
onInnerConnectionClosed(); .getSystemService(Context.CONNECTIVITY_SERVICE);
} onDevicesNetworkChanged(connectivityManager.getActiveNetworkInfo());
}
/*
* cim连接服务器失败事件 /*
*/ * cim断开服务器事件
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED)) */
{ if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED)) {
long interval = intent.getLongExtra("interval", CIMConstant.RECONN_INTERVAL_TIME); onInnerConnectionClosed();
String exceptionName = intent.getStringExtra(Exception.class.getName()); }
onConnectionFailed(exceptionName,interval);
} /*
* cim连接服务器失败事件
/* */
* cim连接服务器成功事件 if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED)) {
*/ long interval = intent.getLongExtra("interval", CIMConstant.RECONN_INTERVAL_TIME);
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_SUCCESSED)) String exceptionName = intent.getStringExtra(Exception.class.getName());
{ onConnectionFailed(exceptionName, interval);
onInnerConnectionSuccessed(); }
}
/*
/* * cim连接服务器成功事件
* 收到推送消息事件 */
*/ if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_SUCCESSED)) {
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED)) onInnerConnectionSuccessed();
{ }
onInnerMessageReceived((Message)intent.getSerializableExtra(Message.class.getName()),intent);
} /*
* 收到推送消息事件
*/
/* if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED)) {
* 获取收到replybody成功事件 onInnerMessageReceived((Message) intent.getSerializableExtra(Message.class.getName()), intent);
*/ }
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_REPLY_RECEIVED))
{ /*
onReplyReceived((ReplyBody)intent.getSerializableExtra(ReplyBody.class.getName())); * 获取收到replybody成功事件
} */
if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_REPLY_RECEIVED)) {
onReplyReceived((ReplyBody) intent.getSerializableExtra(ReplyBody.class.getName()));
/* }
* 获取sendbody发送失败事件
*/ /*
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_SENT_FAILED)) * 获取sendbody发送失败事件
{ */
String exceptionName = intent.getStringExtra(Exception.class.getName()); if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_SENT_FAILED)) {
SentBody sentBody = (SentBody)intent.getSerializableExtra(SentBody.class.getName()); String exceptionName = intent.getStringExtra(Exception.class.getName());
onSentFailed(exceptionName,sentBody); SentBody sentBody = (SentBody) intent.getSerializableExtra(SentBody.class.getName());
} onSentFailed(exceptionName, sentBody);
}
/*
* 获取sendbody发送成功事件 /*
*/ * 获取sendbody发送成功事件
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_SENT_SUCCESSED)) */
{ if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_SENT_SUCCESSED)) {
onSentSucceed((SentBody)intent.getSerializableExtra(SentBody.class.getName())); onSentSucceed((SentBody) intent.getSerializableExtra(SentBody.class.getName()));
} }
/*
* 重新连接如果断开的话
/* */
* 重新连接如果断开的话 if (intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_RECOVERY)) {
*/ CIMPushManager.connect(context, 0);
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_RECOVERY)) }
{
CIMPushManager.connect(context,0);
}
} }
private void startPushService(){ private void startPushService() {
Intent intent = new Intent(context, CIMPushService.class); Intent intent = new Intent(context, CIMPushService.class);
intent.setAction(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE); intent.setAction(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE);
context.startService(intent); context.startService(intent);
} }
private void onInnerConnectionClosed(){ private void onInnerConnectionClosed() {
CIMCacheManager.putBoolean(context,CIMCacheManager.KEY_CIM_CONNECTION_STATE, false); CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_CIM_CONNECTION_STATE, false);
if(CIMConnectorManager.isNetworkConnected(context)) if (CIMConnectorManager.isNetworkConnected(context)) {
{ CIMPushManager.connect(context, 0);
CIMPushManager.connect(context,0);
} }
onConnectionClosed(); onConnectionClosed();
} }
private void onConnectionFailed(String exceptionName,long reinterval){ private void onConnectionFailed(String exceptionName, long reinterval) {
if(CIMConnectorManager.isNetworkConnected(context)) if (CIMConnectorManager.isNetworkConnected(context)) {
{
onConnectionFailed(); onConnectionFailed();
CIMPushManager.connect(context,reinterval); CIMPushManager.connect(context, reinterval);
} }
} }
private void onInnerConnectionSuccessed(){ private void onInnerConnectionSuccessed() {
CIMCacheManager.putBoolean(context,CIMCacheManager.KEY_CIM_CONNECTION_STATE, true); CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_CIM_CONNECTION_STATE, true);
boolean autoBind = CIMPushManager.autoBindAccount(context); boolean autoBind = CIMPushManager.autoBindAccount(context);
onConnectionSuccessed(autoBind); onConnectionSuccessed(autoBind);
} }
private void onDevicesNetworkChanged(NetworkInfo info) { private void onDevicesNetworkChanged(NetworkInfo info) {
if(info !=null) if (info != null) {
{ CIMPushManager.connect(context, 0);
CIMPushManager.connect(context,0); }
}
onNetworkChanged(info); onNetworkChanged(info);
} }
private void onInnerMessageReceived(com.farsunset.cim.sdk.android.model.Message message, Intent intent){ private void onInnerMessageReceived(com.farsunset.cim.sdk.android.model.Message message, Intent intent) {
if(isForceOfflineMessage(message.getAction())) if (isForceOfflineMessage(message.getAction())) {
{
CIMPushManager.stop(context); CIMPushManager.stop(context);
} }
onMessageReceived(message,intent); onMessageReceived(message, intent);
}
private boolean isForceOfflineMessage(String action)
{
return CIMConstant.MessageAction.ACTION_999.equals(action);
}
private void onSentFailed(String exceptionName, SentBody body){
//与服务端端开链接重新连接
if(SessionClosedException.class.getSimpleName().equals(exceptionName))
{
CIMPushManager.connect(context,0);
}else
{
//发送失败 重新发送
CIMPushManager.sendRequest(context, body);
}
} }
private boolean isForceOfflineMessage(String action) {
return CIMConstant.MessageAction.ACTION_999.equals(action);
public abstract void onMessageReceived(com.farsunset.cim.sdk.android.model.Message message,Intent intent); }
public void onNetworkChanged(NetworkInfo info) { private void onSentFailed(String exceptionName, SentBody body) {
// 与服务端端开链接重新连接
if (SessionClosedException.class.getSimpleName().equals(exceptionName)) {
CIMPushManager.connect(context, 0);
} else {
// 发送失败 重新发送
CIMPushManager.sendRequest(context, body);
}
}
public abstract void onMessageReceived(com.farsunset.cim.sdk.android.model.Message message, Intent intent);
public void onNetworkChanged(NetworkInfo info) {
CIMListenerManager.notifyOnNetworkChanged(info); CIMListenerManager.notifyOnNetworkChanged(info);
} }
public void onConnectionSuccessed(boolean hasAutoBind) {
public void onConnectionSuccessed(boolean hasAutoBind) {
CIMListenerManager.notifyOnConnectionSuccessed(hasAutoBind); CIMListenerManager.notifyOnConnectionSuccessed(hasAutoBind);
} }
public void onConnectionClosed() { public void onConnectionClosed() {
CIMListenerManager.notifyOnConnectionClosed(); CIMListenerManager.notifyOnConnectionClosed();
} }
public void onConnectionFailed() { public void onConnectionFailed() {
CIMListenerManager.notifyOnConnectionFailed(); CIMListenerManager.notifyOnConnectionFailed();
} }
public void onReplyReceived(ReplyBody body) { public void onReplyReceived(ReplyBody body) {
CIMListenerManager.notifyOnReplyReceived(body); CIMListenerManager.notifyOnReplyReceived(body);
} }
public void onSentSucceed(SentBody body){ public void onSentSucceed(SentBody body) {
CIMListenerManager.notifyOnSentSucceed(body); CIMListenerManager.notifyOnSentSucceed(body);
} }
} }

View File

@ -28,59 +28,60 @@ import com.farsunset.cim.sdk.android.model.ReplyBody;
import com.farsunset.cim.sdk.android.model.SentBody; import com.farsunset.cim.sdk.android.model.SentBody;
/** /**
*CIM 主要事件接口 * CIM 主要事件接口
*/ */
public interface CIMEventListener public interface CIMEventListener {
{
/**
* 当收到服务端推送过来的消息时调用
*
* @param message
*/
void onMessageReceived(Message message);
/** /**
* 当收到服务端推送过来的消息时调用 * 当调用CIMPushManager.sendRequest()向服务端发送请求获得相应时调用
* @param message *
*/ * @param replybody
void onMessageReceived(Message message); */
void onReplyReceived(ReplyBody replybody);
/** /**
* 当调用CIMPushManager.sendRequest()向服务端发送请求获得相应时调用 * 当调用CIMPushManager.sendRequest()向服务端发送请求成功时
* @param replybody *
*/ * @param body
void onReplyReceived(ReplyBody replybody); */
void onSentSuccessed(SentBody body);
/** /**
* 当调用CIMPushManager.sendRequest()向服务端发送请求成功时 * 当手机网络发生变化时调用
* @param body *
*/ * @param networkinfo
void onSentSuccessed(SentBody body); */
void onNetworkChanged(NetworkInfo networkinfo);
/**
/** * 当连接服务器成功时回调
* 当手机网络发生变化时调用 *
* @param networkinfo * @param hasAutoBind
*/ * : true 已经自动绑定账号到服务器了不需要再手动调用bindAccount
void onNetworkChanged(NetworkInfo networkinfo); */
void onConnectionSuccessed(boolean hasAutoBind);
/** /**
* 当连接服务器成功时回调 * 当断开服务器连接的时候回调
* @param hasAutoBind : true 已经自动绑定账号到服务器了不需要再手动调用bindAccount *
*/ */
void onConnectionSuccessed(boolean hasAutoBind); void onConnectionClosed();
/** /**
* 当断开服务器连接的时候回调 * 当连接服务器失败的时候回调
* *
*/ */
void onConnectionClosed(); void onConnectionFailed();
/** /**
* 当连接服务器失败的时候回调 * 监听器在容器里面的排序值越大则越先接收
* */
*/ int getEventDispatchOrder();
void onConnectionFailed();
/**
* 监听器在容器里面的排序值越大则越先接收
*/
int getEventDispatchOrder();
} }

View File

@ -20,6 +20,7 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.android; package com.farsunset.cim.sdk.android;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@ -30,25 +31,23 @@ import com.farsunset.cim.sdk.android.model.SentBody;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.util.Log; import android.util.Log;
/** /**
* CIM 消息监听器管理 * CIM 消息监听器管理
*/ */
public class CIMListenerManager { public class CIMListenerManager {
private static ArrayList<CIMEventListener> cimListeners = new ArrayList<CIMEventListener>(); private static ArrayList<CIMEventListener> cimListeners = new ArrayList<CIMEventListener>();
private static CIMMessageReceiveComparator comparator = new CIMMessageReceiveComparator(); private static CIMMessageReceiveComparator comparator = new CIMMessageReceiveComparator();
public static void registerMessageListener(CIMEventListener listener) { public static void registerMessageListener(CIMEventListener listener) {
if (!cimListeners.contains(listener)) { if (!cimListeners.contains(listener)) {
cimListeners.add(listener); cimListeners.add(listener);
Collections.sort(cimListeners,comparator); Collections.sort(cimListeners, comparator);
} }
} }
public static void removeMessageListener(CIMEventListener listener) { public static void removeMessageListener(CIMEventListener listener) {
for (int i = 0; i < cimListeners.size(); i++) { for (int i = 0; i < cimListeners.size(); i++) {
if (listener.getClass() == cimListeners.get(i).getClass()) { if (listener.getClass() == cimListeners.get(i).getClass()) {
@ -56,76 +55,72 @@ public class CIMListenerManager {
} }
} }
} }
public static void notifyOnNetworkChanged(NetworkInfo info) { public static void notifyOnNetworkChanged(NetworkInfo info) {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onNetworkChanged(info); listener.onNetworkChanged(info);
} }
} }
public static void notifyOnConnectionSuccessed(boolean hasAutoBind) { public static void notifyOnConnectionSuccessed(boolean hasAutoBind) {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onConnectionSuccessed(hasAutoBind); listener.onConnectionSuccessed(hasAutoBind);
} }
} }
public static void notifyOnMessageReceived(Message message) { public static void notifyOnMessageReceived(Message message) {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onMessageReceived(message); listener.onMessageReceived(message);
} }
} }
public static void notifyOnConnectionClosed() { public static void notifyOnConnectionClosed() {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onConnectionClosed(); listener.onConnectionClosed();
} }
} }
public static void notifyOnConnectionFailed() { public static void notifyOnConnectionFailed() {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onConnectionFailed(); listener.onConnectionFailed();
} }
} }
public static void notifyOnReplyReceived(ReplyBody body) { public static void notifyOnReplyReceived(ReplyBody body) {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onReplyReceived(body); listener.onReplyReceived(body);
} }
} }
public static void notifyOnSentSucceed(SentBody body) { public static void notifyOnSentSucceed(SentBody body) {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
listener.onSentSuccessed(body); listener.onSentSuccessed(body);
} }
} }
public static void destory() { public static void destory() {
cimListeners.clear(); cimListeners.clear();
} }
public static void logListenersName() { public static void logListenersName() {
for (CIMEventListener listener : cimListeners) { for (CIMEventListener listener : cimListeners) {
Log.i(CIMEventListener.class.getSimpleName(),"#######" + listener.getClass().getName() + "#######" ); Log.i(CIMEventListener.class.getSimpleName(), "#######" + listener.getClass().getName() + "#######");
} }
} }
/** /**
* 消息接收activity的接收顺序排序CIM_RECEIVE_ORDER倒序 * 消息接收activity的接收顺序排序CIM_RECEIVE_ORDER倒序
*/ */
private static class CIMMessageReceiveComparator implements Comparator<CIMEventListener>{ private static class CIMMessageReceiveComparator implements Comparator<CIMEventListener> {
@Override @Override
public int compare(CIMEventListener arg1, CIMEventListener arg2) { public int compare(CIMEventListener arg1, CIMEventListener arg2) {
int order1 = arg1.getEventDispatchOrder(); int order1 = arg1.getEventDispatchOrder();
int order2 = arg2.getEventDispatchOrder(); int order2 = arg2.getEventDispatchOrder();
return order2 - order1 ; return order2 - order1;
} }
} }
} }

View File

@ -20,6 +20,7 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.android; package com.farsunset.cim.sdk.android;
import java.util.UUID; import java.util.UUID;
import android.content.Context; import android.content.Context;
@ -34,212 +35,204 @@ import com.farsunset.cim.sdk.android.model.SentBody;
/** /**
* CIM 功能接口 * CIM 功能接口
*/ */
public class CIMPushManager { public class CIMPushManager {
static String ACTION_ACTIVATE_PUSH_SERVICE = "ACTION_ACTIVATE_PUSH_SERVICE";
static String ACTION_CREATE_CIM_CONNECTION = "ACTION_CREATE_CIM_CONNECTION";
static String ACTION_SEND_REQUEST_BODY = "ACTION_SEND_REQUEST_BODY";
static String ACTION_CLOSE_CIM_CONNECTION = "ACTION_CLOSE_CIM_CONNECTION";
static String ACTION_DESTORY = "ACTION_DESTORY";
static String KEY_SEND_BODY = "KEY_SEND_BODY";
static String KEY_CIM_CONNECTION_STATUS = "KEY_CIM_CONNECTION_STATUS";
static String ACTION_ACTIVATE_PUSH_SERVICE ="ACTION_ACTIVATE_PUSH_SERVICE";
static String ACTION_CREATE_CIM_CONNECTION ="ACTION_CREATE_CIM_CONNECTION";
static String ACTION_SEND_REQUEST_BODY ="ACTION_SEND_REQUEST_BODY";
static String ACTION_CLOSE_CIM_CONNECTION ="ACTION_CLOSE_CIM_CONNECTION";
static String ACTION_DESTORY ="ACTION_DESTORY";
static String KEY_SEND_BODY ="KEY_SEND_BODY";
static String KEY_CIM_CONNECTION_STATUS ="KEY_CIM_CONNECTION_STATUS";
/** /**
* 初始化,连接服务端在程序启动页或者 在Application里调用 * 初始化,连接服务端在程序启动页或者 在Application里调用
*
* @param context * @param context
* @param ip * @param ip
* @param port * @param port
*/ */
public static void connect(Context context,String host,int port){ public static void connect(Context context, String host, int port) {
connect(context,host,port,false,0); connect(context, host, port, false, 0);
} }
private static void connect(Context context,String ip,int port,boolean autoBind,long delayedTime){ private static void connect(Context context, String ip, int port, boolean autoBind, long delayedTime) {
CIMCacheManager.putBoolean(context,CIMCacheManager.KEY_CIM_DESTROYED, false); CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED, false);
CIMCacheManager.putBoolean(context,CIMCacheManager.KEY_MANUAL_STOP, false); CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_MANUAL_STOP, false);
CIMCacheManager.putString(context, CIMCacheManager.KEY_CIM_SERVIER_HOST, ip); CIMCacheManager.putString(context, CIMCacheManager.KEY_CIM_SERVIER_HOST, ip);
CIMCacheManager.putInt(context, CIMCacheManager.KEY_CIM_SERVIER_PORT, port); CIMCacheManager.putInt(context, CIMCacheManager.KEY_CIM_SERVIER_PORT, port);
if(!autoBind) if (!autoBind) {
{ CIMCacheManager.remove(context, CIMCacheManager.KEY_ACCOUNT);
CIMCacheManager.remove(context,CIMCacheManager.KEY_ACCOUNT);
} }
Intent serviceIntent = new Intent(context, CIMPushService.class); Intent serviceIntent = new Intent(context, CIMPushService.class);
serviceIntent.putExtra(CIMCacheManager.KEY_CIM_SERVIER_HOST, ip); serviceIntent.putExtra(CIMCacheManager.KEY_CIM_SERVIER_HOST, ip);
serviceIntent.putExtra(CIMCacheManager.KEY_CIM_SERVIER_PORT, port); serviceIntent.putExtra(CIMCacheManager.KEY_CIM_SERVIER_PORT, port);
serviceIntent.putExtra(CIMPushService.KEY_DELAYED_TIME, delayedTime); serviceIntent.putExtra(CIMPushService.KEY_DELAYED_TIME, delayedTime);
serviceIntent.setAction(ACTION_CREATE_CIM_CONNECTION); serviceIntent.setAction(ACTION_CREATE_CIM_CONNECTION);
context.startService(serviceIntent); context.startService(serviceIntent);
}
protected static void connect(Context context,long delayedTime){ }
boolean isManualStop = CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_MANUAL_STOP); protected static void connect(Context context, long delayedTime) {
boolean isManualDestory = CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_CIM_DESTROYED);
boolean isManualStop = CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_MANUAL_STOP);
if(isManualStop || isManualDestory) boolean isManualDestory = CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED);
{
return ; if (isManualStop || isManualDestory) {
return;
} }
String host = CIMCacheManager.getString(context, CIMCacheManager.KEY_CIM_SERVIER_HOST); String host = CIMCacheManager.getString(context, CIMCacheManager.KEY_CIM_SERVIER_HOST);
int port =CIMCacheManager.getInt(context, CIMCacheManager.KEY_CIM_SERVIER_PORT); int port = CIMCacheManager.getInt(context, CIMCacheManager.KEY_CIM_SERVIER_PORT);
connect(context,host,port,true,delayedTime); connect(context, host, port, true, delayedTime);
} }
/** /**
* 设置一个账号登录到服务端 * 设置一个账号登录到服务端
* @param account 用户唯一ID *
* @param account
* 用户唯一ID
*/ */
public static void bindAccount(Context context,String account){ public static void bindAccount(Context context, String account) {
boolean isManualDestory = CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_CIM_DESTROYED);
if(isManualDestory || account==null || account.trim().length()==0)
{
return ;
}
sendBindRequest(context,account);
}
private static void sendBindRequest(Context context, String account){
CIMCacheManager.putBoolean(context,CIMCacheManager.KEY_MANUAL_STOP, false);
CIMCacheManager.putString(context,CIMCacheManager.KEY_ACCOUNT, account);
String deviceId = CIMCacheManager.getString(context,CIMCacheManager.KEY_DEVICE_ID);
if(TextUtils.isEmpty(deviceId)) {
deviceId = UUID.randomUUID().toString().replaceAll("-", "");
CIMCacheManager.putString(context,CIMCacheManager.KEY_DEVICE_ID, deviceId);
}
SentBody sent = new SentBody(); boolean isManualDestory = CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED);
if (isManualDestory || account == null || account.trim().length() == 0) {
return;
}
sendBindRequest(context, account);
}
private static void sendBindRequest(Context context, String account) {
CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_MANUAL_STOP, false);
CIMCacheManager.putString(context, CIMCacheManager.KEY_ACCOUNT, account);
String deviceId = CIMCacheManager.getString(context, CIMCacheManager.KEY_DEVICE_ID);
if (TextUtils.isEmpty(deviceId)) {
deviceId = UUID.randomUUID().toString().replaceAll("-", "");
CIMCacheManager.putString(context, CIMCacheManager.KEY_DEVICE_ID, deviceId);
}
SentBody sent = new SentBody();
sent.setKey(CIMConstant.RequestKey.CLIENT_BIND); sent.setKey(CIMConstant.RequestKey.CLIENT_BIND);
sent.put("account", account); sent.put("account", account);
sent.put("deviceId",deviceId); sent.put("deviceId", deviceId);
sent.put("channel", "android"); sent.put("channel", "android");
sent.put("device",android.os.Build.MODEL); sent.put("device", android.os.Build.MODEL);
sent.put("version",getVersionName(context)); sent.put("version", getVersionName(context));
sent.put("osVersion",android.os.Build.VERSION.RELEASE); sent.put("osVersion", android.os.Build.VERSION.RELEASE);
sent.put("packageName",context.getPackageName()); sent.put("packageName", context.getPackageName());
sendRequest(context,sent); sendRequest(context, sent);
}
protected static boolean autoBindAccount(Context context){
String account = CIMCacheManager.getString(context,CIMCacheManager.KEY_ACCOUNT);
boolean isManualDestory = CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_CIM_DESTROYED);
if( account==null || account.trim().length()==0 || isManualDestory )
{
return false;
}
sendBindRequest(context,account);
return true;
} }
protected static boolean autoBindAccount(Context context) {
String account = CIMCacheManager.getString(context, CIMCacheManager.KEY_ACCOUNT);
/** boolean isManualDestory = CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED);
if (account == null || account.trim().length() == 0 || isManualDestory) {
return false;
}
sendBindRequest(context, account);
return true;
}
/**
* 发送一个CIM请求 * 发送一个CIM请求
*
* @param context * @param context
* @body * @body
*/ */
public static void sendRequest(Context context, SentBody body){ public static void sendRequest(Context context, SentBody body) {
boolean isManualStop = CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_MANUAL_STOP); boolean isManualStop = CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_MANUAL_STOP);
boolean isManualDestory = CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_CIM_DESTROYED); boolean isManualDestory = CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED);
if(isManualStop || isManualDestory) if (isManualStop || isManualDestory) {
{ return;
return ;
} }
Intent serviceIntent = new Intent(context, CIMPushService.class); Intent serviceIntent = new Intent(context, CIMPushService.class);
serviceIntent.putExtra(KEY_SEND_BODY, body); serviceIntent.putExtra(KEY_SEND_BODY, body);
serviceIntent.setAction(ACTION_SEND_REQUEST_BODY); serviceIntent.setAction(ACTION_SEND_REQUEST_BODY);
context.startService(serviceIntent); context.startService(serviceIntent);
} }
/** /**
* 停止接受推送将会退出当前账号登录端口与服务端的连接 * 停止接受推送将会退出当前账号登录端口与服务端的连接
*
* @param context * @param context
*/ */
public static void stop(Context context){ public static void stop(Context context) {
boolean isManualDestory = CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_CIM_DESTROYED);
if(isManualDestory){
return ;
}
CIMCacheManager.putBoolean(context,CIMCacheManager.KEY_MANUAL_STOP, true);
Intent serviceIntent = new Intent(context, CIMPushService.class); boolean isManualDestory = CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED);
if (isManualDestory) {
return;
}
CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_MANUAL_STOP, true);
Intent serviceIntent = new Intent(context, CIMPushService.class);
serviceIntent.setAction(ACTION_CLOSE_CIM_CONNECTION); serviceIntent.setAction(ACTION_CLOSE_CIM_CONNECTION);
context.startService(serviceIntent); context.startService(serviceIntent);
} }
/**
/**
* 完全销毁CIM一般用于完全退出程序调用resume将不能恢复 * 完全销毁CIM一般用于完全退出程序调用resume将不能恢复
*
* @param context * @param context
*/ */
public static void destroy(Context context){ public static void destroy(Context context) {
CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED, true);
CIMCacheManager.putBoolean(context,CIMCacheManager.KEY_CIM_DESTROYED, true); CIMCacheManager.putString(context, CIMCacheManager.KEY_ACCOUNT, null);
CIMCacheManager.putString(context,CIMCacheManager.KEY_ACCOUNT, null);
Intent serviceIntent = new Intent(context, CIMPushService.class);
Intent serviceIntent = new Intent(context, CIMPushService.class);
serviceIntent.setAction(ACTION_DESTORY); serviceIntent.setAction(ACTION_DESTORY);
context.startService(serviceIntent); context.startService(serviceIntent);
} }
/**
/** * 重新恢复接收推送重新连接服务端并登录当前账号
* 重新恢复接收推送重新连接服务端并登录当前账号 *
* @param context * @param context
*/ */
public static void resume(Context context){ public static void resume(Context context) {
boolean isManualDestory = CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_CIM_DESTROYED); boolean isManualDestory = CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED);
if(isManualDestory){ if (isManualDestory) {
return ; return;
} }
autoBindAccount(context); autoBindAccount(context);
} }
public static boolean isConnected(Context context){ public static boolean isConnected(Context context) {
return CIMCacheManager.getBoolean(context,CIMCacheManager.KEY_CIM_CONNECTION_STATE); return CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_CIM_CONNECTION_STATE);
} }
private static String getVersionName(Context context) {
String versionName = null;
private static String getVersionName(Context context) {
String versionName = null;
try { try {
PackageInfo mPackageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); PackageInfo mPackageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
versionName = mPackageInfo.versionName; versionName = mPackageInfo.versionName;

View File

@ -20,6 +20,7 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.android; package com.farsunset.cim.sdk.android;
import android.app.Service; import android.app.Service;
import android.content.Intent; import android.content.Intent;
import android.os.Handler; import android.os.Handler;
@ -28,98 +29,88 @@ import android.os.Message;
import android.util.Log; import android.util.Log;
import com.farsunset.cim.sdk.android.model.SentBody; import com.farsunset.cim.sdk.android.model.SentBody;
/** /**
* 与服务端连接服务 * 与服务端连接服务
*
* @author 3979434 * @author 3979434
* *
*/ */
public class CIMPushService extends Service { public class CIMPushService extends Service {
private final String TAG = CIMPushService.class.getSimpleName(); private final String TAG = CIMPushService.class.getSimpleName();
public final static String KEY_DELAYED_TIME ="KEY_DELAYED_TIME"; public final static String KEY_DELAYED_TIME = "KEY_DELAYED_TIME";
private CIMConnectorManager manager; private CIMConnectorManager manager;
@Override
public void onCreate() @Override
{ public void onCreate() {
manager = CIMConnectorManager.getManager(this.getApplicationContext()); manager = CIMConnectorManager.getManager(this.getApplicationContext());
} }
Handler connectionHandler = new Handler() {
Handler connectionHandler = new Handler(){
@Override @Override
public void handleMessage(android.os.Message message){ public void handleMessage(android.os.Message message) {
connectionHandler.removeMessages(0); connectionHandler.removeMessages(0);
String host = message.getData().getString(CIMCacheManager.KEY_CIM_SERVIER_HOST); String host = message.getData().getString(CIMCacheManager.KEY_CIM_SERVIER_HOST);
int port = message.getData().getInt(CIMCacheManager.KEY_CIM_SERVIER_PORT,0); int port = message.getData().getInt(CIMCacheManager.KEY_CIM_SERVIER_PORT, 0);
manager.connect(host, port); manager.connect(host, port);
} }
}; };
@Override
@Override public int onStartCommand(Intent intent, int flags, int startId) {
public int onStartCommand(Intent intent,int flags, int startId) {
intent = (intent == null ? new Intent(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE) : intent);
intent = (intent == null ? new Intent(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE) : intent); String action = intent.getAction();
String action = intent.getAction(); if (CIMPushManager.ACTION_CREATE_CIM_CONNECTION.equals(action)) {
if(CIMPushManager.ACTION_CREATE_CIM_CONNECTION.equals(action)) long delayMillis = intent.getLongExtra(KEY_DELAYED_TIME, 0);
{ if (delayMillis > 0) {
long delayMillis = intent.getLongExtra(KEY_DELAYED_TIME,0); Message msg = connectionHandler.obtainMessage();
if( delayMillis > 0){ msg.what = 0;
msg.setData(intent.getExtras());
Message msg = connectionHandler.obtainMessage(); connectionHandler.sendMessageDelayed(msg, delayMillis);
msg.what = 0;
msg.setData(intent.getExtras()); } else {
connectionHandler.sendMessageDelayed(msg, delayMillis); String host = intent.getStringExtra(CIMCacheManager.KEY_CIM_SERVIER_HOST);
int port = intent.getIntExtra(CIMCacheManager.KEY_CIM_SERVIER_PORT, 0);
}else manager.connect(host, port);
{ }
String host = intent.getStringExtra(CIMCacheManager.KEY_CIM_SERVIER_HOST); }
int port = intent.getIntExtra(CIMCacheManager.KEY_CIM_SERVIER_PORT,0);
manager.connect(host,port); if (CIMPushManager.ACTION_SEND_REQUEST_BODY.equals(action)) {
} manager.send((SentBody) intent.getSerializableExtra(CIMPushManager.KEY_SEND_BODY));
} }
if(CIMPushManager.ACTION_SEND_REQUEST_BODY.equals(action)) if (CIMPushManager.ACTION_CLOSE_CIM_CONNECTION.equals(action)) {
{ manager.closeSession();
manager.send((SentBody) intent.getSerializableExtra(CIMPushManager.KEY_SEND_BODY)); }
}
if (CIMPushManager.ACTION_DESTORY.equals(action)) {
if(CIMPushManager.ACTION_CLOSE_CIM_CONNECTION.equals(action)) manager.destroy();
{ this.stopSelf();
manager.closeSession(); }
}
if (CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE.equals(action)) {
if(CIMPushManager.ACTION_DESTORY.equals(action)) if (!manager.isConnected()) {
{
manager.destroy(); boolean isManualStop = CIMCacheManager.getBoolean(getApplicationContext(),
this.stopSelf(); CIMCacheManager.KEY_MANUAL_STOP);
} Log.w(TAG, "manager.isConnected() == false, isManualStop == " + isManualStop);
CIMPushManager.connect(this, 0);
if(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE.equals(action) )
{ } else {
if(!manager.isConnected()){ Log.i(TAG, "manager.isConnected() == true");
}
boolean isManualStop = CIMCacheManager.getBoolean(getApplicationContext(),CIMCacheManager.KEY_MANUAL_STOP);
Log.w(TAG, "manager.isConnected() == false, isManualStop == " + isManualStop); }
CIMPushManager.connect(this,0);
return START_STICKY;
}else }
{
Log.i(TAG, "manager.isConnected() == true");
}
}
return START_STICKY;
}
@Override @Override
public IBinder onBind(Intent arg0) { public IBinder onBind(Intent arg0) {
return null; return null;

View File

@ -21,93 +21,88 @@
*/ */
package com.farsunset.cim.sdk.android.constant; package com.farsunset.cim.sdk.android.constant;
/** /**
* 常量 * 常量
*/ */
public interface CIMConstant { public interface CIMConstant {
long RECONN_INTERVAL_TIME= 30 * 1000; long RECONN_INTERVAL_TIME = 30 * 1000;
//消息头长度为3个字节第一个字节为消息类型第二第三字节 转换int后为消息长度 // 消息头长度为3个字节第一个字节为消息类型第二第三字节 转换int后为消息长度
int DATA_HEADER_LENGTH = 3; int DATA_HEADER_LENGTH = 3;
public static interface ReturnCode{
public static interface ReturnCode {
String CODE_404 ="404";
String CODE_404 = "404";
String CODE_403 ="403";
String CODE_403 = "403";
String CODE_405 ="405";
String CODE_405 = "405";
String CODE_200 ="200";
String CODE_200 = "200";
String CODE_206 ="206";
String CODE_206 = "206";
String CODE_500 ="500";
String CODE_500 = "500";
} }
public static interface ProtobufType {
byte C_H_RS = 0;
byte S_H_RQ = 1;
byte MESSAGE = 2;
byte SENTBODY = 3;
byte REPLYBODY = 4;
}
public static interface RequestKey {
String CLIENT_BIND = "client_bind";
String CLIENT_LOGOUT = "client_logout";
public static interface ProtobufType{
byte C_H_RS = 0;
byte S_H_RQ = 1;
byte MESSAGE = 2;
byte SENTBODY = 3;
byte REPLYBODY = 4;
}
public static interface RequestKey{
String CLIENT_BIND ="client_bind";
String CLIENT_LOGOUT ="client_logout";
@Deprecated @Deprecated
String CLIENT_PULL_MESSAGE ="client_pull_message"; String CLIENT_PULL_MESSAGE = "client_pull_message";
} }
public static interface MessageAction {
public static interface MessageAction{
// 被其他设备登录挤下线消息
//被其他设备登录挤下线消息 String ACTION_999 = "999";
String ACTION_999 ="999"; }
}
public static interface IntentAction {
public static interface IntentAction{ // 消息广播action
String ACTION_MESSAGE_RECEIVED = "com.farsunset.cim.MESSAGE_RECEIVED";
// 消息广播action
String ACTION_MESSAGE_RECEIVED = "com.farsunset.cim.MESSAGE_RECEIVED"; // 发送sendbody失败广播
String ACTION_SENT_FAILED = "com.farsunset.cim.SENT_FAILED";
// 发送sendbody失败广播
String ACTION_SENT_FAILED = "com.farsunset.cim.SENT_FAILED"; // 发送sendbody成功广播
String ACTION_SENT_SUCCESSED = "com.farsunset.cim.SENT_SUCCESSED";
// 发送sendbody成功广播
String ACTION_SENT_SUCCESSED = "com.farsunset.cim.SENT_SUCCESSED"; // 链接意外关闭广播
String ACTION_CONNECTION_CLOSED = "com.farsunset.cim.CONNECTION_CLOSED";
// 链接意外关闭广播
String ACTION_CONNECTION_CLOSED = "com.farsunset.cim.CONNECTION_CLOSED"; // 链接失败广播
String ACTION_CONNECTION_FAILED = "com.farsunset.cim.CONNECTION_FAILED";
// 链接失败广播
String ACTION_CONNECTION_FAILED = "com.farsunset.cim.CONNECTION_FAILED"; // 链接成功广播
String ACTION_CONNECTION_SUCCESSED = "com.farsunset.cim.CONNECTION_SUCCESSED";
// 链接成功广播
String ACTION_CONNECTION_SUCCESSED = "com.farsunset.cim.CONNECTION_SUCCESSED"; // 发送sendbody成功后获得replaybody回应广播
String ACTION_REPLY_RECEIVED = "com.farsunset.cim.REPLY_RECEIVED";
// 发送sendbody成功后获得replaybody回应广播
String ACTION_REPLY_RECEIVED = "com.farsunset.cim.REPLY_RECEIVED"; // 网络变化广播
String ACTION_NETWORK_CHANGED = "android.net.conn.CONNECTIVITY_CHANGE";
// 网络变化广播
String ACTION_NETWORK_CHANGED = "android.net.conn.CONNECTIVITY_CHANGE"; // 重试连接
String ACTION_CONNECTION_RECOVERY = "com.farsunset.cim.CONNECTION_RECOVERY";
//重试连接
String ACTION_CONNECTION_RECOVERY = "com.farsunset.cim.CONNECTION_RECOVERY"; // 未知异常
String ACTION_UNCAUGHT_EXCEPTION = "com.farsunset.cim.UNCAUGHT_EXCEPTION";
// 未知异常 }
String ACTION_UNCAUGHT_EXCEPTION = "com.farsunset.cim.UNCAUGHT_EXCEPTION";
}
} }

View File

@ -23,14 +23,14 @@ package com.farsunset.cim.sdk.android.exception;
import java.io.Serializable; import java.io.Serializable;
public class NetworkDisabledException extends Exception implements Serializable { public class NetworkDisabledException extends Exception implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public NetworkDisabledException() { public NetworkDisabledException() {
super(); super();
} }
public NetworkDisabledException(String s) { public NetworkDisabledException(String s) {
super(s); super(s);
} }

View File

@ -24,7 +24,7 @@ package com.farsunset.cim.sdk.android.exception;
import java.io.Serializable; import java.io.Serializable;
public class SessionClosedException extends Exception implements Serializable { public class SessionClosedException extends Exception implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public SessionClosedException() { public SessionClosedException() {

View File

@ -41,6 +41,7 @@ import io.netty.handler.codec.ByteToMessageDecoder;
*/ */
public class ClientMessageDecoder extends ByteToMessageDecoder { public class ClientMessageDecoder extends ByteToMessageDecoder {
final static String TAG = ClientMessageDecoder.class.getSimpleName(); final static String TAG = ClientMessageDecoder.class.getSimpleName();
@Override @Override
protected void decode(ChannelHandlerContext arg0, ByteBuf buffer, List<Object> queue) throws Exception { protected void decode(ChannelHandlerContext arg0, ByteBuf buffer, List<Object> queue) throws Exception {
@ -72,8 +73,8 @@ public class ClientMessageDecoder extends ByteToMessageDecoder {
buffer.readBytes(dataBytes); buffer.readBytes(dataBytes);
Object message = mappingMessageObject(dataBytes, conetnType); Object message = mappingMessageObject(dataBytes, conetnType);
if(message!=null){ if (message != null) {
queue.add(message); queue.add(message);
} }

View File

@ -21,7 +21,6 @@
*/ */
package com.farsunset.cim.sdk.android.filter; package com.farsunset.cim.sdk.android.filter;
import com.farsunset.cim.sdk.android.constant.CIMConstant; import com.farsunset.cim.sdk.android.constant.CIMConstant;
import com.farsunset.cim.sdk.android.model.Protobufable; import com.farsunset.cim.sdk.android.model.Protobufable;
@ -31,46 +30,41 @@ import io.netty.handler.codec.MessageToByteEncoder;
import android.util.Log; import android.util.Log;
/** /**
* 客户端消息发送前进行编码,可在此加密消息 * 客户端消息发送前进行编码,可在此加密消息
* *
*/ */
public class ClientMessageEncoder extends MessageToByteEncoder<Object> { public class ClientMessageEncoder extends MessageToByteEncoder<Object> {
@Override @Override
protected void encode(ChannelHandlerContext ctx, Object message, ByteBuf out) throws Exception { protected void encode(ChannelHandlerContext ctx, Object message, ByteBuf out) throws Exception {
if (message instanceof Protobufable) {
if(message instanceof Protobufable){
Protobufable data = (Protobufable) message;
Protobufable data = (Protobufable) message; byte[] byteArray = data.getByteArray();
byte[] byteArray = data.getByteArray();
out.writeBytes(createHeader(data.getType(), byteArray.length));
out.writeBytes(byteArray);
out.writeBytes(createHeader(data.getType(),byteArray.length));
out.writeBytes(byteArray); }
}
Log.i(ClientMessageEncoder.class.getSimpleName(), message.toString()); Log.i(ClientMessageEncoder.class.getSimpleName(), message.toString());
} }
/** /**
* 消息体最大为65535 * 消息体最大为65535
*
* @param type * @param type
* @param length * @param length
* @return * @return
*/ */
private byte[] createHeader(byte type,int length){ private byte[] createHeader(byte type, int length) {
byte[] header = new byte[CIMConstant.DATA_HEADER_LENGTH]; byte[] header = new byte[CIMConstant.DATA_HEADER_LENGTH];
header[0] = type; header[0] = type;
header[1] = (byte) (length & 0xff); header[1] = (byte) (length & 0xff);
header[2] = (byte) ((length >> 8) & 0xff); header[2] = (byte) ((length >> 8) & 0xff);
return header; return header;
} }
} }

View File

@ -24,39 +24,39 @@ package com.farsunset.cim.sdk.android.model;
import java.io.Serializable; import java.io.Serializable;
import com.farsunset.cim.sdk.android.constant.CIMConstant; import com.farsunset.cim.sdk.android.constant.CIMConstant;
/** /**
* 服务端心跳请求 * 服务端心跳请求
* *
*/ */
public class HeartbeatRequest implements Serializable,Protobufable { public class HeartbeatRequest implements Serializable, Protobufable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final String TAG = "SERVER_HEARTBEAT_REQUEST"; private static final String TAG = "SERVER_HEARTBEAT_REQUEST";
private static final String CMD_HEARTBEAT_RESPONSE = "SR"; private static final String CMD_HEARTBEAT_RESPONSE = "SR";
private static HeartbeatRequest object = new HeartbeatRequest(); private static HeartbeatRequest object = new HeartbeatRequest();
private HeartbeatRequest(){ private HeartbeatRequest() {
} }
public static HeartbeatRequest getInstance() { public static HeartbeatRequest getInstance() {
return object; return object;
} }
@Override @Override
public byte[] getByteArray() { public byte[] getByteArray() {
return CMD_HEARTBEAT_RESPONSE.getBytes(); return CMD_HEARTBEAT_RESPONSE.getBytes();
} }
public String toString(){ public String toString() {
return TAG; return TAG;
} }
@Override @Override
public byte getType() { public byte getType() {
return CIMConstant.ProtobufType.S_H_RQ; return CIMConstant.ProtobufType.S_H_RQ;
} }
} }

View File

@ -24,30 +24,32 @@ package com.farsunset.cim.sdk.android.model;
import java.io.Serializable; import java.io.Serializable;
import com.farsunset.cim.sdk.android.constant.CIMConstant; import com.farsunset.cim.sdk.android.constant.CIMConstant;
/** /**
* 客户端心跳响应 * 客户端心跳响应
*/ */
public class HeartbeatResponse implements Serializable,Protobufable { public class HeartbeatResponse implements Serializable, Protobufable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final String TAG = "CLIENT_HEARTBEAT_RESPONSE"; private static final String TAG = "CLIENT_HEARTBEAT_RESPONSE";
private static final String CMD_HEARTBEAT_RESPONSE = "CR"; private static final String CMD_HEARTBEAT_RESPONSE = "CR";
private static HeartbeatResponse object = new HeartbeatResponse(); private static HeartbeatResponse object = new HeartbeatResponse();
private HeartbeatResponse(){ private HeartbeatResponse() {
} }
public static HeartbeatResponse getInstance() { public static HeartbeatResponse getInstance() {
return object; return object;
} }
@Override @Override
public byte[] getByteArray() { public byte[] getByteArray() {
return CMD_HEARTBEAT_RESPONSE.getBytes(); return CMD_HEARTBEAT_RESPONSE.getBytes();
} }
public String toString(){ public String toString() {
return TAG; return TAG;
} }
@ -55,5 +57,5 @@ public class HeartbeatResponse implements Serializable,Protobufable {
public byte getType() { public byte getType() {
return CIMConstant.ProtobufType.C_H_RS; return CIMConstant.ProtobufType.C_H_RS;
} }
} }

View File

@ -30,13 +30,11 @@ public class Message implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 消息类型用户自定义消息类别 * 消息类型用户自定义消息类别
*/ */
private String mid; private String mid;
/** /**
* 消息类型用户自定义消息类别 * 消息类型用户自定义消息类别
*/ */
@ -59,8 +57,6 @@ public class Message implements Serializable {
*/ */
private String receiver; private String receiver;
/** /**
* content 内容格式 * content 内容格式
*/ */
@ -72,12 +68,11 @@ public class Message implements Serializable {
private String extra; private String extra;
private long timestamp; private long timestamp;
public Message() {
public Message()
{
timestamp = System.currentTimeMillis(); timestamp = System.currentTimeMillis();
} }
public long getTimestamp() { public long getTimestamp() {
return timestamp; return timestamp;
} }
@ -86,14 +81,14 @@ public class Message implements Serializable {
this.timestamp = timestamp; this.timestamp = timestamp;
} }
public String getAction() { public String getAction() {
return action; return action;
} }
public void setAction(String action) { public void setAction(String action) {
this.action = action; this.action = action;
} }
public String getTitle() { public String getTitle() {
return title; return title;
} }
@ -126,7 +121,6 @@ public class Message implements Serializable {
this.receiver = receiver; this.receiver = receiver;
} }
public String getFormat() { public String getFormat() {
return format; return format;
} }
@ -134,17 +128,17 @@ public class Message implements Serializable {
public void setFormat(String format) { public void setFormat(String format) {
this.format = format; this.format = format;
} }
public String getExtra() { public String getExtra() {
return extra; return extra;
} }
public void setExtra(String extra) { public void setExtra(String extra) {
this.extra = extra; this.extra = extra;
} }
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("#Message#").append("\n"); buffer.append("#Message#").append("\n");
buffer.append("mid:").append(mid).append("\n"); buffer.append("mid:").append(mid).append("\n");
@ -158,7 +152,6 @@ public class Message implements Serializable {
buffer.append("timestamp:").append(timestamp); buffer.append("timestamp:").append(timestamp);
return buffer.toString(); return buffer.toString();
} }
public String getMid() { public String getMid() {
return mid; return mid;
@ -169,8 +162,7 @@ public class Message implements Serializable {
} }
public boolean isNotEmpty(String txt) { public boolean isNotEmpty(String txt) {
return txt != null && txt.trim().length()!=0; return txt != null && txt.trim().length() != 0;
} }
} }

View File

@ -20,12 +20,13 @@
*************************************************************************************** ***************************************************************************************
*/ */
package com.farsunset.cim.sdk.android.model; package com.farsunset.cim.sdk.android.model;
/** /**
* 需要向另一端发送的结构体 * 需要向另一端发送的结构体
*/ */
public interface Protobufable { public interface Protobufable {
byte[] getByteArray(); byte[] getByteArray();
byte getType(); byte getType();
} }

Some files were not shown because too many files have changed in this diff Show More