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

3
我正在开发一个包含聊天功能的应用程序,使用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个回答

2

我曾经遇到过同样的问题,并发现我无法像处理本地服务一样处理远程服务,详见这个问题。当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>

希望这能对您有所帮助。


没错,@l-swifter 把 MqttService 挂载到现有的父进程上确实可行,因为我已经有一个专门运行在自己进程中进行通信和其他操作的服务了。 - AXSM

1
我有这个问题,因为我们的代码中有两个服务:一个用于MQTT,另一个用于与服务器同步。
我们尝试将它们放在不同的进程中,但没有成功。我们还尝试将它们放在同一进程中,但也没有成功。
在寻找解决方案后,由于这是一个简单的ClassCastException,我们决定下载paho.mqtt.android的源代码并检查该转换。
所以,我们采取的步骤是:
  • 从这里克隆存储库:Eclipse Paho MQTT Android
  • 将项目导入您的IDE(例如Android Studio)
  • org.eclipse.paho.android.service包的MqttAndroidClient类中修改此方法,并将其放置在此处:

    @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            if (MqttServiceBinder.class.isAssignableFrom(binder.getClass())) {
                mqttService = ((MqttServiceBinder) binder).getService();
                bindedService = true;
                //现在我们有了可用的服务,我们可以实际连接...
                doConnect();
            }
        }
  • 编译并制作模块paho.mqtt.android.service',并使用IDE生成的aar。

有了那个aar,我们就没有问题了,问题已经解决了。

希望这能帮助你。


那个错误让我头疼。谢谢你提供的解决方案,对我很有效。 - loumaros

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。

为了解决这个问题,我想出了这个解决方法。

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

在服务器的AndroidManifest.xml中添加<service android:name=".service.RemoteServiceForMqtt"/>
在RemoteService(异常发生的地方)中替换为:
Intent service = new Intent(getApplicationContext(), RemoteServiceForMqtt.class);
service.putExtra("data1","data1");
service.putExtra("data2","data2");
service.putExtra("data3","data3");
startService(service);

希望这能帮助到某个人。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接