一、单向认证
public class SSLSingleTrustManager implements TrustManager, X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType)throws CertificateException {
return;
}
public void checkServerTrusted(X509Certificate[] chain, String authType)throws CertificateException {
return;
}
public X509Certificate[]getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(X509Certificate[] certs) {
return true;
}
}
private void singleTrust(MqttConnectOptions options ){
TrustManager[] trustAllCerts =new TrustManager[]{new SSLSingleTrustManager()};
SSLContext sc =null;
try {
sc =SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, null);
}catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}catch (KeyManagementException e) {
e.printStackTrace();
}
SocketFactory factory = sc.getSocketFactory();
options.setSocketFactory(factory);
}
二、手动重连
用手动重连原因当然是自动重连不好用了!!
options.setAutomaticReconnect(true);
这一段是源码,重连
/**
* Reconnect
* Only appropriate if cleanSession is false and we were connected.
* Declare as synchronized to avoid multiple calls to this method to send connect
* multiple times
*/
synchronized void reconnect() {
if (myClient ==null) {
service.traceError(TAG,"Reconnect myClient = null. Will not do reconnect");
return;
}
if (isConnecting) {
service.traceDebug(TAG, "The client is connecting. Reconnect return directly.");
return ;
}
if(!service.isOnline()){
service.traceDebug(TAG,
"The network is not reachable. Will not do reconnect");
return;
}
if(connectOptions.isAutomaticReconnect()){
//The Automatic reconnect functionality is enabled here
Log.i(TAG, "Requesting Automatic reconnect using New Java AC");
final Bundle resultBundle =new Bundle();
resultBundle.putString(
MqttServiceConstants.CALLBACK_ACTIVITY_TOKEN,
reconnectActivityToken);
resultBundle.putString(
MqttServiceConstants.CALLBACK_INVOCATION_CONTEXT, null);
resultBundle.putString(MqttServiceConstants.CALLBACK_ACTION,
MqttServiceConstants.CONNECT_ACTION);
try {
myClient.reconnect();
}catch (MqttException ex){
Log.e(TAG, "Exception occurred attempting to reconnect: " + ex.getMessage());
setConnectingState(false);
handleException(resultBundle, ex);
}
}else if (disconnected && !cleanSession) {
// use the activityToke the same with action connect
service.traceDebug(TAG,"Do Real Reconnect!");
final Bundle resultBundle =new Bundle();
resultBundle.putString(
MqttServiceConstants.CALLBACK_ACTIVITY_TOKEN,
reconnectActivityToken);
resultBundle.putString(
MqttServiceConstants.CALLBACK_INVOCATION_CONTEXT, null);
resultBundle.putString(MqttServiceConstants.CALLBACK_ACTION,
MqttServiceConstants.CONNECT_ACTION);
try {
IMqttActionListener listener =new MqttConnectionListener(resultBundle) {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
// since the device's cpu can go to sleep, acquire a
// wakelock and drop it later.
service.traceDebug(TAG,"Reconnect Success!");
service.traceDebug(TAG,"DeliverBacklog when reconnect.");
doAfterConnectSuccess(resultBundle);
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
resultBundle.putString(
MqttServiceConstants.CALLBACK_ERROR_MESSAGE,
exception.getLocalizedMessage());
resultBundle.putSerializable(
MqttServiceConstants.CALLBACK_EXCEPTION,
exception);
service.callbackToActivity(clientHandle, Status.ERROR,
resultBundle);
doAfterConnectFail(resultBundle);
}
};
myClient.connect(connectOptions, null, listener);
setConnectingState(true);
}catch (MqttException e) {
service.traceError(TAG, "Cannot reconnect to remote server." + e.getMessage());
setConnectingState(false);
handleException(resultBundle, e);
}catch (Exception e){
/* TODO: Added Due to: https://github.com/eclipse/paho.mqtt.android/issues/101
For some reason in a small number of cases, myClient is null here and so
a NullPointer Exception is thrown. This is a workaround to pass the exception
up to the application. myClient should not be null so more investigation is
required.
*/
service.traceError(TAG, "Cannot reconnect to remote server." + e.getMessage());
setConnectingState(false);
MqttException newEx =new MqttException(MqttException.REASON_CODE_UNEXPECTED_ERROR, e.getCause());
handleException(resultBundle, newEx);
}
}
}
一顿骚操作看的眼花缭乱,经过断网测试,这经常抛出已连接客户机的异常拒绝重连,导致一旦掉线后一直无法重连。
于是乎有了不要自动重连手动重连的方案,每十秒尝试一次重连,屡试不爽
public void connectionLost(Throwable cause) {
if (!isConnecting){
startReconnect();
isConnecting =true;
}
}
private void startReconnect(){
if (!isDissConnectedBySelf) {
synchronized (MQTTManager.class) {
LogUtils.d(TAG, "开始重连 ");
runnable = getRunnable();
isNeedReConnect =true;
mHandler.postDelayed(runnable, 2000);
}
}else {
LogUtils.d(TAG, "主动断开 不重连接 ");
}
}
private void stopToConnect(){
LogUtils.d(TAG,"结束重连 ");
isNeedReConnect =false;
isDissConnectedBySelf =false;
mHandler.removeCallbacks(runnable);
runnable =null;
}
private RunnablegetRunnable(){
if (runnable!=null){
return runnable;
}
return new Runnable() {
@Override
public void run() {
LogUtils.d(TAG,isNeedReConnect +" "+isConnectIsNomarl() +" "+isNetworkAvailable());
if (isNeedReConnect &&isConnectIsNomarl() &&isNetworkAvailable()) {
LogUtils.d(TAG,"重连尝试 "+currentConnectTime++);
doClientConnection();
}
mHandler.postDelayed(this,TIME_OUT);
}
};
}
又是一顿骚操作完美解决问题,设置自动重连不好用那就直接重新连接吧