Android中MQTT的簡單實現(只是連線到伺服器,未實現傳送、接受資訊)
阿新 • • 發佈:2018-12-03
1.新增mqtt包到gradle.build
a.在project的gradle.build中新增地址(P:我下載的參考例子是不用新增的,但是我自己寫的時候不新增就編譯不過去)
allprojects {
repositories {
google()
jcenter()
maven {
url "https://repo.eclipse.org/content/repositories/paho-snapshots/"
}
}
}
b.在app的gradle.build中新增MQTT的依賴
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support.constraint:constraint-layout:1.1.2' implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0' implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1' }
2.在AndroidMenifest.xml中新增許可權和service
(P:那個WAKE_LOCK,ACCESS_NETWORK_STATE許可權和service一定要新增,之前參考網上的例子寫的時候沒有注意到要新增service,啟動mqtt.connect一直返回連線失敗,列印失敗資訊報cannot start service org.eclipse.paho.android.service.MqttService,然後添加了service又報WAKE_LOCK,ACCESS_NETWORK_STATE許可權安全錯誤,所以一定要注意新增它們)
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.chenss.baselib"> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <application android:name=".MyApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name="org.eclipse.paho.android.service.MqttService"> </service> </application>
3.佈局
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v7.widget.AppCompatEditText
android:id="@+id/host"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請輸入URl:格式tcp://ip地址"
android:layout_marginTop="5dp"
android:padding="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<android.support.v7.widget.AppCompatEditText
android:id="@+id/port"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請輸入埠號"
android:layout_marginTop="5dp"
android:padding="20dp"
app:layout_constraintTop_toBottomOf="@+id/host"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"/>
<android.support.v7.widget.AppCompatEditText
android:id="@+id/clientId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請輸入clientId"
android:layout_marginTop="5dp"
android:padding="20dp"
app:layout_constraintTop_toBottomOf="@+id/port"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"/>
<android.support.v7.widget.AppCompatEditText
android:id="@+id/userName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請輸入使用者名稱"
android:layout_marginTop="5dp"
android:padding="20dp"
app:layout_constraintTop_toBottomOf="@+id/clientId"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"/>
<android.support.v7.widget.AppCompatEditText
android:id="@+id/passWord"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請輸入密碼"
android:layout_marginTop="5dp"
android:padding="20dp"
app:layout_constraintTop_toBottomOf="@+id/userName"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"/>
<Button
android:id="@+id/connect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="連線"
android:background="@color/colorAccent"
android:layout_marginTop="5dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/passWord" />
</android.support.constraint.ConstraintLayout>
4 .實現程式碼:MainActivity
public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; @BindView(R.id.host) AppCompatEditText host; @BindView(R.id.port) AppCompatEditText port; @BindView(R.id.clientId) AppCompatEditText clientId; @BindView(R.id.connect) Button connect; @BindView(R.id.userName) AppCompatEditText userName; @BindView(R.id.passWord) AppCompatEditText passWord; private MqttAndroidClient mClient; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(MainActivity.this); } @OnClick(R.id.connect) public void onViewClicked() { if (check()) { connect(); } } private void connect() { String serUrl =getServerURI(host.getText().toString(), port.getText().toString()); connect.setText("正在連線"); //serUrl為主機名,clientid即連線MQTT的客戶端ID,一般以客戶端唯一識別符號表示,MemoryPersistence設定clientid的儲存形式,預設為以記憶體儲存 mClient = new MqttAndroidClient(MyApplication.getContext(), serUrl, clientId.getText().toString(),new MemoryPersistence()); //設定回撥 mClient.setCallback(mqttCallbackExtended); try { mClient.connect(getMqttConnectOptions(), "Connect", iMqttActionListener); } catch (MqttException ex) { ex.printStackTrace(); } } private boolean check() { if (TextUtils.isEmpty(host.getText().toString())) { Toast.makeText(MainActivity.this, "host不能為空", Toast.LENGTH_SHORT).show(); return false; } if (TextUtils.isEmpty(port.getText().toString())) { Toast.makeText(MainActivity.this, "port不能為空", Toast.LENGTH_SHORT).show(); return false; } if (TextUtils.isEmpty(clientId.getText().toString())) { Toast.makeText(MainActivity.this, "clientIds不能為空", Toast.LENGTH_SHORT).show(); return false; } if (TextUtils.isEmpty(userName.getText().toString())) { Toast.makeText(MainActivity.this, "userName不能為空", Toast.LENGTH_SHORT).show(); return false; } if (TextUtils.isEmpty(passWord.getText().toString())) { Toast.makeText(MainActivity.this, "passWord不能為空", Toast.LENGTH_SHORT).show(); return false; } return true; } private MqttCallbackExtended mqttCallbackExtended = new MqttCallbackExtended() { @Override public void connectComplete(boolean reconnect, String serverURI) { //連線丟失後,一般在這裡面進行重連 if (reconnect) { Log.e(TAG, "Reconnected to : " + serverURI); connect.setText("連線成功"); } else { Log.e(TAG, "Connected to: " + serverURI); connect.setText("連線成功"); } } @Override public void connectionLost(Throwable cause) { Log.e(TAG, "The Connection was lost."); } @Override public void messageArrived(String topic, MqttMessage message) throws Exception { //subscribe後得到的訊息會執行到這裡面 Log.e(TAG, "Incoming message: " + new String(message.getPayload())); } @Override public void deliveryComplete(IMqttDeliveryToken token) { //publish後會執行到這裡 } }; private IMqttActionListener iMqttActionListener = new IMqttActionListener() { @Override public void onSuccess(IMqttToken asyncActionToken) { Log.e(TAG, "onSuccess!"); connect.setText("連線成功"); } @Override public void onFailure(IMqttToken asyncActionToken, Throwable exception) { Log.e(TAG, "exception: " + exception.getMessage()); connect.setText("連線失敗"); } }; public String getServerURI(String host,String port) { return "tcp://" + host + ":" + port; } //MQTT的連線設定 public MqttConnectOptions getMqttConnectOptions() { MqttConnectOptions options = new MqttConnectOptions(); //設定是否清空session,這裡如果設定為false表示伺服器會保留客戶端的連線記錄,這裡設定為true表示每次連線到伺服器都以新的身份連線 options.setCleanSession(true); // 設定超時時間 單位為秒 options.setConnectionTimeout(10); // 設定會話心跳時間 單位為秒 伺服器會每隔1.5*20秒的時間向客戶端傳送個訊息判斷客戶端是否線上,但這個方法並沒有重連的機制 options.setKeepAliveInterval(20); //設定連線的使用者名稱 options.setUserName(userName.getText().toString().trim()); //設定連線的密碼 options.setPassword(passWord.getText().toString().trim().toCharArray()); return options; } @Override protected void onDestroy() { try { if (mClient!=null&&mClient.isConnected()){ mClient.disconnect(); } } catch (MqttException e) { e.printStackTrace(); } super.onDestroy(); } }