2016-09-06 4 views
1

Я работаю над приложением, которое включает функцию чата с использованием MqttAndroidClient, и у меня возникла проблема с инициализацией клиента.android.os.BinderProxy не может быть передан в org.eclipse.paho.android.service.MqttServiceBinder

Я пытаюсь выполнить отдельный процесс (используя : remote), чтобы запустить клиент mqtt, чтобы подписаться на брокера, чтобы получать сообщения с моего чат-сервера. Удаленная служба создается в рамках основной операции, и я установил IPC с помощью AIDL. Я знаю, что код ошибки указывает, что с IPC есть ошибка; однако я не могу найти причину, потому что я уверен, что правильно установил AIDL.

Короче говоря, вот мои служебные коды:

private static final String MQTT_BROKER = "________(blank on purpose)"; 
private String userId; 
private String publishTopic; 
private String subscribeTopic; 
MqttAndroidClient client; 

@Nullable 
@Override 
public IBinder onBind(Intent intent) { 
    return new Chat_AIDL.Stub() { 
     @Override 
     public String passString(String message) throws RemoteException { 
      return message; 
     } 
    }; 
} 

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 
    userId = intent.getStringExtra("userId"); 
    publishTopic = "chat/+/" + userId + "/"; 
    subscribeTopic = "chat/#/" + userId + "/"; 

    Log.d("publishTopic", publishTopic); 
    Log.d("subscribeTopic", subscribeTopic); 


    establishMqttConnection(); 

    client.setCallback(new MqttCallback() { 
     @Override 
     public void connectionLost(Throwable cause) { 

     } 

     @Override 
     public void messageArrived(String topic, MqttMessage receivedMessage) throws Exception { 
      Intent in = new Intent(); 
      String msg = new String(receivedMessage.getPayload(), "UTF-8"); 

      in.putExtra("resultCode", Activity.RESULT_OK); 
      in.putExtra("chatMsg", msg); 
      Log.d("MQTT_RECEIVED", msg); 
      LocalBroadcastManager.getInstance(getBaseContext()).sendBroadcast(in); 
     } 

     @Override 
     public void deliveryComplete(IMqttDeliveryToken token) { 

     } 
    }); 


    Log.d("SERVICE_CHAT", "STICKY"); 

    super.onStartCommand(intent, flags, startId); 
    return Service.START_STICKY; 
} 

private void establishMqttConnection() { 
    MemoryPersistence memPer = new MemoryPersistence(); 
    client = new MqttAndroidClient(this, MQTT_BROKER, userId, memPer); 
    try { 
     client.connect(null, new IMqttActionListener() { 
      @Override 
      public void onSuccess(IMqttToken asyncActionToken) { 
       Log.d("MQTT", "SUCCESS"); 
       subscribeMessage(); 
      } 

      @Override 
      public void onFailure(IMqttToken asyncActionToken, Throwable exception) { 
       Log.d("MQTT", "FAILURE"); 
       exception.printStackTrace(); 
      } 
     }); 
    } catch (MqttException e) { 
     e.printStackTrace(); 
    } 
} 

private void subscribeMessage() { 
    try { 
     client.subscribe(subscribeTopic, 0, null, new IMqttActionListener() { 
      @Override 
      public void onSuccess(IMqttToken asyncActionToken) { 

      } 

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

      } 
     }); 
    } catch (MqttSecurityException e) { 
     e.printStackTrace(); 
    } catch (MqttException e) { 
     e.printStackTrace(); 
    } 
} 

ответ

1

Я сталкивался с таким же вопросом, и я обнаружил, что я не могу иметь дело с дистанционным обслуживанием, как местный сервис, посмотреть issue. Когда служба mqtt создается в разных процессах, официальный пример не будет работать.

Моего способ решить этот вопрос создает свою собственную службу и сделать эту услугу, созданной в одних и тех же процессах с сервисом MQTT:

<application> 
    <!-- skipped... --> 
    <service 
     android:name=".MyService" 
     android:exported="false" 
     android:process=":background" /> 
    <service 
     android:name="org.eclipse.paho.android.service.MqttService" 
     android:process=":background" /> 
