eclipse-paho / paho.mqtt.android

MQTT Android
Other
2.94k stars 892 forks source link

java.lang.IllegalArgumentException Invalid ClientHandle #318

Open amglhit opened 6 years ago

amglhit commented 6 years ago

Invalid ClientHandle

org.eclipse.paho.android.service.MqttService.org.eclipse.paho.android.service.MqttConnection getConnection(java.lang.String)(SourceFile:588) org.eclipse.paho.android.service.MqttService.void connect(java.lang.String,org.eclipse.paho.client.mqttv3.MqttConnectOptions,java.lang.String,java.lang.String)(SourceFile:328) org.eclipse.paho.android.service.MqttAndroidClient.void doConnect()(SourceFile:467) org.eclipse.paho.android.service.MqttAndroidClient.org.eclipse.paho.android.service.MqttService access$002(org.eclipse.paho.android.service.MqttAndroidClient,org.eclipse.paho.android.service.MqttService)(SourceFile:76)

chintan-mishra commented 6 years ago

Please reformat your snippet. And show us some code that you are using to connect with the broker.

SweetAsprin commented 5 years ago

you should not throw IllegalArgumentException in getConnection method…… we can not catch this exception in main thread, it make my application crash many times……

chintan-mishra commented 5 years ago

@kuailewangzi0328 you should not be doing any network operation on Main Thread of android. This will lead to crash and ANRs.

SweetAsprin commented 5 years ago

@chintan-mishra yes,I have not do any network operate in main thread, but I need call mClient.connect(mConnectOptions,null, mConnectCallback) in main thread, but in this method , you called pool.excute(doConnect();), and throw a IllegalArgumentException in code "getConnection(clientHandle)", so this exception throwed in another thread, then my app crashed because I cant catch this exception when I call "mClient.connect()" in main thread, how can I do?

chintan-mishra commented 5 years ago

This is a network operation mClient.connect(mConnectOptions,null, mConnectCallback).

What does this execute?

pool.excute(doConnect();) // Looks like semantic error

I have no idea of your implementation. Share your code.

And format your snippet so that we can find it easily

SweetAsprin commented 5 years ago

`@Override public IMqttToken connect(MqttConnectOptions options, Object userContext, IMqttActionListener callback) throws MqttException {

    IMqttToken token = new MqttTokenAndroid(this, userContext,
            callback);

    connectOptions = options;
    connectToken = token;

    /*
     * The actual connection depends on the service, which we start and bind
     * to here, but which we can't actually use until the serviceConnection
     * onServiceConnected() method has run (asynchronously), so the
     * connection itself takes place in the onServiceConnected() method
     */
    if (mqttService == null) { // First time - must bind to the service
        Intent serviceStartIntent = new Intent();
        serviceStartIntent.setClassName(myContext, SERVICE_NAME);
        Object service = myContext.startService(serviceStartIntent);
        if (service == null) {
            IMqttActionListener listener = token.getActionCallback();
            if (listener != null) {
                listener.onFailure(token, new RuntimeException(
                        "cannot start service " + SERVICE_NAME));
            }
        }

        // We bind with BIND_SERVICE_FLAG (0), leaving us the manage the lifecycle
        // until the last time it is stopped by a call to stopService()
        myContext.bindService(serviceStartIntent, serviceConnection,
                Context.BIND_AUTO_CREATE);

        if (!receiverRegistered) registerReceiver(this);
    }
    else {
        pool.execute(new Runnable() {

            @Override
            public void run() {
                doConnect();

                //Register receiver to show shoulder tap.
                if (!receiverRegistered) registerReceiver(MqttAndroidClient.this);
            }

        });
    }

    return token;
}`
SweetAsprin commented 5 years ago

`/**

SweetAsprin commented 5 years ago

`public void connect(String clientHandle, MqttConnectOptions connectOptions, String invocationContext, String activityToken) throws MqttSecurityException, MqttException { MqttConnection client = getConnection(clientHandle); client.connect(connectOptions, null, activityToken);

}`

SweetAsprin commented 5 years ago

`/**

SweetAsprin commented 5 years ago

try { mClient.connect(mConnectOptions,null, mConnectCallback); } catch (Exception e) { e.printStackTrace(); LogUtil.e("连接到Mqtt服务器失败!"); doReconnect(false); }

this is my code, I just call connect(), but it throw exception and I cant catch it ,So my app crashed

SweetAsprin commented 5 years ago

https://github.com/eclipse/paho.mqtt.android/blob/b5d5e5ef91e846d39a365b8c561fa9670d34f691/org.eclipse.paho.android.service/src/main/java/org/eclipse/paho/android/service/MqttService.java#L588

https://github.com/eclipse/paho.mqtt.android/blob/b5d5e5ef91e846d39a365b8c561fa9670d34f691/org.eclipse.paho.android.service/src/main/java/org/eclipse/paho/android/service/MqttAndroidClient.java#L431

chintan-mishra commented 5 years ago

IllegalArgumentException is the correct exception but the issue is that you were not able to catch it on the main thread.

For now you can try this

try {
  // Your code
} catch (MqttException | IllegalArgumentException e) {
  // More code to handle exception
}
SweetAsprin commented 5 years ago

I call mClient.connect() in A thread, but actually your code excuted and throw exception in B thread because your code excute by pool.excute() , so I cant catch any exception in my code ,do you understand?

chintan-mishra commented 5 years ago

Now I understand what problem you are facing.

chintan-mishra commented 5 years ago

What do I do to reproduce the error @kuailewangzi0328 ?

I tried connecting a vanilla application it seems to work fine/

SweetAsprin commented 5 years ago

In my application, I register a network state change broadcast receiver ,when network disable, I disconnecte mqtt connection, and when network available, I will try to reconnect to the mqtt server, so when turn on/off my cellphone's wifi or celluar data, the code will be throw this exception. Actually in the begin, I find the exception throwed when I call mCliend.isconnected(), so I catch this exception. but then I find it crash as before, so when I read the source cod I find I cant catch the cxception when I call mClient.connect() because it run in another thread.

SweetAsprin commented 5 years ago

in my opinion, you should not just throw a exception when you get a null object in getConnection method, in especial you excute it in other thread , it make my whole application crash again and again, even I cant catch it . you should invoke the callback onfail method, then I can make a try to reconnect or do other thing …… I hope you can give me a solution to avoid my application crash…… thanks a lot

wll995806658 commented 4 years ago

I also face this problem. Similar to his situation.I try to connect and disconnect frequently.It seems that such a problem occurs when I call disconnect before getting the callback result of the subscribe, and then, I call connect again. but I'm not sure.

ArcticSnowSky commented 4 years ago

Heya @all, as I am working on a project with this lib too, I got also contact with this problem.

I always got the problem when my app got restarted, however i have to add that i have a foreground_service keeping various connectionSystems (Bluetooth, Mqtt, DataRecorder). The problem appeared when: App gets closed (with isFinally() true), unregisterResources gets called. Inside, unregisterReceiver gets called. ClientHandle can't be set to null anymore. When the app gets opened again,client Object I have is still the same (as it was stored in the foreground_service). registerResources didn't help, because the ClientHandle inside was not null, on the next operation it will say InvalidClientHandle.

In my opinion, unregisterReceiver maybe shall set ClientHandle null, or registerReceiver might check ClientHandle validity and reset it if required?

bailyzheng commented 3 years ago

I also got this problem. It disappeared when I set the auto connection option to false. Reconnect by some other method when it disconnect. You guys can try this method to get rid of this bug.