android.os.BinderProxy无法强制转换为org.eclipse.paho.android.service.MqttServiceBinder

时间:2016-09-06 11:55:13

标签: java android service casting mqtt

我正在使用MqttAndroidClient处理包含聊天功能的应用,我在初始化客户端时遇到了问题。

我想要实现的是运行一个单独的进程(使用:remote )来运行mqtt客户端以订阅代理,以便从我的聊天服务器获取消息。 远程服务在主活动中创建,我使用AIDL设置IPC。 我知道错误代码指出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();
    }
}

3 个答案:

答案 0 :(得分:2)

我遇到了同样的问题,我发现我无法像本地服务那样处理远程服务,请参阅此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>

希望这可以帮到你。

答案 1 :(得分: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说,问题是因为我们试图从remote listening的服务连接到MQTT。

要解决此问题,我可以解决此问题。

  1. 创建另一项服务RemoteServiceForMqtt
  2. 在服务RemoteService中,启动服务RemoteServiceForMqtt
  3. 启动服务时,将要发送给Mqtt的数据添加为附加内容。
  4. 在RemoteServiceForMqtt中,覆盖方法public int onStartCommand(Intent intent, int flags, int startId),您可以在其中添加将数据发送到mqtt的方法。
  5. 那是

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

    希望这有助于某人。

答案 2 :(得分:0)

我遇到了这个问题,因为在我们的代码中我们有两个服务:一个用于MQTT,另一个用于与服务器同步。

我们试图加入单独的流程,但它没有起作用。我们也尝试将它们放在同一个过程中,但它也没有用。

在寻找解决方案后,因为它是一个简单的ClassCastException,我们决定下载paho.mqtt.android的源代码并检查该转换。

所以,我们采取的步骤:

  • 从此处克隆存储库:Eclipse Paho MQTT Android
  • 在IDE(即Android Studio)上导入项目
  • 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'并使用IDE生成的aar。

有了这个,我们没有问题,问题已经消失。

希望这有帮助。