一、简介
此文章是通过阿里云提供的文档书写的笔记,作为小白的参考。
二、安装Paho Android Client
2.1、新建一个Android工程
这个就不写了,不会的问百度。
2.2、添加Paho Android Client依赖
阿里云的文档中说:工程build.gradle中,添加Paho仓库地址。本示例使用release仓库。
repositories {
maven {
url "https://repo.eclipse.org/content/repositories/paho-releases/"
}
}
在settings.gradle(Project Settings)的dependencyResolutionManagement内添加就行。
阿里云文档中第二个要添加的:在应用build.gradle中,添加Paho Android Service
dependencies {
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
}
在setting.gradle->dependencyResolutionManagement->repositories添加就行。
2.3、在AndroidMainfest.xml中声明服务和添加权限
声明以下服务:
<!-- Mqtt Service -->
<service android:name="org.eclipse.paho.android.service.MqttService">
</service>
具体位置在</activity>和</application>中间添加:
添加Paho MQTT Service所需的权限:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
具体位置在<application>之前:
注意,在高版本安卓系统中,需要添加:
android:usesCleartextTraffic="true"
高版本安卓的网络权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
如果编译器显示:“Landroid/support/v4/content/LocalBroadcastManager”等错误,记得在build.gradle(app)和gradle.properties中添加两行代码
/*build.gradle(app)中添加*/
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
/*gradle.properties中添加*/
/*#表示将依赖包也迁移到AndroidX,也就是阿里云的那个依赖包*/
android.enableJetifier=true
记得一定要把 targetSdk修改为<=30!!!
3、完整代码
public class MainActivity extends AppCompatActivity {
private final String TAG = "AiotMqtt";
/* 设备三元组信息 */
final private String PRODUCTKEY = "i2krG******";
final private String DEVICENAME = "MPU6050_Android";
final private String DEVICESECRET = "bf4bff7cc******b3f5**80******3ff";
final private String REGION_ID = "cn-shanghai";
/*获取手机IMEI号*/
String TelephonyIMEI="";
/* 自动Topic, 用于上报消息 */
final private String PUB_TOPIC = "/sys/" + PRODUCTKEY + "/" + DEVICENAME + "/thing/event/property/post";
/* 自动Topic, 用于接受消息 */
final private String SUB_TOPIC = "/sys/" + PRODUCTKEY + "/" + DEVICENAME + "/thing/service/property/set";
/*上报正文*/
private String BODY_FORMAT = "{\"id\":\""+TelephonyIMEI+"\",\"params\":{%s},\"version\":\"1.0\",\"method\":\"thing.event.property.post\"}";
/* 阿里云Mqtt服务器域名 */
final String host = "tcp://" + PRODUCTKEY + ".iot-as-mqtt." + REGION_ID + ".aliyuncs.com:1883"; //"tcp://" +
private String clientId;
private String userName;
private String passWord;
MqttAndroidClient mqttAndroidClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*获取手机IMEI号*/
TelephonyManager mTm = (TelephonyManager)this.getSystemService(TELEPHONY_SERVICE);
TelephonyIMEI = mTm.getDeviceId();
/* 获取MQTT连接信息clientId、username、password。 */
AiotMqttOption aiotMqttOption = new AiotMqttOption().getMqttOption(PRODUCTKEY, DEVICENAME, DEVICESECRET);
if (aiotMqttOption == null) {
Log.e(TAG, "device info error");
} else {
clientId = aiotMqttOption.getClientId();
userName = aiotMqttOption.getUsername();
passWord = aiotMqttOption.getPassword();
}
/* 创建MqttConnectOptions对象,并配置username和password。 */
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setUserName(userName);
mqttConnectOptions.setPassword(passWord.toCharArray());
/* 创建MqttAndroidClient对象,并设置回调接口。 */
mqttAndroidClient = new MqttAndroidClient(getApplicationContext(), host, clientId);
mqttAndroidClient.setCallback(new MqttCallback() {
@Override
public void connectionLost(Throwable cause) {
Log.i(TAG, "connection lost");
}
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
Log.i(TAG, "topic: " + topic + ", msg: " + new String(message.getPayload()));
//JSON解析
parseDiffJson(new String(message.getPayload()));
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
Log.i(TAG, "msg delivered");
}
});
/* 建立MQTT连接。 */
try {
mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.i(TAG, "connect succeed");
subscribeTopic(SUB_TOPIC);
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.i(TAG, "connect failed");
}
});
} catch (MqttException e) {
e.printStackTrace();
}
//此处为发送数据的部分,可能用不到,注意注释掉
Button OledOpen = findViewById(R.id.OledOpen);
OledOpen.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
publishMessage("\"CardID\":\"" + Old_Delete_CardID + "\"");
}
});
}
/*JSON解析*/
private void parseDiffJson(String json){
try {
//获取JSON数据中,字符串checkFailedData数据
JSONObject jsonObjectAll = new JSONObject(json);
String checkFailedData = jsonObjectAll.optString("items");
JSONObject jsonObject = new JSONObject(checkFailedData);
//解析传过来的数据,标识名(CardID)替换为自己的即可
/* try {
String SCardID = jsonObject.optString("CardID");
JSONObject json_card = new JSONObject(SCardID);
String asd = json_card.optString("value");
if(!TextUtils.isEmpty(asd))
{ CardID = asd; }
Log.i(TAG, "卡号: "+ CardID);
} catch (Exception e) {
}*/
}catch (Exception e){
}
}
/*
* 向默认的主题/user/update发布消息
* @param payload 消息载荷
*/
public void publishMessage(String payload2) {
try {
String payload = String.format(BODY_FORMAT,payload2);
if (mqttAndroidClient.isConnected() == false) {
mqttAndroidClient.connect();
}
MqttMessage message = new MqttMessage();
message.setPayload(payload.getBytes());
message.setQos(0);
mqttAndroidClient.publish(PUB_TOPIC, message,null, new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.i(TAG, "publish succeed!");
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.i(TAG, "publish failed!");
}
});
} catch (MqttException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
}
}
/*
* 订阅特定的主题
* @param topic mqtt主题
*/
public void subscribeTopic(String topic) {
try {
mqttAndroidClient.subscribe(topic, 0, null, new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.i(TAG, "subscribed succeed");
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.i(TAG, "subscribed failed");
}
});
} catch (MqttException e) {
e.printStackTrace();
}
}
/**
* MQTT建连选项类,输入设备三元组productKey, deviceName和deviceSecret, 生成Mqtt建连参数clientId,username和password.
*/
class AiotMqttOption {
private String username = "";
private String password = "";
private String clientId = "";
public String getUsername() { return this.username;}
public String getPassword() { return this.password;}
public String getClientId() { return this.clientId;}
/**
* 获取Mqtt建连选项对象
* @param productKey 产品秘钥
* @param deviceName 设备名称
* @param deviceSecret 设备机密
* @return AiotMqttOption对象或者NULL
*/
public AiotMqttOption getMqttOption(String productKey, String deviceName, String deviceSecret) {
if (productKey == null || deviceName == null || deviceSecret == null) {
return null;
}
try {
String timestamp = Long.toString(System.currentTimeMillis());
// clientId
this.clientId = TelephonyIMEI + "." + deviceName + "|timestamp=" + timestamp +
",_v=paho-android-1.0.0,securemode=2,signmethod=hmacsha256|";
// userName
this.username = deviceName + "&" + productKey;
// password
String macSrc = "clientId" + TelephonyIMEI + "." + deviceName + "deviceName" +
deviceName + "productKey" + productKey + "timestamp" + timestamp;
String algorithm = "HmacSHA256";
Mac mac = Mac.getInstance(algorithm);
SecretKeySpec secretKeySpec = new SecretKeySpec(deviceSecret.getBytes(), algorithm);
mac.init(secretKeySpec);
byte[] macRes = mac.doFinal(macSrc.getBytes());
password = String.format("%064x", new BigInteger(1, macRes));
} catch (Exception e) {
e.printStackTrace();
return null;
}
return this;
}
}
}
4、xml部分
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="陀螺仪检测系统测试程序"
android:textSize="30dp"
android:textStyle="italic|bold"/>
<LinearLayout
android:layout_marginTop="30dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="AX:"
android:textSize="30dp"
android:textColor="#000000"
/>
<TextView
android:id="@+id/ax"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="30dp"
android:gravity="center"
android:textColor="@color/white"
android:background="#3F51B5"
/>
</LinearLayout>
<LinearLayout
android:layout_marginTop="30dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="AY:"
android:textSize="30dp"
android:textColor="#000000"
/>
<TextView
android:id="@+id/ay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="30dp"
android:gravity="center"
android:textColor="@color/white"
android:background="#3F51B5"
/>
</LinearLayout>
<LinearLayout
android:layout_marginTop="30dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="AZ:"
android:textSize="30dp"
android:textColor="#000000"
/>
<TextView
android:id="@+id/az"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="30dp"
android:gravity="center"
android:textColor="@color/white"
android:background="#3F51B5"
/>
</LinearLayout>
<LinearLayout
android:layout_marginTop="30dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="GX:"
android:textSize="30dp"
android:textColor="#000000"
/>
<TextView
android:id="@+id/gx"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="30dp"
android:gravity="center"
android:textColor="@color/white"
android:background="#3F51B5"
/>
</LinearLayout>
<LinearLayout
android:layout_marginTop="30dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="GY:"
android:textSize="30dp"
android:textColor="#000000"
/>
<TextView
android:id="@+id/gy"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="30dp"
android:gravity="center"
android:textColor="@color/white"
android:background="#3F51B5"
/>
</LinearLayout>
<LinearLayout
android:layout_marginTop="30dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="GZ:"
android:textSize="30dp"
android:textColor="#000000"
/>
<TextView
android:id="@+id/gz"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="30dp"
android:gravity="center"
android:textColor="@color/white"
android:background="#3F51B5"
/>
</LinearLayout>
<LinearLayout
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="50dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
>
<Button
android:id="@+id/OledOpen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开灯"
android:textSize="30dp"
/>
<Button
android:layout_marginLeft="60dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/OledClose"
android:text="关灯"
android:textSize="30dp"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_marginEnd="50dp"/>
</LinearLayout>