paho.mqtt.android icon indicating copy to clipboard operation
paho.mqtt.android copied to clipboard

java.lang.IllegalArgumentException Invalid ClientHandle

Open amglhit opened this issue 6 years ago • 20 comments

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)

amglhit avatar Sep 04 '18 06:09 amglhit

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

chintan-mishra avatar Nov 07 '18 16:11 chintan-mishra

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

SweetAsprin avatar Jan 21 '19 05:01 SweetAsprin

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

chintan-mishra avatar Jan 21 '19 07:01 chintan-mishra

@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?

SweetAsprin avatar Jan 21 '19 07:01 SweetAsprin

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

chintan-mishra avatar Jan 21 '19 07:01 chintan-mishra

`@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 avatar Jan 21 '19 07:01 SweetAsprin

`/** * Actually do the mqtt connect operation */ private void doConnect() { if (clientHandle == null) { clientHandle = mqttService.getClient(serverURI, clientId,myContext.getApplicationInfo().packageName, persistence); } mqttService.setTraceEnabled(traceEnabled); mqttService.setTraceCallbackId(clientHandle);

	String activityToken = storeToken(connectToken);
	try {
		mqttService.connect(clientHandle, connectOptions, null,
				activityToken);
	}
	catch (MqttException e) {
		IMqttActionListener listener = connectToken.getActionCallback();
		if (listener != null) {
			listener.onFailure(connectToken, e);
		}
	}
}`

SweetAsprin avatar Jan 21 '19 07:01 SweetAsprin

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

}`

SweetAsprin avatar Jan 21 '19 07:01 SweetAsprin

`/**

  • Get the MqttConnection identified by this client handle
  • @param clientHandle identifies the MqttConnection
  • @return the MqttConnection identified by this handle */ private MqttConnection getConnection(String clientHandle) { MqttConnection client = connections.get(clientHandle); if (client == null) { throw new IllegalArgumentException("Invalid ClientHandle"); } return client; }`

SweetAsprin avatar Jan 21 '19 07:01 SweetAsprin

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 avatar Jan 21 '19 07:01 SweetAsprin

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

SweetAsprin avatar Jan 21 '19 07:01 SweetAsprin

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
}

chintan-mishra avatar Jan 21 '19 08:01 chintan-mishra

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?

SweetAsprin avatar Jan 21 '19 08:01 SweetAsprin

Now I understand what problem you are facing.

chintan-mishra avatar Jan 21 '19 11:01 chintan-mishra

What do I do to reproduce the error @kuailewangzi0328 ?

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

chintan-mishra avatar Jan 21 '19 11:01 chintan-mishra

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 avatar Jan 21 '19 12:01 SweetAsprin

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

SweetAsprin avatar Jan 21 '19 12:01 SweetAsprin

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.

wll995806658 avatar Jan 19 '20 09:01 wll995806658

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?

ArcticSnowSky avatar Nov 19 '20 13:11 ArcticSnowSky

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.

bailyzheng avatar Jan 15 '21 02:01 bailyzheng