Issue
When using MqttClient in AsnyTask, the client callback to MqttListener.messageArrived() is executed after Async.onPostExecute().
That means that the reply variable will be set after it is passed to the listener callback.
If onTaskCompleted is called from the MqttClient thread (from messageArrived()), an Exception is thrown from inside onTaskCompleted:
MqttException (0) - android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
public class MqttRequestHandler extends AsyncTask<Object, Void, String> implements MqttCallback {
private OnTaskCompleted listener;
String reply = "";
public MqttRequestHandler(OnTaskCompleted listener) {
this.listener = listener;
}
@Override
protected String doInBackground(Object... params) {
try {
MqttClient client = new MqttClient("tcp://192.168.1.101", "test-client", new MemoryPersistence());
client.setCallback(this);
client.connect();
client.subscribe(setup.topic);
} catch (Exception e) {
Log.e("MqttResponseHandler", e.toString());
}
return ""; //dummy, since we have to use the callback
}
@Override
public void connectionLost(Throwable cause) {
Log.d("MqttRequestHandler", "connectionLost: " + cause.toString());
}
@Override
public void messageArrived(String topic, MqttMessage message) {
this.reply = message.toString(); // not empty
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
protected void onPostExecute(String dummy) {
listener.onTaskCompleted(this.reply); // empty string!
}
}
listener.onTaskCompleted(..) hangs when to doing ImageView.setImageBitmap(). The error message is received in connectionLost().
Solution
You can't Change a View from another thread, you have to make sure to Access the View from the Thread it was created in, this should be the UI Thread. You can refer to this Post
How do we use runOnUiThread in Android?
Inside your listener.onTaskCompleted(..)
function you should make sure to Access your Views from the UI Thread.
If you want to use only the received String you can remove the OnPostexecute and do your onTaskcompleted inside your messagearrived callback.
Remove
protected void onPostExecute(String dummy) {
listener.onTaskCompleted(this.reply); // empty string!
}
and Change
@Override
public void messageArrived(String topic, MqttMessage message) {
this.reply = message.toString(); // not empty
}
to
@Override
public void messageArrived(String topic, MqttMessage message) {
listener.onTaskCompleted(message.toString())
}
Answered By - Dominik Wuttke
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.