我正在为我的Android应用程序使用MQTT。我在扩展 AsyncTask 的类中实现了 MQTT 连接。这是我的代码:
public class MainActivity extends AppCompatActivity {
String TAG = "MQTT";
private Context context;
String status;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
context = getApplicationContext();
MQTT mqtt = new MQTT();
mqtt.execute();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public class MQTT extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
String clientId = generateClientId();
MqttAndroidClient client =
new MqttAndroidClient(context, "tcp://broker.hivemq.com:1883",
clientId);
try {
IMqttToken token = client.connect();
token.setActionCallback(new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
// We are connected
Log.d(TAG, "onSuccess");
status = "True";
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
// Something went wrong e.g. connection timeout or firewall problems
Log.d(TAG, "onFailure");
status = "False";
}
});
} catch (MqttException e) {
e.printStackTrace();
}
Log.d(TAG, "value of status " + status);
return status;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Log.d(TAG, s);
}
}
}
我在这里面临的问题是doInBackground()在调用onSuccess之前返回。因此,此函数将状态返回为 null。我试图在 onPostExecute() 中获取返回值的日志,它显示 null。而我在doInBackGround内的onSuccess函数中分配状态值。有没有办法确保doInBackground仅在onSuccess完成后返回。
快速解决方案是阻止直到异步任务完成,例如通过使用Semaphore
:
protected String doInBackground(String... params) {
String clientId = generateClientId();
MqttAndroidClient client = // ....
Semaphore s = new Semaphore(0);
try {
IMqttToken token = client.connect();
token.setActionCallback(new IMqttActionListener() {
@Override
public void onSuccess() {
// ...
status = "True";
s.release();
}
@Override
public void onFailure() {
// ...
status = "False";
s.release();
}
});
} catch (MqttException e) {
e.printStackTrace();
s.release();
}
s.acquire(); // blocks until `s.release()` is invoked in callback
return status;
}