Open amglhit opened 6 years ago
Please reformat your snippet. And show us some code that you are using to connect with the broker.
you should not throw IllegalArgumentException in getConnection method…… we can not catch this exception in main thread, it make my application crash many times……
@kuailewangzi0328 you should not be doing any network operation on Main Thread of android. This will lead to crash and ANRs.
@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?
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
`@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;
}`
`/**
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);
}
}
}`
`public void connect(String clientHandle, MqttConnectOptions connectOptions, String invocationContext, String activityToken) throws MqttSecurityException, MqttException { MqttConnection client = getConnection(clientHandle); client.connect(connectOptions, null, activityToken);
}`
`/**
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
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
}
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?
Now I understand what problem you are facing.
What do I do to reproduce the error @kuailewangzi0328 ?
I tried connecting a vanilla application it seems to work fine/
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.
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
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.
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?
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.
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)