</application> 

Надеется, что это может помочь вам.

+0

Да, @ l-swifter, приклеивающий MqttService к существующему родительскому процессу, работал, поскольку у меня уже есть выделенный сервис, который запускается на собственном процессе для общения и других действий. – AlexSanchez

0

Сегодня я столкнулся с этим исключением, я сделал много изменений, но большинство из них нарушало мой код и его логику. Это моя логика, у меня есть приложение (говорит клиент), который отправляет данные в другое приложение (говорит сервер). Чтобы сделать это, следуйте за this tutorial. Я должен был сделать некоторые изменения в моей AndroidManifest.xml серверов, которые

<service android:name=".service.RemoteService" 
     android:process=":remote"> 
     <intent-filter> 
      <action android:name="full.package.name.service.RemoteService" > 
      </action> 
     </intent-filter> 
</service> 

Как @L. По словам Swifter, проблема связана с тем, что мы пытаемся подключиться к MQTT из службы, предназначенной для remote listening.

Чтобы решить эту проблему, я могу решить этот обходной путь.

  1. Создать другую службу RemoteServiceForMqtt
  2. В RemoteService службы, запускает службу RemoteServiceForMqtt
  3. При запуске службы добавить данные, которые вы хотите отправить MQTT в качестве статистов.
  4. В RemoteServiceForMqtt переопределите метод public int onStartCommand(Intent intent, int flags, int startId), где вы добавляете свой метод, который будет отправлять данные в mqtt.

Это

public class RemoteServiceForMqtt extends Service 
{ 
    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     MqttClientUtil.getInstance(RemoteServiceForMqtt.this).reconnect(); // MqttClientUtil is a class that content all the necessary informations needed to connect to mqtt 
     if (intent != null){ 
      Bundle bundle = intent.getExtras(); 
      sendToMQTT(bundle.getString("data1"),bundle.getString("data2"),bundle.getString("data3")); 
     } 
     return 0b1; 
    } 


    public void sendToMQTT(String data1, String data2,String data3) { 

     JSONObject object = new JSONObject(); 
     try { 
      object.put("data1", data1); 
      object.put("data2", data2); 
      object.put("data3", data3); 
     } catch (JSONException e) { 
      e.printStackTrace(); 
     } 

     MqttClientUtil.getInstance(RemoteServiceForMqtt.this).publish(object.toString()); 
    } 

    @Nullable 
    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 
} 

Добавить <service android:name=".service.RemoteServiceForMqtt"/> в AndroidManifest.xml сервера.

В RemoteService (где происходит исключение) заменить

Intent service = new Intent(getApplicationContext(), RemoteServiceForMqtt.class); 
service.putExtra("data1","data1"); 
service.putExtra("data2","data2"); 
service.putExtra("data3","data3"); 
startService(service); 

Надеется, что это поможет кому-то.

0

У меня была эта проблема, потому что в нашем коде у нас есть две службы: одна для MQTT и другая, которая синхронизирует вещи с сервером.

Мы попытались установить отдельные процессы, но это не сработало. Также мы попытались включить их в один и тот же процесс, но это тоже не сработало.

После поиска решений, поскольку это было простое ClassCastException, мы решили загрузить исходный код paho.mqtt.android и проверить его.

Итак, шаги, которые мы сделали:

  • хранилище клонов здесь: Eclipse Paho MQTT Android
  • Импорт проект на вашем IDE (то есть Android-студия)
  • В MqttAndroidClient классе пакета org.eclipse.paho.android.service модифицировать этот метод и следующим образом:

    @Override 
        public void onServiceConnected(ComponentName name, IBinder binder) { 
         if (MqttServiceBinder.class.isAssignableFrom(binder.getClass())) { 
          mqttService = ((MqttServiceBinder) binder).getService(); 
          bindedService = true; 
          // now that we have the service available, we can actually 
          // connect... 
          doConnect(); 
         } 
        }
  • Скомпилировать и изготовить модуль paho.mqtt.android.service' и используйте aar, сгенерированный вашей IDE.

С этим aar у нас нет проблем, и проблема исчезла.

Надеюсь, это поможет.