2017-08-16 6 views
1

MainActivity onCreate()のアプリケーションは、サーバーに接続しトピックを購読するサービスを開始します。また、新しい接続を追加すると、サービスが(stop/startServiceを使用して)再起動します。私はSQLデータベースに接続データ(ip、portなど)を保存し、起動後にサービスにプールします。問題は(私は)接続パラメータの1つが間違っていると、サービスがタイムアウトを待っていて、アクティビティをブロックしているということです... 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)を呼び出すことによって - ブロックメインスレッドを。

これらのハッキングを適用しないでください。代わりに、非同期接続コールバック(mCallbackおよびmConnectionCallback)を使用してください。だからあなたのアプリはビットを再配置し、それがブロックされません

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()); 
} 

:接続が成功した後と、非同期サブスクリプションのコールバック(以下mSubscribeCallback)を使用します。

また、SQLite、MQTT、およびアクティビティ間の通信にLocalBroadcastManagerを使用することを検討してください。

関連する問題