Merge branch 'master' of http://gitlab.zhidaoauto.com/ITC/Apps/MoGoAiCloudSdk
This commit is contained in:
@@ -29,7 +29,7 @@ public class LocationActivity extends AppCompatActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_location);
|
||||
MogoLocationInfoServices.getInstance().init(this);
|
||||
SocketHandler.getInstance().initSocket(this, MoGoAiCloudClientConfig.getInstance().getServiceAppId());
|
||||
SocketHandler.getInstance().initSocket(this, MoGoAiCloudClientConfig.getInstance().getServiceAppId(),0,0);
|
||||
|
||||
MogoLocation mogoLocation = new MogoLocation();
|
||||
mogoLocation.setAccuracy(0.0f);
|
||||
|
||||
@@ -118,7 +118,7 @@ internal class HttpDnsHelper(private val builder: MogoHttpDnsConfig) : Handler.C
|
||||
return defaultUrl ?: host
|
||||
}
|
||||
|
||||
override fun getHttpDnsCachedAddress(type: Int, _host: String): String? {
|
||||
override fun getHttpDnsCachedAddress(type: Int, _host: String): String {
|
||||
val host = _host.toLowerCase(Locale.getDefault())
|
||||
httpDnsCache?.let {
|
||||
val currentLoc = builder.getCurrentLocation()?.getCurrentLocation()
|
||||
@@ -140,7 +140,7 @@ internal class HttpDnsHelper(private val builder: MogoHttpDnsConfig) : Handler.C
|
||||
}
|
||||
}
|
||||
val default = defaultUrl ?: host
|
||||
return addressMap?.get("$type-$host")
|
||||
return addressMap?.get("$type-$host") ?: default
|
||||
}
|
||||
|
||||
override fun getAllAddress(): Map<String, String>? {
|
||||
|
||||
@@ -18,7 +18,7 @@ object MogoHttpDnsClient : IMogoHttpDns {
|
||||
* 先从本地缓存中根据type和host获取ip:port,如果本地缓存中没有,再通过网络获取
|
||||
*/
|
||||
fun getHttpDnsAddressUseCacheIfNecessary(type: Int, _host: String): String? {
|
||||
return getHttpDnsCachedAddress(type, _host) ?: return getHttpDnsAddress(type, _host)
|
||||
return getHttpDnsCachedAddress(type, _host)
|
||||
}
|
||||
|
||||
override fun addressChangedListener(addressChangedListener: OnAddressChangedListener) {
|
||||
|
||||
@@ -46,7 +46,7 @@ public class SocketMsgUtils implements IMogoCloudSocketMsgAckListener {
|
||||
Logger.i(TAG, "初始化长连接……");
|
||||
mSocketManager = SocketManager.getInstance();
|
||||
mMessageListener = listener;
|
||||
mSocketManager.init(mContext);
|
||||
mSocketManager.init(mContext,0,0);
|
||||
mSocketManager.registerOnMessageListener(401017, listener);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@ import com.mogo.cloud.location.third.core.Location;
|
||||
import com.mogo.cloud.location.third.core.LocationDelegateManager;
|
||||
import com.mogo.cloud.location.third.core.LocationServiceProvider;
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
|
||||
import com.mogo.cloud.socket.third.core.SocketClient;
|
||||
import com.zhidao.ptech.connsvr.commom.protocol.MogoCommon;
|
||||
import com.zhidao.ptech.connsvr.payload.protocol.MogoPayload;
|
||||
import com.zhidao.ptech.connsvr.protocol.MogoConnsvr;
|
||||
import com.zhidao.socket.SocketClient;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -16,11 +16,11 @@ import com.mogo.cloud.location.third.core.LocUploadConfig;
|
||||
import com.mogo.cloud.location.third.core.Location;
|
||||
import com.mogo.cloud.location.third.core.LocationDelegateManager;
|
||||
import com.mogo.cloud.location.third.core.LocationServiceProvider;
|
||||
import com.mogo.cloud.socket.third.core.Callback;
|
||||
import com.mogo.cloud.socket.third.core.CallbackManager;
|
||||
import com.mogo.cloud.socket.third.core.SocketClient;
|
||||
import com.zhidao.ptech.connsvr.payload.protocol.MogoPayload;
|
||||
import com.zhidao.ptech.connsvr.protocol.MogoConnsvr;
|
||||
import com.zhidao.socket.Callback;
|
||||
import com.zhidao.socket.CallbackManager;
|
||||
import com.zhidao.socket.SocketClient;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
|
||||
@@ -48,6 +48,9 @@ public class MoGoAiCloudClientConfig {
|
||||
*/
|
||||
private String authPubKey = "";
|
||||
|
||||
// 必传, Socket长链接时做校验
|
||||
private String secretKey = "";
|
||||
|
||||
/**
|
||||
* 签名信息
|
||||
*/
|
||||
@@ -162,6 +165,25 @@ public class MoGoAiCloudClientConfig {
|
||||
this.authPubKey = authPubKey;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取长链接公钥匙
|
||||
*
|
||||
* @return 授权公钥匙
|
||||
*/
|
||||
public String getSecretKey() {
|
||||
return secretKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置长链接公钥匙
|
||||
*
|
||||
* @param authPubKey 授权公钥匙
|
||||
*/
|
||||
public void setSecretKey(String secretKey) {
|
||||
this.secretKey = secretKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取AI云平台分配给三方应用的签名密钥,需要从AI云平台申请
|
||||
*
|
||||
|
||||
@@ -36,6 +36,9 @@ dependencies {
|
||||
// socket-for-internal 长链 内部SDK版本
|
||||
implementation 'com.zhidao.socketsdk:socketsdk:2.1.4'
|
||||
|
||||
// socket-for-sdk 长链 http://wiki.zhidaohulian.com/pages/viewpage.action?pageId=48956182 外部SDK版本
|
||||
api 'com.zhidao.socket:built-in-socket:1.0.24'
|
||||
|
||||
|
||||
if (Boolean.valueOf(RELEASE)) {
|
||||
implementation "com.mogo.cloud:passport:${MOGO_PASSPORT_VERSION}"
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.mogo.cloud.socket;
|
||||
import android.content.Context;
|
||||
|
||||
import com.mogo.cloud.socket.entity.MsgBody;
|
||||
import com.mogo.cloud.socket.third.core.ConnectionLifecycleListener;
|
||||
import com.zhidao.socket.ConnectionLifecycleListener;
|
||||
|
||||
|
||||
/**
|
||||
@@ -16,7 +16,7 @@ public interface IMogoCloudSocketManager {
|
||||
*
|
||||
* @param context 上下文
|
||||
*/
|
||||
void init(Context context);
|
||||
void init(Context context, double lat, double lon);
|
||||
|
||||
/**
|
||||
* 注册消息监听
|
||||
@@ -35,13 +35,11 @@ public interface IMogoCloudSocketManager {
|
||||
void unregisterOnMessageListener(int msgType, IMogoCloudSocketOnMessageListener listener);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
void registerSocketConnCallback(ConnectionLifecycleListener listener);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
void unregisterSocketConnCallback(ConnectionLifecycleListener listener);
|
||||
|
||||
@@ -17,8 +17,8 @@ import com.mogo.cloud.socket.entity.MsgBody;
|
||||
import com.mogo.cloud.socket.entity.SocketDownData;
|
||||
import com.mogo.cloud.socket.internal.InternalSocketManager;
|
||||
import com.mogo.cloud.socket.third.ThirdSocketManager;
|
||||
import com.mogo.cloud.socket.third.core.ConnectionLifecycleListener;
|
||||
import com.zhidao.ptech.connsvr.protocol.MogoConnsvr;
|
||||
import com.zhidao.socket.ConnectionLifecycleListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@@ -70,9 +70,9 @@ public class SocketManager implements IMogoCloudSocketManager {
|
||||
private int mCurrentIndex = 0;
|
||||
|
||||
@Override
|
||||
public void init(Context context) {
|
||||
public void init(Context context, double lat, double lon) {
|
||||
if (cloudClientConfig.isThirdLogin()) {
|
||||
ThirdSocketManager.getInstance().init(context);
|
||||
ThirdSocketManager.getInstance().init(context, lat, lon);
|
||||
} else {
|
||||
InternalSocketManager.getInstance().init(context);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import androidx.annotation.Keep;
|
||||
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClient;
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
|
||||
import com.mogo.cloud.socket.third.core.Environment;
|
||||
import com.zhidao.socket.Environment;
|
||||
|
||||
public class SocketServicesConstants {
|
||||
|
||||
|
||||
@@ -3,8 +3,10 @@ package com.mogo.cloud.socket.third;
|
||||
import static com.mogo.cloud.socket.SocketServicesConstants.SOCKET_CHANNEL_ID;
|
||||
import static com.mogo.cloud.socket.SocketServicesConstants.getEnvironment;
|
||||
import static com.mogo.cloud.socket.SocketServicesConstants.getTag;
|
||||
import static com.zhidao.socket.location.MLocation.GCJ02;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
@@ -14,12 +16,13 @@ import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
|
||||
import com.mogo.cloud.socket.SocketBuildConfig;
|
||||
import com.mogo.cloud.socket.SocketManager;
|
||||
import com.mogo.cloud.socket.SocketServicesConstants;
|
||||
import com.mogo.cloud.socket.third.core.Callback;
|
||||
import com.mogo.cloud.socket.third.core.CallbackManager;
|
||||
import com.mogo.cloud.socket.third.core.ConnectionLifecycleListener;
|
||||
import com.mogo.cloud.socket.third.core.SocketClient;
|
||||
import com.mogo.cloud.socket.third.core.SocketConfig;
|
||||
import com.zhidao.ptech.connsvr.commom.protocol.MogoCommon;
|
||||
import com.zhidao.socket.Callback;
|
||||
import com.zhidao.socket.CallbackManager;
|
||||
import com.zhidao.socket.ConnectionLifecycleListener;
|
||||
import com.zhidao.socket.SocketClient;
|
||||
import com.zhidao.socket.SocketConfig;
|
||||
import com.zhidao.socket.location.MLocation;
|
||||
|
||||
public class ThirdSocketManager implements Callback {
|
||||
|
||||
@@ -42,7 +45,11 @@ public class ThirdSocketManager implements Callback {
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
public void init(Context context) {
|
||||
public void init(Context context, double lat, double lon) {
|
||||
MLocation mLocation = new MLocation();
|
||||
mLocation.setCoordinate(GCJ02);
|
||||
mLocation.setLatitude(lat);
|
||||
mLocation.setLongitude(lon);
|
||||
SocketConfig.instance()
|
||||
.setAppContext(context.getApplicationContext())
|
||||
.setEnvironment(getEnvironment())
|
||||
@@ -51,12 +58,15 @@ public class ThirdSocketManager implements Callback {
|
||||
.setOpenAnalytics(true)
|
||||
.setSn(cloudClientConfig.getSn())
|
||||
.setToken(cloudClientConfig.getToken())
|
||||
.setSecretKey(cloudClientConfig.getSecretKey())
|
||||
.setAuthPubKey(cloudClientConfig.getAuthPubKey())
|
||||
.setDebug(cloudClientConfig.isShowDebugLog());
|
||||
.setDebug(cloudClientConfig.isShowDebugLog())
|
||||
.setLocation(mLocation);
|
||||
SocketClient.getInstance().registerSocketCallback(this);
|
||||
SocketClient.getInstance().start(context);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(@NonNull CallbackManager manager, @NonNull byte[] message, String appId, long msgId) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.analytics;
|
||||
|
||||
import com.elegant.analytics.Analytics;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
public class EventManager {
|
||||
|
||||
private static SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA);
|
||||
|
||||
public static void trackEvent(String event, JSONObject jsonObject) {
|
||||
if (jsonObject == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
jsonObject.put("time", getCurrentTime());
|
||||
Analytics.getInstance().track(event, jsonObject);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getCurrentTime() {
|
||||
return format.format(new Date());
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.analytics;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.elegant.log.simplelog.Logger;
|
||||
import com.elegant.utils.CheckUtils;
|
||||
import com.mogo.cloud.socket.SocketBuildConfig;
|
||||
import com.mogo.cloud.socket.third.core.SocketConfig;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class EventRequest {
|
||||
|
||||
//socket授权状态
|
||||
private static final String SOCKET_STATUS = "socket_status";
|
||||
//异常情况
|
||||
private static final String EXCEPTION = "exception";
|
||||
private static final String TAG = "EventRequest";
|
||||
|
||||
/**
|
||||
* socket状态相关
|
||||
*
|
||||
* @param status: socket 状态
|
||||
*/
|
||||
public static void trackSocketStatus(String status, String desc) {
|
||||
if(!SocketConfig.instance().isAnalyticsOpen()){
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.d(TAG,"analytics is closed");
|
||||
}
|
||||
return;
|
||||
}
|
||||
EventManager.trackEvent(SOCKET_STATUS, buildAuthStatus(status, desc));
|
||||
}
|
||||
|
||||
/**
|
||||
* 埋点异常情况
|
||||
*
|
||||
* @param reason: 异常场景
|
||||
*/
|
||||
public static void trackException(String reason) {
|
||||
if(!SocketConfig.instance().isAnalyticsOpen()){
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.d(TAG,"analytics is closed");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (TextUtils.isEmpty(reason)) {
|
||||
return;
|
||||
}
|
||||
EventManager.trackEvent(EXCEPTION, buildException(reason));
|
||||
}
|
||||
|
||||
private static JSONObject buildAuthStatus(String status, String desc) {
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("socket_status", status);
|
||||
jsonObject.put("desc", desc);
|
||||
if(SocketConfig.instance().getAppContext() != null){
|
||||
jsonObject.put("net", CheckUtils.isNetworkConnected(SocketConfig.instance().getAppContext()));
|
||||
}
|
||||
return jsonObject;
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static JSONObject buildException(String reason) {
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("exception", reason);
|
||||
return jsonObject;
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.analytics;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface SocketStatus {
|
||||
|
||||
//socket 断开连接
|
||||
String socket_disconnect = "socket_disconnect";
|
||||
|
||||
//鉴权失败
|
||||
String auth_rsp_failed = "auth_rsp_failed";
|
||||
|
||||
//发送用户信息反馈失败
|
||||
String send_userInfo_rsp_failed = "send_userInfo_rsp_failed";
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core;
|
||||
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public interface Callback {
|
||||
|
||||
/**
|
||||
* Callback's method invoked when message is received by client
|
||||
*
|
||||
* @param manager callback manager.
|
||||
* @param message message.
|
||||
*/
|
||||
void update(@NonNull CallbackManager manager, @NonNull byte[] message, String appId, long msgId);
|
||||
|
||||
void onAck(@NonNull CallbackManager manager, @NonNull byte[] header, byte[] content);
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.collection.ArraySet;
|
||||
|
||||
|
||||
import com.elegant.log.simplelog.Logger;
|
||||
import com.mogo.cloud.socket.SocketBuildConfig;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public final class CallbackManager {
|
||||
private final Set<Callback> observers = new ArraySet<>();
|
||||
|
||||
private CallbackManager() {
|
||||
}
|
||||
|
||||
public static CallbackManager getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private static final class SingletonHolder {
|
||||
private final static CallbackManager INSTANCE = new CallbackManager();
|
||||
}
|
||||
|
||||
public synchronized void register(Callback callback) {
|
||||
if (callback == null) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "Can not register a callback that is null.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
observers.add(callback);
|
||||
}
|
||||
|
||||
public synchronized void unregister(Callback callback) {
|
||||
observers.remove(callback);
|
||||
}
|
||||
|
||||
public synchronized void unregisterAll() {
|
||||
observers.clear();
|
||||
}
|
||||
|
||||
public synchronized void notify(@NonNull byte[] content, String appId, long msgId) {
|
||||
for (Callback callback : observers) {
|
||||
callback.update(this, content, appId, msgId);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void ack(@NonNull byte[] header, byte[] content) {
|
||||
for (Callback callback : observers) {
|
||||
callback.onAck(this, header, content);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core;
|
||||
|
||||
|
||||
import androidx.collection.ArraySet;
|
||||
|
||||
|
||||
import com.elegant.log.simplelog.Logger;
|
||||
import com.mogo.cloud.socket.SocketBuildConfig;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class ConnCallbackManager {
|
||||
private ConnCallbackManager() {
|
||||
}
|
||||
|
||||
public static ConnCallbackManager getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private static final class SingletonHolder {
|
||||
private final static ConnCallbackManager INSTANCE = new ConnCallbackManager();
|
||||
}
|
||||
|
||||
private final Set<ConnectionLifecycleListener> observers = new ArraySet<>();
|
||||
|
||||
public synchronized void register(ConnectionLifecycleListener callback) {
|
||||
if (callback == null) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "Can not register a callback that is null.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
observers.add(callback);
|
||||
}
|
||||
|
||||
public synchronized void unregister(ConnectionLifecycleListener callback) {
|
||||
observers.remove(callback);
|
||||
}
|
||||
|
||||
public synchronized void unregisterAll() {
|
||||
observers.clear();
|
||||
}
|
||||
|
||||
public void onConnectFailure() {
|
||||
for (ConnectionLifecycleListener callback : observers) {
|
||||
callback.onConnectFailure();
|
||||
}
|
||||
}
|
||||
|
||||
public void onConnectSuccess() {
|
||||
for (ConnectionLifecycleListener callback : observers) {
|
||||
callback.onConnectSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
public void onConnectLost(boolean reconnect) {
|
||||
for (ConnectionLifecycleListener callback : observers) {
|
||||
callback.onConnectLost(reconnect);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core;
|
||||
|
||||
public abstract class ConnectionLifecycleListener {
|
||||
|
||||
public void onConnectFailure() {
|
||||
}
|
||||
|
||||
public void onConnectSuccess() {
|
||||
}
|
||||
|
||||
public void onConnectLost(boolean reconnect) {
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core;
|
||||
|
||||
public enum Environment {
|
||||
release(3),
|
||||
qa(2),
|
||||
dev(1),
|
||||
;
|
||||
|
||||
private int env;
|
||||
|
||||
Environment(int env) {
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
public int getEnv(){
|
||||
return env;
|
||||
}
|
||||
|
||||
public static Environment get(int env){
|
||||
for(Environment environment : values()){
|
||||
if(environment.getEnv() == env){
|
||||
return environment;
|
||||
}
|
||||
}
|
||||
return release;
|
||||
}
|
||||
}
|
||||
@@ -1,236 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core;
|
||||
|
||||
import static com.mogo.cloud.socket.SocketServicesConstants.getTag;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.elegant.log.simplelog.Logger;
|
||||
import com.elegant.network.NetConfig;
|
||||
import com.elegant.utils.UiThreadHandler;
|
||||
import com.mogo.cloud.socket.SocketBuildConfig;
|
||||
import com.mogo.cloud.socket.third.core.client.ClientSocketManager;
|
||||
import com.mogo.cloud.socket.third.core.network.RequestManager;
|
||||
import com.mogo.cloud.socket.third.core.network.model.SocketAddressData;
|
||||
import com.mogo.cloud.socket.third.utils.RequestUtil;
|
||||
import com.zhidao.ptech.connsvr.commom.protocol.MogoCommon;
|
||||
import com.zhidao.ptech.connsvr.payload.protocol.MogoPayload;
|
||||
import com.zhidao.ptech.connsvr.protocol.MogoConnsvr;
|
||||
|
||||
public class SocketClient {
|
||||
|
||||
private Context mAppContext;
|
||||
|
||||
private volatile boolean mHasStarted;
|
||||
|
||||
private SocketClient() {
|
||||
}
|
||||
|
||||
public static SocketClient getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private static final class SingletonHolder {
|
||||
private static final SocketClient INSTANCE = new SocketClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动socket
|
||||
*
|
||||
* @param context app context
|
||||
*/
|
||||
public synchronized void start(Context context) {
|
||||
if (mHasStarted) {
|
||||
Logger.d(getTag(), "socket already started");
|
||||
return;
|
||||
}
|
||||
if (context == null) {
|
||||
throw new NullPointerException("context cannot be null");
|
||||
}
|
||||
Logger.d(getTag(), "start socket");
|
||||
|
||||
//ensure context be set
|
||||
SocketConfig.instance().setAppContext(mAppContext = context.getApplicationContext());
|
||||
initNetConfig();
|
||||
requestSocketAddress();
|
||||
mHasStarted = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止socket
|
||||
*/
|
||||
public synchronized void stop() {
|
||||
if (!mHasStarted) {
|
||||
Logger.d(getTag(), "socket already stopped");
|
||||
return;
|
||||
}
|
||||
ClientSocketManager.getInstance().close();
|
||||
mHasStarted = false;
|
||||
Logger.d(getTag(), "stop");
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册Socket Callback
|
||||
*
|
||||
* @param callback 用于接收socket消息的callback
|
||||
*/
|
||||
public void registerSocketCallback(Callback callback) {
|
||||
CallbackManager.getInstance().register(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注销Socket Callback
|
||||
*
|
||||
* @param callback 用于接收socket消息的callback
|
||||
*/
|
||||
public void unregisterSocketCallback(Callback callback) {
|
||||
CallbackManager.getInstance().unregister(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过socket发送上行数据
|
||||
*
|
||||
* @param appId 此app id可被业务定制,不用于建立长连接
|
||||
* @param productLine 产品线,参考{@link MogoCommon.Product}
|
||||
* @param payload 上行数据,使用{@link MogoConnsvr.Payload}构建数据
|
||||
* @param msgType msg类型,参考{@link MogoPayload.PayloadMsgType}
|
||||
* @param ack 是否需要server回执,如果为true会在{@link Callback#onAck(CallbackManager, byte[], byte[])}中收到
|
||||
* @param msgId msg id,可自定义,比如时间戳
|
||||
*/
|
||||
public void sendData(String appId,
|
||||
int productLine,
|
||||
byte[] payload,
|
||||
int msgType,
|
||||
boolean ack,
|
||||
long msgId) {
|
||||
RequestUtil.sendPayloadData(appId, productLine, payload, msgType, ack, msgId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册socket连接状态监听
|
||||
*
|
||||
* @param callback 用于接收socket连接状态callback
|
||||
*/
|
||||
public void registerSocketConnCallback(ConnectionLifecycleListener callback) {
|
||||
if (callback != null) {
|
||||
ConnCallbackManager.getInstance().register(callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注销socket连接状态监听
|
||||
*
|
||||
* @param callback 用于接收socket连接状态callback
|
||||
*/
|
||||
public void unregisterSocketConnCallback(ConnectionLifecycleListener callback) {
|
||||
if (callback != null) {
|
||||
ConnCallbackManager.getInstance().unregister(callback);
|
||||
}
|
||||
}
|
||||
|
||||
private void initNetConfig() {
|
||||
NetConfig.instance().
|
||||
setLoggable(SocketConfig.instance().isDebug()).
|
||||
setAppContext(mAppContext);
|
||||
}
|
||||
|
||||
private void requestSocketAddress() {
|
||||
RequestManager.requestSocketAddress(mAppContext, new RequestManager.SocketAddressCallback() {
|
||||
@Override
|
||||
public void onGetSocketAddressSuccess(SocketAddressData addressData) {
|
||||
if (addressData.result != null && checkHost(addressData.result.ip) && checkPort(addressData.result.port)) {
|
||||
internalStart(addressData.result.ip, addressData.result.port);
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.d(getTag(), "network--->ip:" + addressData.result.ip + " & port: " + addressData.result.port);
|
||||
}
|
||||
} else {
|
||||
retryGetAddress(1000L); //todo 时间调整为1秒,后续在重连时增加网络状态验证,以及增加链路日志
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGetSocketAddressFailed(int code, String msg) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.d(getTag(), "onFailed-->" + code + ":" + msg);
|
||||
}
|
||||
retryGetAddress(1000L); //todo 时间调整为1秒,后续在重连时增加网络状态验证,以及增加链路日志
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private final Runnable mRequestSocketAddressTask = () -> {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.d(getTag(), "get socket address");
|
||||
}
|
||||
requestSocketAddress();
|
||||
};
|
||||
|
||||
private void internalStart(String host, int port) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.d(getTag(), "internalStart-->host: " + host + " & port: " + port);
|
||||
}
|
||||
ClientSocketManager.getInstance().setConnectionLifecycleListener(connectionLifecycleListener);
|
||||
ClientSocketManager.getInstance().start(host, port);
|
||||
}
|
||||
|
||||
private final ConnectionLifecycleListener connectionLifecycleListener = new ConnectionLifecycleListener() {
|
||||
@Override
|
||||
public void onConnectLost(boolean reconnect) {
|
||||
super.onConnectLost(reconnect);
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.d(getTag(), "---onConnectLost");
|
||||
}
|
||||
ConnCallbackManager.getInstance().onConnectLost(reconnect);
|
||||
if (reconnect) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.d(getTag(), "---onConnectLost reconnect");
|
||||
}
|
||||
retryGetAddress(1000L);//1-7s //todo 时间调整为1秒,后续在重连时增加网络状态验证,以及增加链路日志
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectFailure() {
|
||||
super.onConnectFailure();
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.d(getTag(), "---onConnectFailure");
|
||||
}
|
||||
ConnCallbackManager.getInstance().onConnectFailure();
|
||||
retryGetAddress(1000L);//3-6s //todo 时间调整为1秒,后续在重连时增加网络状态验证,以及增加链路日志
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectSuccess() {
|
||||
super.onConnectSuccess();
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.d(getTag(), "---onConnectSuccess");
|
||||
}
|
||||
ConnCallbackManager.getInstance().onConnectSuccess();
|
||||
}
|
||||
};
|
||||
|
||||
private void retryGetAddress(long delayedInMillis) {
|
||||
UiThreadHandler.removeCallbacks(mRequestSocketAddressTask);
|
||||
UiThreadHandler.postDelayed(mRequestSocketAddressTask, delayedInMillis);
|
||||
}
|
||||
|
||||
private boolean checkPort(int port) {
|
||||
if (port < 0 || port > 0xFFFF) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.e(getTag(), "port out of range:" + port);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean checkHost(String hostname) {
|
||||
if (TextUtils.isEmpty(hostname)) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.e(getTag(), "hostname can't be null");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core;
|
||||
|
||||
import static com.mogo.cloud.socket.third.core.SocketConstants.DEFAULT_AUTH_ORIGIN_PUB_KEY;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
|
||||
import com.zhidao.ptech.connsvr.commom.protocol.MogoCommon;
|
||||
import com.zhidao.utils.common.TelephoneUtil;
|
||||
|
||||
public class SocketConfig {
|
||||
public static final String PROTO_VERSION = "1.0.1";
|
||||
|
||||
private boolean debug = false;
|
||||
|
||||
private Context appContext;
|
||||
|
||||
/**
|
||||
* Need to be registered by server before it can be applied
|
||||
*/
|
||||
private String channelId;
|
||||
|
||||
private Environment environment;
|
||||
|
||||
private MogoCommon.Client client;
|
||||
|
||||
private boolean openAnalytics;
|
||||
|
||||
/**
|
||||
* Customized sn can be set
|
||||
*/
|
||||
private String sn;
|
||||
|
||||
private String uid;
|
||||
|
||||
private String token;
|
||||
|
||||
private String authPubKey;
|
||||
|
||||
private SocketConfig() {
|
||||
}
|
||||
|
||||
public static SocketConfig instance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private final static class SingletonHolder {
|
||||
private static final SocketConfig INSTANCE = new SocketConfig();
|
||||
}
|
||||
|
||||
public SocketConfig setDebug(boolean debug) {
|
||||
this.debug = debug;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isDebug() {
|
||||
return debug;
|
||||
}
|
||||
|
||||
public SocketConfig setAppContext(Context appContext) {
|
||||
this.appContext = appContext.getApplicationContext();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Context getAppContext() {
|
||||
return appContext;
|
||||
}
|
||||
|
||||
public String getChannelId() {
|
||||
return channelId;
|
||||
}
|
||||
|
||||
public SocketConfig setChannelId(String channelId) {
|
||||
this.channelId = channelId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MogoCommon.Client getClient() {
|
||||
return client == null ? MogoCommon.Client.car : client;
|
||||
}
|
||||
|
||||
public SocketConfig setClient(MogoCommon.Client client) {
|
||||
this.client = client;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Environment getEnvironment() {
|
||||
return environment == null ? Environment.release : environment;
|
||||
}
|
||||
|
||||
public SocketConfig setEnvironment(Environment environment) {
|
||||
this.environment = environment;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isAnalyticsOpen() {
|
||||
return openAnalytics;
|
||||
}
|
||||
|
||||
public SocketConfig setOpenAnalytics(boolean openAnalytics) {
|
||||
this.openAnalytics = openAnalytics;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve sn of current device, and return customized sn first
|
||||
*/
|
||||
public String getSn() {
|
||||
return TextUtils.isEmpty(sn) ? TelephoneUtil.getSerialNumber() : sn;
|
||||
}
|
||||
|
||||
/**
|
||||
* The third-party device can set a customized sn
|
||||
*/
|
||||
public SocketConfig setSn(String sn) {
|
||||
this.sn = sn;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public SocketConfig setUid(String uid) {
|
||||
this.uid = uid;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public SocketConfig setToken(String token) {
|
||||
this.token = token;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getAuthPubKey() {
|
||||
if (TextUtils.isEmpty(authPubKey)) {
|
||||
authPubKey = DEFAULT_AUTH_ORIGIN_PUB_KEY;
|
||||
}
|
||||
return authPubKey;
|
||||
}
|
||||
|
||||
public SocketConfig setAuthPubKey(String authPubKey) {
|
||||
this.authPubKey = authPubKey;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core;
|
||||
|
||||
public interface SocketConstants {
|
||||
String TAG = "com.zhidao.socket--->";
|
||||
|
||||
/*unit is second*/
|
||||
int DEFAULT_READER_IDLE_TIME = 0;
|
||||
/*unit is second*/
|
||||
int DEFAULT_WRITER_IDLE_TIME = 0;
|
||||
/*unit is second*/
|
||||
int DEFAULT_READER_WRITER_IDLE_TIME = 60 * 3;
|
||||
|
||||
/*unit is ms*/
|
||||
long ZERO = 0L;
|
||||
/*unit is ms*/
|
||||
long ONE_SECOND = 1000L;
|
||||
/*unit is ms*/
|
||||
long ONE_MINUTE = 60 * ONE_SECOND;
|
||||
|
||||
String DEFAULT_AUTH_ORIGIN_PUB_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLe57ORPgOnBrcWmGac3esB4PtIyI0rAHiyk5QoCRTnTyanwWLfstu7mz2MSHD3YuveNWDiIY8vtRvFNE4M/yA7eb4Mct01VKhKFI/JqwyXgNaSh5YCfmv0vg9687c7IUjTEAg+ReC/bSLDqEB3a0vuP95Txtj9smMlx1e37XFYQIDAQAB";
|
||||
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core.client;
|
||||
|
||||
import io.netty.channel.ChannelHandler;
|
||||
|
||||
/**
|
||||
* Client-side interface to collect all {@link ChannelHandler}. By doing so, we can conveniently
|
||||
* use {@link ChannelHandlerHolder#handlers()} methods to reconnect to server.
|
||||
*/
|
||||
/*package*/ interface ChannelHandlerHolder {
|
||||
|
||||
/**
|
||||
* Collection of {@link ChannelHandler} used for {@link io.netty.bootstrap.Bootstrap#handler(ChannelHandler)}
|
||||
* to connect server.
|
||||
*
|
||||
* @return Collection of {@link ChannelHandler}
|
||||
*/
|
||||
ChannelHandler[] handlers();
|
||||
}
|
||||
@@ -1,244 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core.client;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.elegant.log.simplelog.Logger;
|
||||
import com.mogo.cloud.socket.SocketBuildConfig;
|
||||
import com.mogo.cloud.socket.third.analytics.EventRequest;
|
||||
import com.mogo.cloud.socket.third.analytics.SocketStatus;
|
||||
import com.mogo.cloud.socket.third.core.CallbackManager;
|
||||
import com.mogo.cloud.socket.third.core.ConnectionLifecycleListener;
|
||||
import com.mogo.cloud.socket.third.core.SocketConfig;
|
||||
import com.mogo.cloud.socket.third.core.SocketConstants;
|
||||
import com.mogo.cloud.socket.third.utils.LoginStatusUtil;
|
||||
import com.mogo.cloud.socket.third.utils.RSAUtils;
|
||||
import com.mogo.cloud.socket.third.utils.RequestUtil;
|
||||
import com.zhidao.ptech.connsvr.protocol.MogoConnsvr;
|
||||
import com.zhidao.ptech.connsvr.protocol.model.MogoConnsvrPacket;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.handler.timeout.IdleStateEvent;
|
||||
import io.netty.util.ReferenceCountUtil;
|
||||
|
||||
|
||||
@ChannelHandler.Sharable
|
||||
/*package*/ final class ClientChannelReader extends ChannelInboundHandlerAdapter {
|
||||
|
||||
public ClientChannelReader() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
||||
if (evt instanceof IdleStateEvent) {
|
||||
|
||||
final IdleStateEvent e = (IdleStateEvent) evt;
|
||||
|
||||
switch (e.state()) {
|
||||
case WRITER_IDLE:
|
||||
RequestUtil.sendHeartbeat(ctx.channel());
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "client send heartbeat write-idle");
|
||||
}
|
||||
break;
|
||||
case READER_IDLE:
|
||||
RequestUtil.sendHeartbeat(ctx.channel());
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "client send heartbeat reader-idle");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
super.userEventTriggered(ctx, evt);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext channelHandlerContext, Object msg) throws Exception {
|
||||
if (!(msg instanceof MogoConnsvrPacket)) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "msg is null or msg is not MogoConnsvrPacket type---" + (msg == null ? "" : msg.toString()));
|
||||
}
|
||||
EventRequest.trackException("msg is not instanceof MogoConnsvrPacket");
|
||||
//重新请求ip port
|
||||
onRetryLogin();
|
||||
return;
|
||||
}
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "Client---client receive server---" + msg.toString());
|
||||
}
|
||||
|
||||
final MogoConnsvrPacket mogoConnsvrPacket = (MogoConnsvrPacket) msg;
|
||||
final MogoConnsvr.MsgType msgType = mogoConnsvrPacket.getMsgType(((MogoConnsvrPacket) msg).getHeaderPb());
|
||||
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "receive server---msgType" + msgType.name());
|
||||
}
|
||||
if (msgType == MogoConnsvr.MsgType.mogoMsgTypeConnSvrAuthMidRsp) {
|
||||
//返回256位随机字符串, 加密后再次发给服务端验证
|
||||
LoginStatusUtil.setStatus(false);
|
||||
if (mogoConnsvrPacket.getPayload() == null) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "AuthMidRsp==>Packet.getPayload is null");
|
||||
}
|
||||
EventRequest.trackException("AuthMidRsp==>Packet.getPayload is null");
|
||||
//重新请求ip port
|
||||
onRetryLogin();
|
||||
return;
|
||||
}
|
||||
MogoConnsvr.AuthMidRsp authMidRsp = MogoConnsvr.AuthMidRsp.parseFrom(mogoConnsvrPacket.getPayloadBytes());
|
||||
if (authMidRsp != null && !TextUtils.isEmpty(authMidRsp.getKey())) {
|
||||
String key = RSAUtils.encryptByPublic(authMidRsp.getKey() + SocketConfig.instance().getSn());
|
||||
RequestUtil.checkAuth(key);
|
||||
} else {
|
||||
EventRequest.trackException("authMidRsp is null or getKey is null");
|
||||
//重新请求ip port
|
||||
onRetryLogin();
|
||||
}
|
||||
} else if (msgType == MogoConnsvr.MsgType.mogoMsgTypeConnSvrAuthRsp) {
|
||||
LoginStatusUtil.setStatus(false);
|
||||
if (mogoConnsvrPacket.getPayload() == null) {
|
||||
EventRequest.trackException("AuthRsp==> Packet.getPayload is null");
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "login response ---> response is null");
|
||||
}
|
||||
//重新请求ip port
|
||||
onRetryLogin();
|
||||
return;
|
||||
}
|
||||
MogoConnsvr.AuthRsp authRsp = MogoConnsvr.AuthRsp.parseFrom(mogoConnsvrPacket.getPayloadBytes());
|
||||
if (authRsp != null) {
|
||||
MogoConnsvr.AuthCode authCode = authRsp.getAuthCode();
|
||||
if (authCode == MogoConnsvr.AuthCode.AUTH_SUCCESS) {
|
||||
onAuthSuccess(channelHandlerContext.channel());
|
||||
} else {
|
||||
EventRequest.trackSocketStatus(SocketStatus.auth_rsp_failed, "auth code is not success");
|
||||
onRetryLogin();
|
||||
}
|
||||
} else {
|
||||
EventRequest.trackException("AuthRsp==> authRsp is null");
|
||||
//重新请求ip port
|
||||
onRetryLogin();
|
||||
}
|
||||
} else if (msgType == MogoConnsvr.MsgType.mogoMsgTypeConnSvrAgentInfoRsp) {//用户信息
|
||||
final MogoConnsvr.ConnSvrUserInfoRsp userInfoResponse = MogoConnsvr.ConnSvrUserInfoRsp.parseFrom(mogoConnsvrPacket.getPayloadBytes());
|
||||
if (userInfoResponse.getResult()) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "Client receives server's user info response, result is true.");
|
||||
}
|
||||
LoginStatusUtil.setStatus(true);
|
||||
} else {
|
||||
EventRequest.trackSocketStatus(SocketStatus.send_userInfo_rsp_failed, "send_userInfo_rsp_failed");
|
||||
onRetryLogin();
|
||||
LoginStatusUtil.setStatus(false);
|
||||
}
|
||||
} else if (msgType == MogoConnsvr.MsgType.mogoMsgTypeConnSvrDisconnectRsp) {//链接断开
|
||||
LoginStatusUtil.setStatus(false);
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "mogoMsgTypeConnSvrDisconnectRsp retry login");
|
||||
}
|
||||
EventRequest.trackSocketStatus(SocketStatus.socket_disconnect, "disconnect");
|
||||
//重新请求ip port
|
||||
onRetryLogin();
|
||||
} else if (msgType == MogoConnsvr.MsgType.mogoMsgTypeAppPushKickMessageReq) {
|
||||
LoginStatusUtil.setStatus(false);
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "close channel response ---> 被踢下线");
|
||||
}
|
||||
EventRequest.trackSocketStatus(SocketStatus.socket_disconnect, "kick out, socket is close");
|
||||
ClientSocketManager.getInstance().close();
|
||||
} else if (msgType == MogoConnsvr.MsgType.mogoMsgTypeAppPushMessageReq) {//推送消息
|
||||
if (mogoConnsvrPacket.getPayload() == null) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "push message response is null");
|
||||
}
|
||||
EventRequest.trackException("push payload message response is null");
|
||||
return;
|
||||
}
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "push message response received");
|
||||
}
|
||||
try {
|
||||
MogoConnsvr.Header header = MogoConnsvr.Header.parseFrom(mogoConnsvrPacket.getHeaderBytes());
|
||||
if (header != null) {
|
||||
//收到消息的回执
|
||||
MogoConnsvr.Header rspHeader = MogoConnsvr.Header.newBuilder(((MogoConnsvrPacket) msg).getHeaderPb())
|
||||
.setMsgType(MogoConnsvr.MsgType.mogoMsgTypeAppPushMessageRsp_VALUE)
|
||||
.build();
|
||||
MogoConnsvrPacket packet = new MogoConnsvrPacket(Unpooled.wrappedBuffer(rspHeader.toByteArray()));
|
||||
RequestUtil.ack(channelHandlerContext.channel(), packet.getBytes());
|
||||
|
||||
|
||||
String appId = header.getAppId();
|
||||
long msgId = header.getMsgId();
|
||||
CallbackManager.getInstance().notify(mogoConnsvrPacket.getPayloadBytes(), appId, msgId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (msgType == MogoConnsvr.MsgType.mogoMsgTypeAppUpstreamAck) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "receive message ack");
|
||||
}
|
||||
|
||||
byte[] bytes = mogoConnsvrPacket.getHeaderBytes();
|
||||
try {
|
||||
MogoConnsvr.Header header = MogoConnsvr.Header.parseFrom(bytes);
|
||||
if (header != null) {
|
||||
CallbackManager.getInstance().ack(bytes, mogoConnsvrPacket.getPayloadBytes());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (msgType == MogoConnsvr.MsgType.mogoMsgTypeConnSvrHeartbeatReq) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "Client receives server's heartbeat.");
|
||||
}
|
||||
}
|
||||
|
||||
ReferenceCountUtil.release(msg);
|
||||
}
|
||||
|
||||
private void onAuthSuccess(Channel channel) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "Client authority check succeeded");
|
||||
}
|
||||
//send heartbeat.
|
||||
HeartbeatAlarmManager.getInstance().send();
|
||||
//send user info
|
||||
RequestUtil.sendUserInfo(channel);
|
||||
}
|
||||
|
||||
private synchronized void onRetryLogin() {
|
||||
onConnectFailure();
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "Client login fails, retry ing");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新请求ip port
|
||||
*/
|
||||
private void onConnectFailure() {
|
||||
ConnectionLifecycleListener connectionLifecycleListener = ClientSocketManager.getInstance().getConnectionLifecycleListener();
|
||||
if (connectionLifecycleListener != null) {
|
||||
//关闭原有通道,重新请求通道
|
||||
ClientSocketManager.getInstance().close();
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "Client onConnectFailure, retry in 5s");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
EventRequest.trackException(cause.getMessage());
|
||||
cause.printStackTrace();
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
@@ -1,233 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core.client;
|
||||
|
||||
import com.elegant.log.simplelog.Logger;
|
||||
import com.mogo.cloud.socket.SocketBuildConfig;
|
||||
import com.mogo.cloud.socket.third.core.ConnectionLifecycleListener;
|
||||
import com.mogo.cloud.socket.third.core.SocketConstants;
|
||||
import com.mogo.cloud.socket.third.utils.LoginStatusUtil;
|
||||
import com.mogo.cloud.socket.third.utils.RequestUtil;
|
||||
import com.zhidao.ptech.connsvr.protocol.codec.MogoPacketDecoder;
|
||||
import com.zhidao.ptech.connsvr.protocol.codec.MogoPacketFrameDecoder;
|
||||
import com.zhidao.ptech.connsvr.protocol.codec.MogoPacketFrameEncoder;
|
||||
import com.zhidao.ptech.connsvr.protocol.model.MogoConnsvrPacket;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.AdaptiveRecvByteBufAllocator;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.timeout.IdleStateHandler;
|
||||
import io.netty.util.HashedWheelTimer;
|
||||
|
||||
public class ClientSocketManager {
|
||||
|
||||
private final HashedWheelTimer hashedWheelTimer = new HashedWheelTimer();
|
||||
private final Bootstrap bootstrap = new Bootstrap();
|
||||
private final NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup();
|
||||
|
||||
private volatile boolean canReconnect = true;
|
||||
private volatile boolean isConnected = false;
|
||||
|
||||
private Channel channel;
|
||||
private ConnectionLifecycleListener connectionLifecycleListener;
|
||||
|
||||
public static ClientSocketManager getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private static class SingletonHolder {
|
||||
private static final ClientSocketManager INSTANCE = new ClientSocketManager();
|
||||
}
|
||||
|
||||
private ClientSocketManager() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
private synchronized void initialize() {
|
||||
bootstrap.channel(NioSocketChannel.class);
|
||||
bootstrap.option(ChannelOption.SO_KEEPALIVE, true)
|
||||
.option(ChannelOption.TCP_NODELAY, true)
|
||||
.option(ChannelOption.RCVBUF_ALLOCATOR, AdaptiveRecvByteBufAllocator.DEFAULT);
|
||||
|
||||
bootstrap.group(eventLoopGroup);
|
||||
|
||||
final ConnectionWatchdog watchdog = createWatchdog();
|
||||
|
||||
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel socketChannel) throws Exception {
|
||||
socketChannel.pipeline().addLast(watchdog.handlers());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return isConnected;
|
||||
}
|
||||
|
||||
private synchronized ConnectionWatchdog createWatchdog() {
|
||||
return new ConnectionWatchdog() {
|
||||
@Override
|
||||
public ChannelHandler[] handlers() {
|
||||
return new ChannelHandler[]{
|
||||
this,
|
||||
//decode
|
||||
new MogoPacketFrameDecoder(MogoPacketFrameDecoder.MAX_FRAME_LENGTH,
|
||||
MogoPacketFrameDecoder.LENGTH_FIELD_OFFSET,
|
||||
MogoPacketFrameDecoder.LENGTH_FIELD_SIZE),
|
||||
new MogoPacketDecoder(),
|
||||
//encode
|
||||
new MogoPacketFrameEncoder(),
|
||||
//config idle state
|
||||
new IdleStateHandler(SocketConstants.DEFAULT_READER_IDLE_TIME, SocketConstants.DEFAULT_READER_WRITER_IDLE_TIME, SocketConstants.DEFAULT_READER_WRITER_IDLE_TIME, TimeUnit.SECONDS),
|
||||
//send and receive proto-type data.
|
||||
new ClientChannelReader(),
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private synchronized void writeAndFlush(Object msg) {
|
||||
if (channel == null) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "socket channel is null when write and flush");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(msg instanceof MogoConnsvrPacket)) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "msg is not MogoConnsvrPacket type when write and flush.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
channel.writeAndFlush(msg);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized Channel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public synchronized void start(String host, int port) {
|
||||
if (isConnected) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "do not need to start, channel is connected");
|
||||
}
|
||||
return;
|
||||
}
|
||||
canReconnect = true;
|
||||
isConnected = false;
|
||||
resetInetAddress(host, port);
|
||||
doConnection(SocketConstants.ONE_SECOND);
|
||||
}
|
||||
|
||||
public synchronized void setConnectionLifecycleListener(ConnectionLifecycleListener connectionLifecycleListener) {
|
||||
this.connectionLifecycleListener = connectionLifecycleListener;
|
||||
}
|
||||
|
||||
public synchronized ConnectionLifecycleListener getConnectionLifecycleListener() {
|
||||
return connectionLifecycleListener;
|
||||
}
|
||||
|
||||
private synchronized void resetInetAddress(String host, int port) {
|
||||
bootstrap.remoteAddress(host, port);
|
||||
}
|
||||
|
||||
private synchronized void doConnection(long delayInMs) {
|
||||
if (channel != null && channel.isOpen() && channel.isActive()) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "channel is active, no need to call doConnection(long delayInMs)");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
hashedWheelTimer.newTimeout(timeout -> {
|
||||
if (!canReconnect) {
|
||||
return;
|
||||
}
|
||||
final ChannelFuture future = bootstrap.connect();
|
||||
future.addListener((ChannelFutureListener) future1 -> {
|
||||
if (future1.isSuccess()) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "Client---connecting server succeeds");
|
||||
}
|
||||
onConnectSuccess(future1.channel());
|
||||
} else {
|
||||
Logger.e(SocketConstants.TAG, "Client---connecting server fails,失败重试");
|
||||
Logger.e(SocketConstants.TAG, future1.cause().getMessage());
|
||||
onConnectFailure();
|
||||
}
|
||||
});
|
||||
}, delayInMs, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private synchronized void onConnectSuccess(Channel channel) {
|
||||
this.isConnected = true;
|
||||
this.channel = channel;
|
||||
RequestUtil.login(channel);
|
||||
if (connectionLifecycleListener != null) {
|
||||
connectionLifecycleListener.onConnectSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void onConnectFailure() {
|
||||
this.isConnected = false;
|
||||
close(canReconnect);
|
||||
if (connectionLifecycleListener != null) {
|
||||
connectionLifecycleListener.onConnectFailure();
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void onConnectionLost() {
|
||||
this.isConnected = false;
|
||||
close(canReconnect);
|
||||
if (connectionLifecycleListener != null) {
|
||||
connectionLifecycleListener.onConnectLost(canReconnect);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void closeChannelSafely() {
|
||||
try {
|
||||
if (channel != null) {
|
||||
channel.close();
|
||||
channel = null;
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "channel is null");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void close() {
|
||||
close(false);
|
||||
if (connectionLifecycleListener != null) {
|
||||
connectionLifecycleListener.onConnectFailure();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void close(boolean allowReconnect) {
|
||||
//close channel
|
||||
closeChannelSafely();
|
||||
|
||||
//reset status
|
||||
isConnected = false;
|
||||
canReconnect = allowReconnect;
|
||||
LoginStatusUtil.setStatus(false);
|
||||
HeartbeatAlarmManager.getInstance().cancel();
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core.client;
|
||||
|
||||
import com.elegant.log.simplelog.Logger;
|
||||
import com.mogo.cloud.socket.SocketBuildConfig;
|
||||
import com.mogo.cloud.socket.third.analytics.EventRequest;
|
||||
import com.mogo.cloud.socket.third.analytics.SocketStatus;
|
||||
import com.mogo.cloud.socket.third.core.SocketConstants;
|
||||
|
||||
import io.netty.channel.ChannelHandler.Sharable;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
|
||||
|
||||
@Sharable
|
||||
/*package*/ abstract class ConnectionWatchdog extends ChannelInboundHandlerAdapter implements ChannelHandlerHolder {
|
||||
|
||||
protected ConnectionWatchdog() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "channel is active");
|
||||
}
|
||||
ctx.fireChannelActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "channel is inactive, it depends on client's choice whether to reconnect or not.");
|
||||
}
|
||||
EventRequest.trackSocketStatus(SocketStatus.socket_disconnect, "channel is inactive");
|
||||
ClientSocketManager.getInstance().onConnectionLost();
|
||||
ctx.fireChannelInactive();
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core.client;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.ConnectivityManager;
|
||||
|
||||
import com.elegant.log.simplelog.Logger;
|
||||
import com.mogo.cloud.passport.utils.DevicesUtils;
|
||||
import com.mogo.cloud.socket.SocketBuildConfig;
|
||||
import com.mogo.cloud.socket.third.analytics.EventRequest;
|
||||
import com.mogo.cloud.socket.third.analytics.SocketStatus;
|
||||
import com.mogo.cloud.socket.third.core.SocketConfig;
|
||||
import com.mogo.cloud.socket.third.core.SocketConstants;
|
||||
import com.mogo.cloud.socket.third.utils.LoginStatusUtil;
|
||||
import com.mogo.cloud.socket.third.utils.RequestUtil;
|
||||
|
||||
/**
|
||||
* Send heartbeats according to network type to keep socket active as well as
|
||||
* to stop a device falling asleep when the screen is off.
|
||||
*/
|
||||
/*package*/ class HeartbeatAlarmManager {
|
||||
|
||||
private AlarmManager alarmManager;
|
||||
private PendingIntent pendingIntent;
|
||||
private static int lastNetworkType;
|
||||
|
||||
private HeartbeatAlarmManager() {
|
||||
}
|
||||
|
||||
public static HeartbeatAlarmManager getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private static final class SingletonHolder {
|
||||
private static final HeartbeatAlarmManager INSTANCE = new HeartbeatAlarmManager();
|
||||
}
|
||||
|
||||
synchronized void cancel() {
|
||||
if (alarmManager != null && pendingIntent != null) {
|
||||
pendingIntent.cancel();
|
||||
alarmManager.cancel(pendingIntent);
|
||||
alarmManager = null;
|
||||
pendingIntent = null;
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "heartbeat alarm is cancelled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void send() {
|
||||
this.cancel();
|
||||
if ((lastNetworkType = DevicesUtils.getNetworkType(SocketConfig.instance().getAppContext())) == ConnectivityManager.TYPE_MOBILE) {
|
||||
sendHeartbeatRepeatedly(SocketConstants.ONE_MINUTE * 2);
|
||||
} else {
|
||||
sendHeartbeatRepeatedly(SocketConstants.ONE_MINUTE * 2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Suggest that interval be 60 seconds or bigger to save power,
|
||||
* and note that the interval will be set to 60 seconds when the interval is
|
||||
* small than 60 seconds in or above 5.1{@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}.
|
||||
*/
|
||||
private void sendHeartbeatRepeatedly(long interval) {
|
||||
final Context appContext = SocketConfig.instance().getAppContext();
|
||||
if (appContext == null) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "sendHeartbeatRepeatedly---> app context is null.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
final int requestCode = 1001;
|
||||
final Intent intent = new Intent(appContext, SendHeartbeatReceiver.class);
|
||||
alarmManager = (AlarmManager) appContext.getSystemService(Context.ALARM_SERVICE);
|
||||
pendingIntent = PendingIntent.getBroadcast(
|
||||
appContext,
|
||||
requestCode,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
if (DevicesUtils.isSdkHigherThan18()) {
|
||||
alarmManager.setExact(
|
||||
AlarmManager.RTC_WAKEUP,
|
||||
System.currentTimeMillis() + interval,
|
||||
pendingIntent);
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "setExact(...)");
|
||||
}
|
||||
} else {
|
||||
alarmManager.setRepeating(
|
||||
AlarmManager.RTC_WAKEUP,
|
||||
System.currentTimeMillis() + interval,
|
||||
interval,
|
||||
pendingIntent);
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "setRepeating(...)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class SendHeartbeatReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (!ClientSocketManager.getInstance().isConnected()) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "onReceive--->channel is not connected");
|
||||
}
|
||||
EventRequest.trackSocketStatus(SocketStatus.socket_disconnect, "heartbeat netty socket disconnect");
|
||||
onRetryConnect();
|
||||
return;
|
||||
}
|
||||
|
||||
boolean result = LoginStatusUtil.isLogin();
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "socket connected is : " + result);
|
||||
}
|
||||
//重试逻辑
|
||||
if (!LoginStatusUtil.isLogin()) {
|
||||
EventRequest.trackSocketStatus(SocketStatus.socket_disconnect, "heartbeat product socket disconnect");
|
||||
onRetryConnect();
|
||||
return;
|
||||
}
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "onReceive--->send heartbeat");
|
||||
}
|
||||
RequestUtil.sendHeartbeat(ClientSocketManager.getInstance().getChannel());
|
||||
|
||||
if (DevicesUtils.isSdkHigherThan18() || lastNetworkType != DevicesUtils.getNetworkType(SocketConfig.instance().getAppContext())) {
|
||||
HeartbeatAlarmManager.getInstance().cancel();
|
||||
HeartbeatAlarmManager.getInstance().send();
|
||||
}
|
||||
}
|
||||
|
||||
//尝试重新连接
|
||||
private void onRetryConnect() {
|
||||
//关闭原有通道,重新请求信通道
|
||||
ClientSocketManager.getInstance().close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core.network;
|
||||
|
||||
import com.elegant.network.BaseResp;
|
||||
|
||||
import okhttp3.RequestBody;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.Headers;
|
||||
import retrofit2.http.POST;
|
||||
import rx.Observable;
|
||||
|
||||
public interface ApiService {
|
||||
|
||||
@Headers({"Content-Type:application/json", "Accept:application/json"})
|
||||
@POST("/connect/message/messageCallback")
|
||||
Observable<BaseResp> socketMessageCallback(@Body RequestBody requestBody);
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core.network;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.elegant.log.simplelog.Logger;
|
||||
import com.elegant.network.BaseResp;
|
||||
import com.elegant.network.DefSubscriberImpl;
|
||||
import com.elegant.network.NetConstants;
|
||||
import com.elegant.network.ParamsBuilder;
|
||||
import com.elegant.network.RequestOptions;
|
||||
import com.elegant.network.utils.GsonUtil;
|
||||
import com.elegant.network.utils.NetworkSdkUtils;
|
||||
import com.elegant.utils.CommonUtils;
|
||||
import com.mogo.cloud.httpdns.bean.HttpDnsSimpleLocation;
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
|
||||
import com.mogo.cloud.socket.SocketBuildConfig;
|
||||
import com.mogo.cloud.socket.third.core.SocketConfig;
|
||||
import com.mogo.cloud.socket.third.core.network.model.MessageCallbackData;
|
||||
import com.mogo.cloud.socket.third.core.network.model.SocketAddressData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import okhttp3.RequestBody;
|
||||
import rx.Observable;
|
||||
|
||||
public class RequestManager {
|
||||
|
||||
private static final String TAG = "RequestManager";
|
||||
|
||||
public static void socketMessageCallback(long msgId, String appId) {
|
||||
final List<Long> msgIds = new ArrayList<>();
|
||||
msgIds.add(msgId);
|
||||
MessageCallbackData callbackData = new MessageCallbackData(appId);
|
||||
callbackData.setNotifyMsgIds(msgIds);
|
||||
|
||||
RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),
|
||||
GsonUtil.jsonFromObject(callbackData));
|
||||
|
||||
RequestOptions requestOptions = RequestOptions.of(SocketConfig.instance().getAppContext());
|
||||
|
||||
ServiceFactory.newApiService().socketMessageCallback(body).
|
||||
compose(NetworkSdkUtils.transformer()).
|
||||
subscribe(new DefSubscriberImpl<BaseResp>(requestOptions) {
|
||||
@Override
|
||||
protected void onFailure(int code, String message) {
|
||||
super.onFailure(code, message);
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.d(TAG, "socket message callback failed");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSuccess(BaseResp o) {
|
||||
super.onSuccess(o);
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.d(TAG, "socket message callback succeeded");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNetworkLost() {
|
||||
super.onNetworkLost();
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.d(TAG, "request socket message callback, network is not available.");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static volatile boolean sRequestingAddress = false;
|
||||
|
||||
public static void requestSocketAddress(Context context, final SocketAddressCallback socketAddressCallback) {
|
||||
if (sRequestingAddress) {
|
||||
return;
|
||||
}
|
||||
|
||||
sRequestingAddress = true;
|
||||
|
||||
double lat = 0;
|
||||
double lon = 0;
|
||||
HttpDnsSimpleLocation httpDnsSimpleLocation = MoGoAiCloudClientConfig.getInstance().getIHttpDnsCurrentLocation().getCurrentLocation();
|
||||
if (httpDnsSimpleLocation != null) {
|
||||
lat = httpDnsSimpleLocation.getLat();
|
||||
lon = httpDnsSimpleLocation.getLon();
|
||||
}
|
||||
final Map<String, Object> params = ParamsBuilder.of(false)
|
||||
|
||||
.append("lat", lat)//required by server
|
||||
.append("lon", lon)//required by server
|
||||
.append("sn", SocketConfig.instance().getSn())
|
||||
.append("versionCode", CommonUtils.getVersionCode(SocketConfig.instance().getAppContext()))
|
||||
.append("versionName", CommonUtils.getVersionName(SocketConfig.instance().getAppContext()))
|
||||
.build();
|
||||
|
||||
Observable<SocketAddressData> observable;
|
||||
if (MoGoAiCloudClientConfig.getInstance().isUseOriginSocket()) {
|
||||
observable = ServiceFactory.newTechOriginApiService().requestSocketAddress(params);
|
||||
} else {
|
||||
observable = ServiceFactory.newTechApiService().requestSocketAddress(params);
|
||||
}
|
||||
observable.compose(NetworkSdkUtils.transformer())
|
||||
.subscribe(new DefSubscriberImpl<SocketAddressData>(RequestOptions.of(context)) {
|
||||
@Override
|
||||
protected void onSuccess(SocketAddressData o) {
|
||||
super.onSuccess(o);
|
||||
sRequestingAddress = false;
|
||||
if (socketAddressCallback != null) {
|
||||
socketAddressCallback.onGetSocketAddressSuccess(o);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailure(int code, String message) {
|
||||
super.onFailure(code, message);
|
||||
sRequestingAddress = false;
|
||||
if (socketAddressCallback != null) {
|
||||
socketAddressCallback.onGetSocketAddressFailed(code, message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNetworkLost() {
|
||||
super.onNetworkLost();
|
||||
sRequestingAddress = false;
|
||||
if (socketAddressCallback != null) {
|
||||
socketAddressCallback.onGetSocketAddressFailed(NetConstants.CODE_REQUEST_NO_NETWORK, "网络失败,请检查网络后重试");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public interface SocketAddressCallback {
|
||||
void onGetSocketAddressSuccess(SocketAddressData data);
|
||||
|
||||
void onGetSocketAddressFailed(int code, String msg);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core.network;
|
||||
|
||||
import com.elegant.network.SimpleServiceFactory;
|
||||
import com.mogo.cloud.socket.third.core.Environment;
|
||||
import com.mogo.cloud.socket.third.core.SocketConfig;
|
||||
|
||||
public class ServiceFactory extends SimpleServiceFactory {
|
||||
|
||||
private static final String TAG = "ServiceFactory";
|
||||
|
||||
protected ServiceFactory(){}
|
||||
|
||||
public static synchronized ApiService newApiService() {
|
||||
return newService(getUrl(), ApiService.class);
|
||||
}
|
||||
|
||||
public static synchronized TechApiService newTechApiService() {
|
||||
return newService(getTechUrl(), TechApiService.class);
|
||||
}
|
||||
|
||||
public static synchronized TechOriginApiService newTechOriginApiService() {
|
||||
return newService(getTechOriginUrl(), TechOriginApiService.class);
|
||||
}
|
||||
|
||||
private static String getTechUrl(){
|
||||
final Environment environment = SocketConfig.instance().getEnvironment();
|
||||
|
||||
if(environment == Environment.release){
|
||||
return "http://dzt.zhidaozhixing.com";
|
||||
}else if(environment == Environment.qa){
|
||||
return "http://dzt-test.zhidaozhixing.com";
|
||||
}else{
|
||||
return "http://dzt-dev.zhidaozhixing.com";
|
||||
}
|
||||
}
|
||||
|
||||
private static String getTechOriginUrl(){
|
||||
final Environment environment = SocketConfig.instance().getEnvironment();
|
||||
|
||||
if(environment == Environment.release){
|
||||
return "http://tech.zhidaohulian.com/";
|
||||
}else if(environment == Environment.qa){
|
||||
return "http://tech-qa.zhidaohulian.com/";
|
||||
}else{
|
||||
return "http://tech-dev.zhidaohulian.com/";
|
||||
}
|
||||
}
|
||||
|
||||
private static String getUrl(){
|
||||
final Environment environment = SocketConfig.instance().getEnvironment();
|
||||
|
||||
if(environment == Environment.release){
|
||||
return "http://api.zhidaohulian.com/";
|
||||
}else if(environment == Environment.qa){
|
||||
return "http://carlife-test.zhidaohulian.com/";
|
||||
}else{
|
||||
return "http://carlife-dev.zhidaohulian.com/";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core.network;
|
||||
|
||||
|
||||
import com.mogo.cloud.socket.third.core.network.model.SocketAddressData;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.QueryMap;
|
||||
import rx.Observable;
|
||||
|
||||
public interface TechApiService {
|
||||
@GET("/yycp-conn-admin/connsvrAddr")
|
||||
Observable<SocketAddressData> requestSocketAddress(@QueryMap Map<String, Object> params);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core.network;
|
||||
|
||||
|
||||
import com.mogo.cloud.socket.third.core.network.model.SocketAddressData;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.QueryMap;
|
||||
import rx.Observable;
|
||||
|
||||
public interface TechOriginApiService {
|
||||
@GET("/alloc/connsvrAddr")
|
||||
Observable<SocketAddressData> requestSocketAddress(@QueryMap Map<String, Object> params);
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core.network.model;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class MessageCallbackData {
|
||||
|
||||
private List<Long> notifyMsgIds;
|
||||
private String reqId;
|
||||
private String caller;
|
||||
private long noise;
|
||||
|
||||
public MessageCallbackData(String appId) {
|
||||
this.reqId = getRandomStr();
|
||||
this.caller = "socketService";
|
||||
this.noise = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void setNotifyMsgIds(List<Long> notifyMsgIds) {
|
||||
this.notifyMsgIds = notifyMsgIds;
|
||||
}
|
||||
|
||||
|
||||
private static String getRandomStr() {
|
||||
char[] c = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
|
||||
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
|
||||
int[] indexArray = new int[32];
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < 32; i++) {
|
||||
indexArray[i] = random.nextInt(36);
|
||||
}
|
||||
StringBuffer stringbuffer = new StringBuffer();
|
||||
for (int i = 0; i < indexArray.length; i++) {
|
||||
stringbuffer.append(c[indexArray[i]]);
|
||||
}
|
||||
return stringbuffer.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core.network.model;
|
||||
|
||||
import com.elegant.network.BaseResp;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class SocketAddressData extends BaseResp {
|
||||
public Address result;
|
||||
|
||||
public static class Address implements Serializable {
|
||||
public String address;
|
||||
public String ip;
|
||||
public int port;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.core.network.model;
|
||||
|
||||
import com.elegant.network.utils.GsonUtil;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class SocketSendData {
|
||||
public int product_line;
|
||||
public byte[] payload;
|
||||
public int header_type;
|
||||
public String app_id;
|
||||
public boolean ack;
|
||||
public long msg_id;
|
||||
|
||||
public static SocketSendData parse(Map map) {
|
||||
JSONObject jsonObject = new JSONObject(map);
|
||||
return GsonUtil.objectFromJson(jsonObject.toString(), SocketSendData.class);
|
||||
}
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.utils;
|
||||
|
||||
|
||||
public final class Base64Utils {
|
||||
|
||||
static private final int BASELENGTH = 128;
|
||||
static private final int LOOKUPLENGTH = 64;
|
||||
static private final int TWENTYFOURBITGROUP = 24;
|
||||
static private final int EIGHTBIT = 8;
|
||||
static private final int SIXTEENBIT = 16;
|
||||
static private final int FOURBYTE = 4;
|
||||
static private final int SIGN = -128;
|
||||
static private final char PAD = '=';
|
||||
static private final boolean fDebug = false;
|
||||
static final private byte[] base64Alphabet = new byte[BASELENGTH];
|
||||
static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];
|
||||
|
||||
static {
|
||||
for (int i = 0; i < BASELENGTH; ++i) {
|
||||
base64Alphabet[i] = -1;
|
||||
}
|
||||
for (int i = 'Z'; i >= 'A'; i--) {
|
||||
base64Alphabet[i] = (byte) (i - 'A');
|
||||
}
|
||||
for (int i = 'z'; i >= 'a'; i--) {
|
||||
base64Alphabet[i] = (byte) (i - 'a' + 26);
|
||||
}
|
||||
|
||||
for (int i = '9'; i >= '0'; i--) {
|
||||
base64Alphabet[i] = (byte) (i - '0' + 52);
|
||||
}
|
||||
|
||||
base64Alphabet['+'] = 62;
|
||||
base64Alphabet['/'] = 63;
|
||||
|
||||
for (int i = 0; i <= 25; i++) {
|
||||
lookUpBase64Alphabet[i] = (char) ('A' + i);
|
||||
}
|
||||
|
||||
for (int i = 26, j = 0; i <= 51; i++, j++) {
|
||||
lookUpBase64Alphabet[i] = (char) ('a' + j);
|
||||
}
|
||||
|
||||
for (int i = 52, j = 0; i <= 61; i++, j++) {
|
||||
lookUpBase64Alphabet[i] = (char) ('0' + j);
|
||||
}
|
||||
lookUpBase64Alphabet[62] = (char) '+';
|
||||
lookUpBase64Alphabet[63] = (char) '/';
|
||||
|
||||
}
|
||||
|
||||
private static boolean isWhiteSpace(char octect) {
|
||||
return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
|
||||
}
|
||||
|
||||
private static boolean isPad(char octect) {
|
||||
return (octect == PAD);
|
||||
}
|
||||
|
||||
private static boolean isData(char octect) {
|
||||
return (octect < BASELENGTH && base64Alphabet[octect] != -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes hex octects into Base64
|
||||
*
|
||||
* @param binaryData Array containing binaryData
|
||||
* @return Encoded Base64 array
|
||||
*/
|
||||
public static String encode(byte[] binaryData) {
|
||||
|
||||
if (binaryData == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int lengthDataBits = binaryData.length * EIGHTBIT;
|
||||
if (lengthDataBits == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
|
||||
int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
|
||||
int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
|
||||
char encodedData[] = null;
|
||||
|
||||
encodedData = new char[numberQuartet * 4];
|
||||
|
||||
byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
|
||||
|
||||
int encodedIndex = 0;
|
||||
int dataIndex = 0;
|
||||
if (fDebug) {
|
||||
System.out.println("number of triplets = " + numberTriplets);
|
||||
}
|
||||
|
||||
for (int i = 0; i < numberTriplets; i++) {
|
||||
b1 = binaryData[dataIndex++];
|
||||
b2 = binaryData[dataIndex++];
|
||||
b3 = binaryData[dataIndex++];
|
||||
|
||||
if (fDebug) {
|
||||
System.out.println("b1= " + b1 + ", b2= " + b2 + ", b3= " + b3);
|
||||
}
|
||||
|
||||
l = (byte) (b2 & 0x0f);
|
||||
k = (byte) (b1 & 0x03);
|
||||
|
||||
byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
|
||||
byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
|
||||
byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
|
||||
|
||||
if (fDebug) {
|
||||
System.out.println("val2 = " + val2);
|
||||
System.out.println("k4 = " + (k << 4));
|
||||
System.out.println("vak = " + (val2 | (k << 4)));
|
||||
}
|
||||
|
||||
encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
|
||||
encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
|
||||
encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
|
||||
encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
|
||||
}
|
||||
|
||||
// form integral number of 6-bit groups
|
||||
if (fewerThan24bits == EIGHTBIT) {
|
||||
b1 = binaryData[dataIndex];
|
||||
k = (byte) (b1 & 0x03);
|
||||
if (fDebug) {
|
||||
System.out.println("b1=" + b1);
|
||||
System.out.println("b1<<2 = " + (b1 >> 2));
|
||||
}
|
||||
byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
|
||||
encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
|
||||
encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
|
||||
encodedData[encodedIndex++] = PAD;
|
||||
encodedData[encodedIndex++] = PAD;
|
||||
} else if (fewerThan24bits == SIXTEENBIT) {
|
||||
b1 = binaryData[dataIndex];
|
||||
b2 = binaryData[dataIndex + 1];
|
||||
l = (byte) (b2 & 0x0f);
|
||||
k = (byte) (b1 & 0x03);
|
||||
|
||||
byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
|
||||
byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
|
||||
|
||||
encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
|
||||
encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
|
||||
encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
|
||||
encodedData[encodedIndex++] = PAD;
|
||||
}
|
||||
|
||||
return new String(encodedData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes Base64 data into octects
|
||||
*
|
||||
* @param encoded string containing Base64 data
|
||||
* @return Array containind decoded data.
|
||||
*/
|
||||
public static byte[] decode(String encoded) {
|
||||
|
||||
if (encoded == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
char[] base64Data = encoded.toCharArray();
|
||||
// remove white spaces
|
||||
int len = removeWhiteSpace(base64Data);
|
||||
|
||||
if (len % FOURBYTE != 0) {
|
||||
return null;//should be divisible by four
|
||||
}
|
||||
|
||||
int numberQuadruple = (len / FOURBYTE);
|
||||
|
||||
if (numberQuadruple == 0) {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
byte decodedData[] = null;
|
||||
byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
|
||||
char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
|
||||
|
||||
int i = 0;
|
||||
int encodedIndex = 0;
|
||||
int dataIndex = 0;
|
||||
decodedData = new byte[(numberQuadruple) * 3];
|
||||
|
||||
for (; i < numberQuadruple - 1; i++) {
|
||||
|
||||
if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
|
||||
|| !isData((d3 = base64Data[dataIndex++]))
|
||||
|| !isData((d4 = base64Data[dataIndex++]))) {
|
||||
return null;
|
||||
}//if found "no data" just return null
|
||||
|
||||
b1 = base64Alphabet[d1];
|
||||
b2 = base64Alphabet[d2];
|
||||
b3 = base64Alphabet[d3];
|
||||
b4 = base64Alphabet[d4];
|
||||
|
||||
decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
|
||||
decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
|
||||
decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
|
||||
}
|
||||
|
||||
if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) {
|
||||
return null;//if found "no data" just return null
|
||||
}
|
||||
|
||||
b1 = base64Alphabet[d1];
|
||||
b2 = base64Alphabet[d2];
|
||||
|
||||
d3 = base64Data[dataIndex++];
|
||||
d4 = base64Data[dataIndex++];
|
||||
if (!isData((d3)) || !isData((d4))) {//Check if they are PAD characters
|
||||
if (isPad(d3) && isPad(d4)) {
|
||||
if ((b2 & 0xf) != 0)//last 4 bits should be zero
|
||||
{
|
||||
return null;
|
||||
}
|
||||
byte[] tmp = new byte[i * 3 + 1];
|
||||
System.arraycopy(decodedData, 0, tmp, 0, i * 3);
|
||||
tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
|
||||
return tmp;
|
||||
} else if (!isPad(d3) && isPad(d4)) {
|
||||
b3 = base64Alphabet[d3];
|
||||
if ((b3 & 0x3) != 0)//last 2 bits should be zero
|
||||
{
|
||||
return null;
|
||||
}
|
||||
byte[] tmp = new byte[i * 3 + 2];
|
||||
System.arraycopy(decodedData, 0, tmp, 0, i * 3);
|
||||
tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
|
||||
tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
|
||||
return tmp;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else { //No PAD e.g 3cQl
|
||||
b3 = base64Alphabet[d3];
|
||||
b4 = base64Alphabet[d4];
|
||||
decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
|
||||
decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
|
||||
decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
|
||||
|
||||
}
|
||||
|
||||
return decodedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* remove WhiteSpace from MIME containing encoded Base64 data.
|
||||
*
|
||||
* @param data the byte array of base64 data (with WS)
|
||||
* @return the new length
|
||||
*/
|
||||
private static int removeWhiteSpace(char[] data) {
|
||||
if (data == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// count characters that's not whitespace
|
||||
int newSize = 0;
|
||||
int len = data.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (!isWhiteSpace(data[i])) {
|
||||
data[newSize++] = data[i];
|
||||
}
|
||||
}
|
||||
return newSize;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.utils;
|
||||
|
||||
public final class LoginStatusUtil {
|
||||
|
||||
private static volatile boolean loginStatus = false;
|
||||
|
||||
private LoginStatusUtil(){}
|
||||
|
||||
public synchronized static void setStatus(boolean loginStatus){
|
||||
LoginStatusUtil.loginStatus = loginStatus;
|
||||
}
|
||||
|
||||
public static boolean isLogin(){
|
||||
return loginStatus;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.utils;
|
||||
|
||||
import com.mogo.cloud.socket.third.core.SocketConfig;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
public class RSAUtils {
|
||||
|
||||
/**
|
||||
* 使用私钥解密
|
||||
*
|
||||
* @param content 密文
|
||||
* @param private_key 私钥
|
||||
* @param input_charset 编码
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String decrypt(String content, String private_key, String input_charset) throws Exception {
|
||||
PrivateKey prikey = getPrivateKey(private_key);
|
||||
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, prikey);
|
||||
|
||||
InputStream ins = new ByteArrayInputStream(Base64Utils.decode(content));
|
||||
ByteArrayOutputStream writer = new ByteArrayOutputStream();
|
||||
byte[] buf = new byte[128];
|
||||
int bufl;
|
||||
|
||||
while ((bufl = ins.read(buf)) != -1) {
|
||||
byte[] block;
|
||||
|
||||
if (buf.length == bufl) {
|
||||
block = buf;
|
||||
} else {
|
||||
block = new byte[bufl];
|
||||
for (int i = 0; i < bufl; i++) {
|
||||
block[i] = buf[i];
|
||||
}
|
||||
}
|
||||
|
||||
writer.write(cipher.doFinal(block));
|
||||
}
|
||||
|
||||
return new String(writer.toByteArray(), input_charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得私钥
|
||||
*
|
||||
* @param key 私钥
|
||||
* @throws Exception
|
||||
*/
|
||||
public static PrivateKey getPrivateKey(String key) throws Exception {
|
||||
|
||||
byte[] keyBytes;
|
||||
|
||||
keyBytes = Base64Utils.decode(key);
|
||||
|
||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
|
||||
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
|
||||
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
|
||||
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到公钥
|
||||
*
|
||||
* @param bysKey
|
||||
* @return
|
||||
*/
|
||||
private static PublicKey getPublicKeyFromX509(String bysKey) throws NoSuchAlgorithmException, Exception {
|
||||
byte[] decodedKey = Base64Utils.decode(bysKey);
|
||||
X509EncodedKeySpec x509 = new X509EncodedKeySpec(decodedKey);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
return keyFactory.generatePublic(x509);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用公钥加密
|
||||
*
|
||||
* @param content 明文
|
||||
* @return
|
||||
*/
|
||||
public static String encryptByPublic(String content) {
|
||||
try {
|
||||
PublicKey pubicKey = getPublicKeyFromX509(SocketConfig.instance().getAuthPubKey());
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, pubicKey);
|
||||
byte plaintext[] = content.getBytes("UTF-8");
|
||||
int inputLen = plaintext.length;
|
||||
int offLen = 0;//偏移量
|
||||
int i = 0;
|
||||
ByteArrayOutputStream bops = new ByteArrayOutputStream();
|
||||
while (inputLen - offLen > 0) {
|
||||
byte[] cache;
|
||||
if (inputLen - offLen > 117) {
|
||||
cache = cipher.doFinal(plaintext, offLen, 117);
|
||||
} else {
|
||||
cache = cipher.doFinal(plaintext, offLen, inputLen - offLen);
|
||||
}
|
||||
bops.write(cache);
|
||||
i++;
|
||||
offLen = 117 * i;
|
||||
}
|
||||
bops.close();
|
||||
byte[] encryptedData = bops.toByteArray();
|
||||
return Base64Utils.encode(encryptedData);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,225 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.utils;
|
||||
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.elegant.log.simplelog.Logger;
|
||||
import com.mogo.cloud.passport.utils.DevicesUtils;
|
||||
import com.mogo.cloud.socket.SocketBuildConfig;
|
||||
import com.mogo.cloud.socket.third.core.SocketConfig;
|
||||
import com.mogo.cloud.socket.third.core.SocketConstants;
|
||||
import com.mogo.cloud.socket.third.core.client.ClientSocketManager;
|
||||
import com.zhidao.ptech.connsvr.commom.protocol.MogoCommon;
|
||||
import com.zhidao.ptech.connsvr.protocol.MogoConnsvr;
|
||||
import com.zhidao.ptech.connsvr.protocol.model.MogoConnsvrPacket;
|
||||
import com.zhidao.utils.common.TelephoneUtil;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.Channel;
|
||||
|
||||
public final class RequestUtil {
|
||||
|
||||
private RequestUtil() {
|
||||
}
|
||||
|
||||
private static boolean checkNotNull(Channel channel) {
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, channel == null ? "checkNotNull(channel), channel is null." : "checkNotNull(channel), channel is not null.");
|
||||
}
|
||||
boolean isLogin = LoginStatusUtil.isLogin() && ClientSocketManager.getInstance().isConnected();
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "socket connected is :" + isLogin);
|
||||
}
|
||||
return channel != null;
|
||||
}
|
||||
|
||||
public static void login(Channel channel) {
|
||||
if (checkNotNull(channel)) {
|
||||
channel.writeAndFlush(RequestModelUtil.buildAuthRequest());
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "requestAuth");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void ack(Channel channel, byte[] data) {
|
||||
if (checkNotNull(channel)) {
|
||||
channel.writeAndFlush(data);
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "ack");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkAuth(String key) {
|
||||
Channel channel = ClientSocketManager.getInstance().getChannel();
|
||||
if (checkNotNull(channel)) {
|
||||
channel.writeAndFlush(RequestModelUtil.buildEncodeInfo(key));
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "checkAuth");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendHeartbeat(Channel channel) {
|
||||
if (checkNotNull(channel)) {
|
||||
channel.writeAndFlush(RequestModelUtil.buildHeartbeat());
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "send heartbeat");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendUserInfo(Channel channel) {
|
||||
if (checkNotNull(channel)) {
|
||||
channel.writeAndFlush(RequestModelUtil.buildUserInfo());
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "send user info");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 此app id可被业务随意定制
|
||||
*/
|
||||
public static void sendPayloadData(String appId, int productLine, byte[] payload, int headerType, boolean ack, long msgId) {
|
||||
final Channel channel = ClientSocketManager.getInstance().getChannel();
|
||||
if (checkNotNull(channel)) {
|
||||
channel.writeAndFlush(RequestModelUtil.buildPayloadData(productLine, appId, payload, headerType, ack, msgId));
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "send---> appId is: " + appId + "; headerType is: " + headerType + "; msgId is: " + msgId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class RequestModelUtil {
|
||||
|
||||
private RequestModelUtil() {
|
||||
}
|
||||
|
||||
private static MogoConnsvrPacket buildAuthRequest() {
|
||||
final ByteBuf headerBuf = Unpooled.buffer();
|
||||
headerBuf.writeBytes(buildHeader(MogoConnsvr.MsgType.mogoMsgTypeConnSvrAuthReq_VALUE));
|
||||
return new MogoConnsvrPacket(headerBuf);
|
||||
}
|
||||
|
||||
private static MogoConnsvrPacket buildEncodeInfo(String enInfo) {
|
||||
final MogoConnsvr.AuthMidReq authMidReq = MogoConnsvr.AuthMidReq.newBuilder()
|
||||
.setKey(enInfo).build();
|
||||
final ByteBuf byteBuf = Unpooled.buffer();
|
||||
byteBuf.writeBytes(authMidReq.toByteArray());
|
||||
|
||||
final ByteBuf headerBuf = Unpooled.buffer();
|
||||
headerBuf.writeBytes(buildHeader(MogoConnsvr.MsgType.mogoMsgTypeConnSvrAuthMidReq_VALUE));
|
||||
|
||||
return new MogoConnsvrPacket(headerBuf, byteBuf);
|
||||
}
|
||||
|
||||
private static ByteBuf buildHeader(int msgType) {
|
||||
String appId = SocketConfig.instance().getChannelId();
|
||||
if (TextUtils.isEmpty(appId)) {
|
||||
appId = "unknown";
|
||||
}
|
||||
if (SocketBuildConfig.isPrintLog) {
|
||||
Logger.i(SocketConstants.TAG, "socket app id is " + appId + ", msg type is " + msgType);
|
||||
}
|
||||
|
||||
return buildHeader(appId, 0, msgType, false, 0);
|
||||
}
|
||||
|
||||
private static ByteBuf buildHeader(String appId, int productLine, int msgType, boolean ack, long msgId) {
|
||||
final String token = SocketConfig.instance().getToken();
|
||||
final String userId = SocketConfig.instance().getUid();
|
||||
final String sn = SocketConfig.instance().getSn();
|
||||
final String versionName = DevicesUtils.getVersionName(SocketConfig.instance().getAppContext());
|
||||
final String fotaVersion = TelephoneUtil.getFotaVersion();
|
||||
|
||||
long uid = 0;
|
||||
try {
|
||||
if (!TextUtils.isEmpty(userId)) {
|
||||
uid = Long.parseLong(userId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
MogoCommon.Client client = SocketConfig.instance().getClient();
|
||||
if (client == null) {
|
||||
client = MogoCommon.Client.car;
|
||||
}
|
||||
|
||||
final MogoConnsvr.UserInfo userInfo = MogoConnsvr.UserInfo.newBuilder()
|
||||
.setUid(uid)
|
||||
.setToken(TextUtils.isEmpty(token) ? "" : token)
|
||||
.setClient(client.getNumber())
|
||||
.setFotaVersion(TextUtils.isEmpty(fotaVersion) ? "" : fotaVersion)
|
||||
.setAppVersion(TextUtils.isEmpty(versionName) ? "" : versionName)
|
||||
.setAppVersionCode(DevicesUtils.getVersionCode(SocketConfig.instance().getAppContext()))
|
||||
.setSn(TextUtils.isEmpty(sn) ? "" : sn).build();
|
||||
|
||||
final MogoConnsvr.Header header = MogoConnsvr.Header.newBuilder()
|
||||
.setTimestamp(System.currentTimeMillis())
|
||||
.setMsgType(msgType)
|
||||
.setAck(ack)
|
||||
.setMsgId(msgId)
|
||||
.setAppId(appId)
|
||||
.setUserInfo(userInfo)
|
||||
.setVersion(0)
|
||||
.setProductLine(productLine).build();
|
||||
|
||||
return Unpooled.buffer().writeBytes(header.toByteArray());
|
||||
}
|
||||
|
||||
private static MogoConnsvrPacket buildHeartbeat() {
|
||||
return new MogoConnsvrPacket(buildHeader(MogoConnsvr.MsgType.mogoMsgTypeConnSvrHeartbeatReq_VALUE));
|
||||
}
|
||||
|
||||
private static MogoConnsvrPacket buildUserInfo() {
|
||||
final String versionName = DevicesUtils.getVersionName(SocketConfig.instance().getAppContext());
|
||||
final String networkTypeName = DevicesUtils.getNetworkTypeName(SocketConfig.instance().getAppContext());
|
||||
final String sn = SocketConfig.instance().getSn();
|
||||
|
||||
long uid = 0;
|
||||
try {
|
||||
String userId = SocketConfig.instance().getUid();
|
||||
if (!TextUtils.isEmpty(userId)) {
|
||||
uid = Long.parseLong(userId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
MogoCommon.Client client = SocketConfig.instance().getClient();
|
||||
if (client == null) {
|
||||
client = MogoCommon.Client.car;
|
||||
}
|
||||
|
||||
final MogoConnsvr.ConnSvrUserInfoReq userInfoReq = MogoConnsvr.ConnSvrUserInfoReq.newBuilder()
|
||||
.setUserId(uid)
|
||||
.setDeviceType(MogoCommon.OS.ANDROID)
|
||||
.setNettype(TextUtils.isEmpty(networkTypeName) ? "" : networkTypeName)
|
||||
.setModel(Build.MODEL)
|
||||
.setManufacturer(Build.MANUFACTURER)
|
||||
.setBrand(Build.BRAND)
|
||||
.setAppVersion(TextUtils.isEmpty(versionName) ? "" : versionName)
|
||||
.setVersion(SocketConfig.PROTO_VERSION)
|
||||
.setClient(client)
|
||||
.setSn(TextUtils.isEmpty(sn) ? "" : sn).build();
|
||||
|
||||
final ByteBuf payloadBuf = Unpooled.buffer().writeBytes(userInfoReq.toByteArray());
|
||||
|
||||
return new MogoConnsvrPacket(buildHeader(MogoConnsvr.MsgType.mogoMsgTypeConnSvrAgentInfoReq_VALUE), payloadBuf);
|
||||
}
|
||||
|
||||
private static MogoConnsvrPacket buildPayloadData(int productLine,
|
||||
String appId,
|
||||
byte[] payload,
|
||||
int headerType,
|
||||
boolean ack,
|
||||
long msgId) {
|
||||
final ByteBuf buf = Unpooled.buffer().writeBytes(payload);
|
||||
return new MogoConnsvrPacket(buildHeader(appId, productLine, headerType, ack, msgId), buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package com.mogo.cloud.socket.third.utils;
|
||||
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class SignUtil {
|
||||
private static final String MD5_PREFIX = "zhidaoautosocket";
|
||||
private static final char[] DIGITS_LOWER;
|
||||
|
||||
static {
|
||||
DIGITS_LOWER = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
}
|
||||
|
||||
public static synchronized String createSign(String token) {
|
||||
String encryptString = MD5_PREFIX + token;
|
||||
return encodeHexString(md5(encryptString));
|
||||
}
|
||||
|
||||
private static String encodeHexString(byte[] data) {
|
||||
return new String(encodeHex(data));
|
||||
}
|
||||
|
||||
private static char[] encodeHex(byte[] data) {
|
||||
int l = data.length;
|
||||
char[] out = new char[l << 1];
|
||||
int i = 0;
|
||||
|
||||
for (int var5 = 0; i < l; ++i) {
|
||||
out[var5++] = DIGITS_LOWER[(240 & data[i]) >>> 4];
|
||||
out[var5++] = DIGITS_LOWER[15 & data[i]];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static byte[] md5(String string) {
|
||||
return string == null ? null : string.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -126,7 +126,7 @@ object V2XManager {
|
||||
}
|
||||
if (started.compareAndSet(false, true)) {
|
||||
Logger.d(TAG, "-- start real --")
|
||||
SocketManager.getInstance().init(config.context)
|
||||
SocketManager.getInstance().init(config.context,0.0,0.0)
|
||||
SocketManager.getInstance().registerOnMessageListener(401012, V2XMessageListener_401012(cbs))
|
||||
SocketManager.getInstance().registerOnMessageListener(401018, V2XMessageListener_401018(cbs))
|
||||
SocketManager.getInstance().registerOnMessageListener(402000, V2XMessageListener_402000(cbs))
|
||||
|
||||
@@ -33,29 +33,29 @@ SNAPSHOT_REPOSITORY_URL=http://nexus.zhidaoauto.com/repository/maven-snapshots/
|
||||
USERNAME=xintai
|
||||
PASSWORD=xintai2018
|
||||
# 编译模式: false - 依赖本地版本, true - 依赖 maven 版本
|
||||
RELEASE=false
|
||||
RELEASE=true
|
||||
# AI CLOUD 云平台
|
||||
# 工具类
|
||||
MOGO_UTILS_VERSION=1.3.32
|
||||
MOGO_UTILS_VERSION=1.3.49
|
||||
# 网络请求
|
||||
MOGO_NETWORK_VERSION=1.3.32
|
||||
MOGO_NETWORK_VERSION=1.3.49
|
||||
# 网络DNS
|
||||
MOGO_HTTPDNS_VERSION=1.3.32
|
||||
MOGO_HTTPDNS_VERSION=1.3.49
|
||||
# 鉴权
|
||||
MOGO_PASSPORT_VERSION=1.3.32
|
||||
MOGO_PASSPORT_VERSION=1.3.49
|
||||
# 常链接
|
||||
MOGO_SOCKET_VERSION=1.3.32
|
||||
MOGO_SOCKET_VERSION=1.3.49
|
||||
# 数据采集
|
||||
MOGO_REALTIME_VERSION=1.3.32
|
||||
MOGO_REALTIME_VERSION=1.3.49
|
||||
# 探路,道路事件发布,获取
|
||||
MOGO_TANLU_VERSION=1.3.32
|
||||
MOGO_TANLU_VERSION=1.3.49
|
||||
# 直播推流
|
||||
MOGO_LIVE_VERSION=1.3.32
|
||||
MOGO_LIVE_VERSION=1.3.49
|
||||
# 直播拉流
|
||||
MOGO_TRAFFICLIVE_VERSION=1.3.32
|
||||
MOGO_TRAFFICLIVE_VERSION=1.3.49
|
||||
# 定位服务
|
||||
MOGO_LOCATION_VERSION=1.3.32
|
||||
MOGO_LOCATION_VERSION=1.3.49
|
||||
# 远程通讯模块
|
||||
MOGO_TELEMATIC_VERSION=1.3.32
|
||||
MOGO_TELEMATIC_VERSION=1.3.49
|
||||
# v2x
|
||||
MOGO_V2X_VERSION=1.3.32
|
||||
MOGO_V2X_VERSION=1.3.49
|
||||
|
||||
@@ -41,7 +41,7 @@ public class SnapshotUploadInTime implements UploadInTimeHandler.IUploadInTimeLi
|
||||
*/
|
||||
public void start(Context context, String appId) {
|
||||
//开启长链服务
|
||||
SocketHandler.getInstance().initSocket(context, appId);
|
||||
SocketHandler.getInstance().initSocket(context, appId,0,0);
|
||||
//上传数据服务启动,定时上报
|
||||
UploadInTimeHandler.getInstance().start();
|
||||
UploadInTimeHandler.getInstance().setUploadInTimeListener(this);
|
||||
|
||||
@@ -47,9 +47,9 @@ public class SocketHandler {
|
||||
* @param context 上下文
|
||||
* @param appId 外部传入
|
||||
*/
|
||||
public void initSocket(Context context, String appId) {
|
||||
public void initSocket(Context context, String appId, double lat, double lon) {
|
||||
mAppId = appId;
|
||||
SocketManager.getInstance().init(context);
|
||||
SocketManager.getInstance().init(context, lat, lon);
|
||||
if (MoGoAiCloudClient.getInstance().getAiCloudClientConfig().getNetMode() == HTTP_DNS_ENV_DEMO) {
|
||||
SocketManager.getInstance().registerOnMessageListener(RealTimeConstant.DEMO_FREQUENCY_CHANNEL_ID, onMessageListener);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user