2017-08-16 113 views
1

来自MainActivity onCreate()的我的应用程序启动了一个服务,它连接到服务器并订阅主题。另外,当我添加新的连接时,我的服务重新启动(使用stop/startService)。我将连接数据(IP,端口等)存储在SQL数据库中,并在启动后将其存储在服务中。问题是(我认为),当连接参数之一不正确的服务正在等待超时,并阻止一个活动... 如果我设置token.waitForCompletion(500);它变得更快,但我不能猜测该值...为什么MQTT服务阻止活动?

有办法解决我的问题吗?

@Override 
public void onCreate() { 

    Datapool(); 
    IntentFilter intentf = new IntentFilter(); 
    intentf.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 
    registerReceiver(mqttBroadcastReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); 
    mConnMan = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE); 
    deviceId = String.format(DEVICE_ID_FORMAT, Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID)); 

} 

MQTTBroadcastReceiver mqttBroadcastReceiver = new MQTTBroadcastReceiver(); 

class MQTTBroadcastReceiver extends BroadcastReceiver { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     Connect(); 
    } 

}; 

IMqttToken token; 
int i = 0; 
private HashMap<String, Boolean> _hashMap = new HashMap<>(); 
private void Connect(){ 
    for (ServiceDataModel connectionData : dataModels) { 

     Log.d(TAG, "doConnect() " + connectionData.getCONNECTION_NAME()); 
     _hashMap.put(connectionData.getCONNECTION_NAME(), false); 
     MqttConnectOptions options = new MqttConnectOptions(); 
     options.setCleanSession(true); 
     i++; 
     try { 
      mqttClient = new MqttAsyncClient("tcp://" + connectionData.getSERVER_IP() + ":" + connectionData.getSERVER_PORT(), deviceId + i , new MemoryPersistence()); 
      token = mqttClient.connect(); 
      token.waitForCompletion(2500); 
      if (mqttClient.isConnected()) { 
        mqttClient.setCallback(new MqttEventCallback()); 
        token = mqttClient.subscribe(connectionData.getTOPIC(), Integer.parseInt(connectionData.getQOS())); 
        token.waitForCompletion(2500); 
        _hashMap.put(connectionData.getCONNECTION_NAME(), true); 
      } 
     }catch (Exception ex){ 
      Log.d(TAG, ex.toString() + connectionData.toString()); 
     } 
    } 
    sendMessageToActivity(_hashMap); 
} 

回答

1

通过调用token.waitForCompletion(2500)您试图首先同步连接,然后订阅 - 这块主线程。

请勿应用这些黑客行为,而应使用异步连接回调(下面的mCallbackmConnectionCallback)。和连接成功后,使用异步回调认购(mSubscribeCallback下):

private final MqttCallbackExtended mCallback = new MqttCallbackExtended() { 
    @Override 
    public void connectComplete(boolean reconnect, String brokerAddress) { 
      mqttClient.subscribe(connectionData.getTOPIC(), Integer.parseInt(connectionData.getQOS()), null, mSubscribeCallback); 
    } 

    @Override 
    public void connectionLost(Throwable ex) { 
    } 

    @Override 
    public void deliveryComplete(IMqttDeliveryToken deliveryToken) { 
    } 

    @Override 
    public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception { 
    } 
}; 

private final IMqttActionListener mConnectionCallback = new IMqttActionListener() { 
    @Override 
    public void onSuccess(IMqttToken asyncActionToken) { 
     // do nothing, this case is handled in mCallback.connectComplete() 
    } 

    @Override 
    public void onFailure(IMqttToken asyncActionToken, Throwable exception) { 
    } 
}; 

private final IMqttActionListener mSubscribeCallback = new IMqttActionListener() { 
    @Override 
    public void onSuccess(IMqttToken subscribeToken) { 
      _hashMap.put(connectionData.getCONNECTION_NAME(), true); 
    } 

    @Override 
    public void onFailure(IMqttToken subscribeToken, Throwable ex) { 
    } 

}; 

try { 
    MqttConnectOptions connectOptions = new MqttConnectOptions(); 
    connectOptions.setCleanSession(true); 
    connectOptions.setAutomaticReconnect(false); 
    connectOptions.setUserName(USERNAME); 
    connectOptions.setPassword(PASSWORD.toCharArray()); 

    mqttClient = new MqttAsyncClient("tcp://" + connectionData.getSERVER_IP() + ":" + connectionData.getSERVER_PORT(), deviceId + i , new MemoryPersistence()); 
    mqttClient.setCallback(mCallback); 
    mqttClient.connect(connectOptions, null, mConnectionCallback); 

} catch (Exception ex) { 
    Log.d(TAG, ex.toString() + connectionData.toString()); 
} 

因此重新安排你的应用程序了一下,也不会封锁。

还可以考虑使用LocalBroadcastManager在SQLite,MQTT和Activity之间进行通信。