当前位置:   article > 正文

物联网平台搭建的全过程介绍(五)——基于阿里云物联网平台的Android聊天app源码_基于阿里云物联网平台的android物联网软件框架

基于阿里云物联网平台的android物联网软件框架

本例程Android源码请点此处免费下载

物联网平台搭建的全过程介绍(四)两台设备之间通过云数据流转实现远程通信之Android studio例程中介绍了两台Android设备通过物联网平台进行通信的步骤;

可调颜色大小可加粗可设置段落自动滚到最后一行的TextView

中介绍了用两个按键模拟聊天界面的实现步骤。

那么下一步就把以上两部分内容结合起来,把两个按键中的一个“发送2”监听换成mqtt接收到消息的监听,接收另外一台设备数据流转过来的信息,并显示在TextView中。“发送1”按键监听中,除把发送内容显示在TextView之外,还要通过mqtt发送到物联网平台,然后流转到另外一台设备。这样就真正实现了类似微信、QQ聊天的即时通信app。本例还增加了登录界面和设置昵称的功能。

目录

一、界面设计

1、前台布局

2、layout代码

(1)登录界面activity_login.xml

(2)聊天界面activity_main.xml

(3)设置昵称settings.xml

二、java程序

1、工程文件目录图

 2、java文件

(1)AiotMqttOption.java

(2)登录loginActivity.java

(3)设置settingsActivity.java

(4)主程序聊天MainActivity.java

三、物联网数据流转解析器配置

1、产品功能定义

2、数据源

3、数据目的

4、解析器脚本

四、测试

1、聊天界面

 2、物联网平台接收数据

 五、本例今后需要改进的地方

1、登录的实用化改进

2、添加好友、建群功能的实现

3、阿里云物联网平台API的调用


一、界面设计

1、前台布局

登录界面

聊天界面

设置昵称界面

  

2、layout代码

(1)登录界面activity_login.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:background="@mipmap/back0"
  8. tools:context=".loginActivity">
  9. <LinearLayout
  10. android:layout_width="match_parent"
  11. android:layout_height="match_parent"
  12. android:layout_marginTop="50dp"
  13. android:orientation="vertical">
  14. <LinearLayout
  15. android:layout_width="match_parent"
  16. android:layout_height="50dp"
  17. android:layout_marginTop="10dp"
  18. android:gravity="center"
  19. android:orientation="horizontal">
  20. <ImageView
  21. android:id="@+id/pirlogo"
  22. android:layout_width="133dp"
  23. android:layout_height="54dp"
  24. app:layout_constraintTop_toTopOf="parent"
  25. app:layout_constraintHorizontal_bias="0.2"
  26. app:layout_constraintLeft_toLeftOf="parent"
  27. app:layout_constraintRight_toRightOf="parent"
  28. app:layout_constraintBottom_toBottomOf="parent"
  29. app:layout_constraintVertical_bias="0.25"
  30. android:src="@drawable/ic_stat_name"/>
  31. </LinearLayout>
  32. <LinearLayout
  33. android:layout_width="match_parent"
  34. android:layout_height="wrap_content"
  35. android:layout_marginTop="50dp"
  36. android:gravity="center"
  37. android:orientation="horizontal">
  38. <TextView
  39. android:layout_width="wrap_content"
  40. android:layout_height="wrap_content"
  41. android:textColor="@color/chocolate"
  42. android:gravity="center"
  43. android:textSize="25dp"
  44. android:text="我的聊聊"/>
  45. </LinearLayout>
  46. <LinearLayout
  47. android:layout_width="match_parent"
  48. android:layout_height="wrap_content"
  49. android:layout_marginTop="50dp"
  50. android:layout_marginLeft="20dp"
  51. android:layout_marginRight="20dp"
  52. android:orientation="horizontal">
  53. <TextView
  54. android:layout_width="0dp"
  55. android:layout_height="wrap_content"
  56. android:layout_weight="0.3"
  57. android:gravity="center"
  58. android:textColor="@color/forestgreen"
  59. android:textSize="18dp"
  60. android:text="用户名:"/>
  61. <EditText
  62. android:id="@+id/name"
  63. android:layout_width="0dp"
  64. android:layout_height="wrap_content"
  65. android:textColor="@color/black"
  66. android:layout_weight="1"
  67. />
  68. </LinearLayout>
  69. <LinearLayout
  70. android:layout_width="match_parent"
  71. android:layout_height="wrap_content"
  72. android:layout_marginTop="10dp"
  73. android:layout_marginLeft="20dp"
  74. android:layout_marginRight="20dp"
  75. android:orientation="horizontal">
  76. <TextView
  77. android:layout_width="0dp"
  78. android:layout_height="wrap_content"
  79. android:gravity="center"
  80. android:textSize="18dp"
  81. android:textColor="@color/forestgreen"
  82. android:layout_weight="0.3"
  83. android:text="密 码:"/>
  84. <EditText
  85. android:id="@+id/pwd"
  86. android:layout_width="0dp"
  87. android:layout_height="wrap_content"
  88. android:inputType="textPassword"
  89. android:textColor="@color/black"
  90. android:layout_weight="1"
  91. />
  92. </LinearLayout>
  93. <LinearLayout
  94. android:layout_width="match_parent"
  95. android:layout_height="wrap_content"
  96. android:layout_marginTop="10dp"
  97. android:layout_marginLeft="20dp"
  98. android:layout_marginRight="20dp"
  99. android:orientation="horizontal">
  100. <Button
  101. android:id="@+id/login"
  102. android:layout_width="wrap_content"
  103. android:layout_height="wrap_content"
  104. android:layout_weight="1"
  105. android:layout_margin="5dp"
  106. android:background="@drawable/button0"
  107. android:textColor="@color/black"
  108. android:text="@string/login"
  109. />
  110. <Button
  111. android:id="@+id/settings"
  112. android:layout_width="wrap_content"
  113. android:layout_height="wrap_content"
  114. android:layout_weight="1"
  115. android:layout_margin="5dp"
  116. android:background="@drawable/button0"
  117. android:textColor="@color/black"
  118. android:text="@string/settings"
  119. />
  120. </LinearLayout>
  121. </LinearLayout>
  122. </androidx.constraintlayout.widget.ConstraintLayout>

(2)聊天界面activity_main.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:background="@color/wechat_bottombar"
  8. tools:context=".MainActivity">
  9. <LinearLayout
  10. android:layout_width="match_parent"
  11. android:layout_height="match_parent"
  12. android:layout_marginLeft="0dp"
  13. android:layout_marginTop="0dp"
  14. android:layout_marginRight="0dp"
  15. android:background="@drawable/bg_stoke_4"
  16. android:layout_marginBottom="0dp"
  17. android:orientation="vertical">
  18. <LinearLayout
  19. android:layout_width="match_parent"
  20. android:layout_height="wrap_content"
  21. android:layout_marginLeft="0dp"
  22. android:layout_marginTop="0dp"
  23. android:layout_marginRight="0dp"
  24. android:background="@drawable/bg_stoke_4"
  25. android:layout_marginBottom="0dp"
  26. android:layout_weight="0"
  27. android:orientation="horizontal">
  28. <TextView
  29. android:id="@+id/tv_title"
  30. android:layout_width="match_parent"
  31. android:layout_height="wrap_content"
  32. android:scrollbars="vertical"
  33. android:background="@drawable/bg_stoke_4"
  34. android:layout_weight="1"
  35. android:textSize="16dp"
  36. android:typeface="sans"
  37. android:textColor="@color/black"
  38. android:textStyle="normal"
  39. android:padding="10dp"
  40. android:gravity="center"
  41. android:layout_marginLeft="10dp"
  42. android:layout_marginRight="10dp"
  43. app:layout_constraintBottom_toBottomOf="parent"
  44. app:layout_constraintLeft_toLeftOf="parent"
  45. app:layout_constraintRight_toRightOf="parent"
  46. app:layout_constraintTop_toTopOf="parent" />
  47. </LinearLayout>
  48. <LinearLayout
  49. android:layout_width="match_parent"
  50. android:layout_height="match_parent"
  51. android:layout_marginLeft="0dp"
  52. android:layout_marginTop="5dp"
  53. android:layout_marginRight="0dp"
  54. android:background="@drawable/bg_stoke_1"
  55. android:layout_marginBottom="0dp"
  56. android:layout_weight="1"
  57. android:orientation="horizontal">
  58. <ScrollView
  59. android:id="@+id/sv_chat"
  60. android:layout_width="fill_parent"
  61. android:layout_height="wrap_content"
  62. android:layout_marginTop="5dp"
  63. android:background="@drawable/bg_stoke_4"
  64. >
  65. <TextView
  66. android:id="@+id/tv_content"
  67. android:layout_width="match_parent"
  68. android:layout_height="wrap_content"
  69. android:scrollbars="vertical"
  70. android:background="@drawable/bg_stoke_4"
  71. android:focusable="true"
  72. android:layout_marginTop="5dp"
  73. android:layout_marginLeft="10dp"
  74. android:layout_marginRight="10dp"
  75. app:layout_constraintBottom_toBottomOf="parent"
  76. app:layout_constraintLeft_toLeftOf="parent"
  77. app:layout_constraintRight_toRightOf="parent"
  78. app:layout_constraintTop_toTopOf="parent" />
  79. </ScrollView>
  80. </LinearLayout>
  81. <LinearLayout
  82. android:layout_width="match_parent"
  83. android:layout_height="wrap_content"
  84. android:layout_marginLeft="0dp"
  85. android:layout_marginTop="0dp"
  86. android:layout_marginRight="0dp"
  87. android:background="@drawable/bg_stoke_3"
  88. android:layout_marginBottom="0dp"
  89. android:layout_weight="0"
  90. android:gravity="center"
  91. android:orientation="horizontal">
  92. <EditText
  93. android:id="@+id/et_send_content"
  94. android:layout_width="wrap_content"
  95. android:layout_height="wrap_content"
  96. android:background="@color/white"
  97. android:layout_marginLeft="10dp"
  98. android:layout_marginTop="0dp"
  99. android:layout_marginRight="10dp"
  100. android:layout_marginBottom="0dp"
  101. android:textSize="16dp"
  102. android:typeface="sans"
  103. android:textColor="@color/black"
  104. android:textStyle="normal"
  105. android:padding="8dp"
  106. android:layout_weight="1"
  107. />
  108. <Button
  109. android:id="@+id/btn_send"
  110. android:layout_width="wrap_content"
  111. android:layout_height="wrap_content"
  112. android:layout_margin="5dp"
  113. android:layout_marginBottom="0dp"
  114. android:layout_weight="0"
  115. app:layout_constraintBottom_toBottomOf="parent"
  116. app:layout_constraintRight_toRightOf="parent"
  117. android:background="@drawable/button0"
  118. android:text="@string/chat_send2"
  119. android:textSize="16dp"
  120. />
  121. </LinearLayout>
  122. </LinearLayout>
  123. </androidx.constraintlayout.widget.ConstraintLayout>

(3)设置昵称settings.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:background="@color/wechat_bottombar"
  8. tools:context=".settingsActivity">
  9. <LinearLayout
  10. android:layout_width="match_parent"
  11. android:layout_height="match_parent"
  12. android:layout_marginLeft="0dp"
  13. android:layout_marginTop="0dp"
  14. android:layout_marginRight="0dp"
  15. android:background="@drawable/bg_stoke_4"
  16. android:layout_marginBottom="0dp"
  17. android:orientation="vertical">
  18. <LinearLayout
  19. android:layout_width="match_parent"
  20. android:layout_height="wrap_content"
  21. android:layout_marginLeft="0dp"
  22. android:layout_marginTop="0dp"
  23. android:layout_marginRight="0dp"
  24. android:background="@drawable/bg_stoke_1"
  25. android:layout_marginBottom="0dp"
  26. android:layout_weight="0"
  27. android:orientation="horizontal">
  28. <TextView
  29. android:id="@+id/tv_setings_title"
  30. android:layout_width="match_parent"
  31. android:layout_height="wrap_content"
  32. android:scrollbars="vertical"
  33. android:background="@drawable/bg_stoke_4"
  34. android:layout_weight="1"
  35. android:textSize="16dp"
  36. android:typeface="sans"
  37. android:textColor="@color/black"
  38. android:textStyle="normal"
  39. android:padding="5dp"
  40. android:gravity="center"
  41. android:layout_marginTop="0dp"
  42. android:layout_marginLeft="10dp"
  43. android:layout_marginRight="10dp"
  44. app:layout_constraintBottom_toBottomOf="parent"
  45. app:layout_constraintLeft_toLeftOf="parent"
  46. app:layout_constraintRight_toRightOf="parent"
  47. app:layout_constraintTop_toTopOf="parent" />
  48. </LinearLayout>
  49. <LinearLayout
  50. android:layout_width="match_parent"
  51. android:layout_height="wrap_content"
  52. android:layout_marginLeft="0dp"
  53. android:layout_marginTop="100dp"
  54. android:layout_marginRight="0dp"
  55. android:background="@drawable/bg_stoke_4"
  56. android:layout_marginBottom="0dp"
  57. android:layout_weight="0"
  58. android:orientation="horizontal">
  59. <TextView
  60. android:layout_width="wrap_content"
  61. android:layout_height="wrap_content"
  62. android:scrollbars="vertical"
  63. android:background="@drawable/bg_stoke_4"
  64. android:layout_weight="1"
  65. android:textSize="16dp"
  66. android:typeface="sans"
  67. android:textColor="@color/black"
  68. android:textStyle="normal"
  69. android:padding="10dp"
  70. android:gravity="center"
  71. android:text="我的昵称:"
  72. android:layout_marginLeft="10dp"
  73. android:layout_marginRight="10dp"
  74. />
  75. <TextView
  76. android:id="@+id/tv_setings_nickname"
  77. android:layout_width="wrap_content"
  78. android:layout_height="wrap_content"
  79. android:gravity="center"
  80. android:textSize="18dp"
  81. android:textColor="@color/forestgreen"
  82. android:layout_weight="1"
  83. android:text="我的昵称"/>
  84. </LinearLayout>
  85. <LinearLayout
  86. android:layout_width="match_parent"
  87. android:layout_height="wrap_content"
  88. android:layout_marginLeft="0dp"
  89. android:layout_marginTop="10dp"
  90. android:layout_marginRight="0dp"
  91. android:background="@drawable/bg_stoke_4"
  92. android:layout_marginBottom="0dp"
  93. android:layout_weight="0"
  94. android:gravity="center"
  95. android:orientation="horizontal">
  96. <EditText
  97. android:id="@+id/et_settings_nickname"
  98. android:layout_width="wrap_content"
  99. android:layout_height="wrap_content"
  100. android:background="@color/white"
  101. android:layout_marginLeft="10dp"
  102. android:layout_marginTop="0dp"
  103. android:layout_marginRight="10dp"
  104. android:layout_marginBottom="0dp"
  105. android:textSize="16dp"
  106. android:typeface="sans"
  107. android:textColor="@color/black"
  108. android:textStyle="normal"
  109. android:padding="8dp"
  110. android:layout_weight="1"
  111. />
  112. <Button
  113. android:id="@+id/btn_set"
  114. android:layout_width="wrap_content"
  115. android:layout_height="wrap_content"
  116. android:layout_margin="5dp"
  117. android:layout_marginBottom="0dp"
  118. android:layout_weight="0"
  119. app:layout_constraintBottom_toBottomOf="parent"
  120. app:layout_constraintRight_toRightOf="parent"
  121. android:background="@drawable/button0"
  122. android:text="@string/btn_set"
  123. android:textSize="16dp"
  124. />
  125. </LinearLayout>
  126. </LinearLayout>
  127. </androidx.constraintlayout.widget.ConstraintLayout>

二、java程序

1、工程文件目录图

 2、java文件

(1)AiotMqttOption.java

  1. package com.example.myaliyunchat;
  2. import java.math.BigInteger;
  3. import javax.crypto.Mac;
  4. import javax.crypto.spec.SecretKeySpec;
  5. /**
  6. * MQTT建连选项类,输入设备三元组productKey, deviceName和deviceSecret, 生成Mqtt建连参数clientId,username和password.
  7. */
  8. class AiotMqttOption {
  9. private String username = "";
  10. private String password = "";
  11. private String clientId = "";
  12. String getUsername() { return this.username;}
  13. String getPassword() { return this.password;}
  14. String getClientId() { return this.clientId;}
  15. /**
  16. * 获取Mqtt建连选项对象
  17. * @param productKey 产品秘钥
  18. * @param deviceName 设备名称
  19. * @param deviceSecret 设备机密
  20. * @return AiotMqttOption对象或者NULL
  21. */
  22. public AiotMqttOption getMqttOption(String productKey, String deviceName, String deviceSecret) {
  23. if (productKey == null || deviceName == null || deviceSecret == null) {
  24. return null;
  25. }
  26. try {
  27. String timestamp = Long.toString(System.currentTimeMillis());
  28. // clientId
  29. this.clientId = productKey + "." + deviceName + "|timestamp=" + timestamp +
  30. ",_v=paho-android-1.0.0,securemode=2,signmethod=hmacsha256|";
  31. // userName
  32. this.username = deviceName + "&" + productKey;
  33. // password
  34. String macSrc = "clientId" + productKey + "." + deviceName + "deviceName" +
  35. deviceName + "productKey" + productKey + "timestamp" + timestamp;
  36. String algorithm = "HmacSHA256";
  37. Mac mac = Mac.getInstance(algorithm);
  38. SecretKeySpec secretKeySpec = new SecretKeySpec(deviceSecret.getBytes(), algorithm);
  39. mac.init(secretKeySpec);
  40. byte[] macRes = mac.doFinal(macSrc.getBytes());
  41. password = String.format("%064x", new BigInteger(1, macRes));
  42. } catch (Exception e) {
  43. e.printStackTrace();
  44. return null;
  45. }
  46. return this;
  47. }
  48. }

(2)登录loginActivity.java

  1. package com.example.myaliyunchat;
  2. import android.content.Intent;
  3. import android.content.SharedPreferences;
  4. import android.os.Bundle;
  5. import android.view.View;
  6. import android.widget.Button;
  7. import android.widget.EditText;
  8. import android.widget.Toast;
  9. import androidx.appcompat.app.AppCompatActivity;
  10. public class loginActivity extends AppCompatActivity {
  11. private EditText User_name,User_pwd;
  12. String loginer1="20220001";
  13. String loginer2="20220002";
  14. String Password1="123456";
  15. String Password2="654321";
  16. boolean check1;
  17. boolean check2;
  18. String str_name;
  19. String str_pwd;
  20. SharedPreferences sp_user;
  21. @Override
  22. protected void onCreate(Bundle savedInstanceState) {
  23. super.onCreate(savedInstanceState);
  24. setContentView(R.layout.activity_login);
  25. User_name = this.findViewById(R.id.name); //用户名输入框
  26. User_pwd = this.findViewById(R.id.pwd); //密码输入框
  27. Button btnlogin = this.findViewById(R.id.login); //登录按钮
  28. Button btn_set = this.findViewById(R.id.settings);
  29. sp_user=this.getSharedPreferences("sp_user",this.MODE_PRIVATE);
  30. User_name.setText(sp_user.getString("Name",null));
  31. User_pwd.setText(sp_user.getString("Password",null));
  32. btnlogin.setOnClickListener(new View.OnClickListener() {
  33. @Override
  34. public void onClick(View v) {
  35. SharedPreferences.Editor editor = sp_user.edit();
  36. str_name = User_name.getText().toString();
  37. str_pwd = User_pwd.getText().toString();
  38. check1=(str_name.equals(loginer1)) &&(str_pwd.equals(Password1));
  39. check2=(str_name.equals(loginer2)) &&(str_pwd.equals(Password2));
  40. if(check1 || check2)
  41. {
  42. editor.putString("Name", str_name);
  43. editor.putString("Password", str_pwd);
  44. editor.apply();
  45. Intent intent = new Intent(loginActivity.this, MainActivity.class);
  46. startActivity(intent);
  47. }
  48. else
  49. {
  50. User_name.setText("");
  51. User_pwd.setText("");
  52. Toast toast = Toast.makeText(loginActivity.this, getText(R.string.wrong_neme_or_psw), Toast.LENGTH_LONG);
  53. toast.show();
  54. }
  55. }
  56. });
  57. btn_set.setOnClickListener(new View.OnClickListener() {
  58. @Override
  59. public void onClick(View v) {
  60. Intent intent = new Intent(loginActivity.this, settingsActivity.class);
  61. startActivity(intent);
  62. }
  63. });
  64. }
  65. }

(3)设置settingsActivity.java

  1. package com.example.myaliyunchat;
  2. import android.content.SharedPreferences;
  3. import android.os.Bundle;
  4. import android.view.View;
  5. import android.widget.Button;
  6. import android.widget.EditText;
  7. import android.widget.TextView;
  8. import androidx.appcompat.app.AppCompatActivity;
  9. public class settingsActivity extends AppCompatActivity {
  10. private EditText et_nickname;
  11. TextView tv_title,tv_nickname;
  12. String str_nickname;
  13. SharedPreferences sp_user;//存放用户账号、密码、昵称信息
  14. @Override
  15. protected void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.settings);
  18. tv_title = this.findViewById(R.id.tv_setings_title);//标题栏
  19. et_nickname = this.findViewById(R.id.et_settings_nickname);//昵称输入框
  20. tv_nickname= this.findViewById(R.id.tv_setings_nickname);//昵称显示
  21. Button btn_set = this.findViewById(R.id.btn_set); //设置确认
  22. tv_title.setText(R.string.settings_title);
  23. sp_user=this.getSharedPreferences("sp_user",this.MODE_PRIVATE);
  24. tv_nickname.setText(sp_user.getString("nickname",null));
  25. btn_set.setOnClickListener(new View.OnClickListener() {
  26. @Override
  27. public void onClick(View v) {
  28. SharedPreferences.Editor editor = sp_user.edit();
  29. str_nickname = et_nickname.getText().toString();
  30. editor.putString("nickname", str_nickname);
  31. editor.apply();
  32. tv_nickname.setText(sp_user.getString("nickname",null));
  33. et_nickname.setText("");
  34. }
  35. });
  36. }
  37. }

(4)主程序聊天MainActivity.java

  1. package com.example.myaliyunchat;
  2. import androidx.appcompat.app.AppCompatActivity;
  3. import android.annotation.SuppressLint;
  4. import android.content.SharedPreferences;
  5. import android.os.Bundle;
  6. import android.text.Html;
  7. import android.util.Log;
  8. import android.view.View;
  9. import android.view.ViewTreeObserver;
  10. import android.widget.Button;
  11. import android.widget.EditText;
  12. import android.widget.ScrollView;
  13. import android.widget.TextView;
  14. import org.eclipse.paho.client.mqttv3.IMqttActionListener;
  15. import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
  16. import org.eclipse.paho.client.mqttv3.IMqttToken;
  17. import org.eclipse.paho.client.mqttv3.MqttCallback;
  18. import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
  19. import org.eclipse.paho.client.mqttv3.MqttException;
  20. import org.eclipse.paho.client.mqttv3.MqttMessage;
  21. import org.json.JSONException;
  22. import org.json.JSONObject;
  23. import org.eclipse.paho.android.service.MqttAndroidClient;
  24. import java.text.SimpleDateFormat;
  25. import java.util.Date;
  26. import java.util.Locale;
  27. import java.util.Objects;
  28. public class MainActivity extends AppCompatActivity {
  29. /* 设备三元组信息 */
  30. //20220002
  31. private String IotInstanceId="";
  32. private String PRODUCTKEY="";
  33. private String DEVICENAME="";
  34. private String DEVICESECRET="";
  35. //20221001
  36. private String PRODUCTKEY1="***********";
  37. private String DEVICENAME1="20220001";
  38. private String DEVICESECRET1="*********************************";
  39. //20220002
  40. private String PRODUCTKEY2="***********";
  41. private String DEVICENAME2="20220002";
  42. private String DEVICESECRET2="*********************************";
  43. String loginName;
  44. String NickName;
  45. String loginer1="20220001";
  46. String loginer2="20220002";
  47. //系统默认昵称
  48. String NickName1="曹操";
  49. String NickName2="刘备";
  50. /* 自动Topic, 用于上报消息 */
  51. private String PUB_TOPIC;
  52. /* 自动Topic, 用于接受消息 */
  53. private String SUB_TOPIC;
  54. /* 阿里云Mqtt服务器域名 */
  55. String host;
  56. /*Mqtt建连参数*/
  57. private String clientId;
  58. private String userName;
  59. private String passWord;
  60. //设置log.e的TAG
  61. private final String TAG = "AiotMqtt";
  62. MqttAndroidClient mqttAndroidClient;
  63. SharedPreferences sp_user;//存放用户账号、密码、昵称信息
  64. //ui相关变量
  65. TextView tv_content,tv_title;
  66. EditText et_send_content;
  67. Button btn_send;
  68. ScrollView scrollView;
  69. @SuppressLint("WrongViewCast")
  70. @Override
  71. protected void onCreate(Bundle savedInstanceState) {
  72. super.onCreate(savedInstanceState);
  73. setContentView(R.layout.activity_main);
  74. scrollView=this.findViewById(R.id.sv_chat);
  75. tv_content= this.findViewById(R.id.tv_content);
  76. tv_title= this.findViewById(R.id.tv_title);
  77. tv_content.setSelected(true);
  78. et_send_content=this.findViewById(R.id.et_send_content);
  79. tv_content.setTextSize(16);
  80. btn_send= findViewById(R.id.btn_send);
  81. sp_user=this.getSharedPreferences("sp_user",this.MODE_PRIVATE);
  82. loginName=sp_user.getString("Name",null);
  83. //根据登录账号的不同分别选择不同的阿里云三要素、昵称
  84. assert loginName != null;
  85. if(loginName.equals(loginer1))
  86. {
  87. PRODUCTKEY=PRODUCTKEY1;
  88. DEVICENAME=DEVICENAME1;
  89. DEVICESECRET=DEVICESECRET1;
  90. NickName=NickName1;
  91. }
  92. else if(loginName.equals(loginer2))
  93. {
  94. PRODUCTKEY=PRODUCTKEY2;
  95. DEVICENAME=DEVICENAME2;
  96. DEVICESECRET=DEVICESECRET2;
  97. NickName=NickName2;
  98. }
  99. else
  100. {
  101. PRODUCTKEY="";
  102. DEVICENAME="";
  103. DEVICESECRET="";
  104. NickName="";
  105. }
  106. if(Objects.requireNonNull(sp_user.getString("Name", null)).isEmpty())
  107. {
  108. if(loginName.equals(loginer1))
  109. {
  110. NickName=NickName1;
  111. }
  112. else if(loginName.equals(loginer2))
  113. {
  114. NickName=NickName2;
  115. }
  116. else
  117. {
  118. NickName="";
  119. }
  120. SharedPreferences.Editor editor = sp_user.edit();
  121. editor.putString("nickname", NickName);
  122. editor.apply();
  123. }
  124. NickName=sp_user.getString("nickname",null);
  125. //根据阿里云三要素构建subtopic、pubtopic、host
  126. AliyunTopicHostSet(0);
  127. //MQTT建连选项类,输入设备三元组productKey, deviceName和deviceSecret, 生成Mqtt建连参数clientId,username和password
  128. AiotMqttOption aiotMqttOption = new AiotMqttOption().getMqttOption(PRODUCTKEY, DEVICENAME, DEVICESECRET);
  129. if (aiotMqttOption == null) {
  130. Log.e(TAG, "device info error");
  131. } else {
  132. clientId = aiotMqttOption.getClientId();
  133. userName = aiotMqttOption.getUsername();
  134. passWord = aiotMqttOption.getPassword();
  135. }
  136. /* Mqtt建连 */
  137. try {
  138. /* 创建MqttConnectOptions对象并配置username和password */
  139. final MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
  140. mqttConnectOptions.setUserName(userName);
  141. mqttConnectOptions.setPassword(passWord.toCharArray());
  142. /* 创建MqttAndroidClient对象, 并设置回调接口 */
  143. //String plstring;
  144. mqttAndroidClient = new MqttAndroidClient(getApplicationContext(), host, clientId);
  145. mqttAndroidClient.connect(mqttConnectOptions,null, new IMqttActionListener() {
  146. //连接成功方法
  147. @Override
  148. public void onSuccess(IMqttToken asyncActionToken) {
  149. Log.i(TAG, "connect succeed");
  150. subscribeTopic(SUB_TOPIC);
  151. }
  152. //连接失败方法
  153. @Override
  154. public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
  155. Log.i(TAG, "connect failed");
  156. }
  157. });
  158. } catch (MqttException e) {
  159. e.printStackTrace();
  160. }
  161. /**
  162. * mqtt回调类,此类内包含三个方法:connectionLost(掉线),messageArrived(订阅消息到达),deliveryComplete(发布消息送达)
  163. */
  164. mqttAndroidClient.setCallback(new MqttCallback() {
  165. //连接中断方法
  166. @Override
  167. public void connectionLost(Throwable cause) {
  168. Log.i(TAG, "connection lost");
  169. }
  170. @SuppressLint("SetTextI18n")
  171. @Override
  172. //订阅消息后,消息到达时方法
  173. public void messageArrived(String topic, MqttMessage message) throws Exception {
  174. Log.i(TAG, "topic: " + topic + ", msg: " + new String(message.getPayload()));
  175. String payload = new String(message.getPayload());
  176. // JSONObject Jobj_payload = new JSONObject(payload);
  177. // JSONObject Jobj_params=new JSONObject(Jobj_payload.getString("params"));
  178. JSONObject Jobj_params = new JSONObject(payload);
  179. String chat_user=Jobj_params.getString("user");
  180. String char_message=Jobj_params.getString("message");
  181. Date curDate = new Date(System.currentTimeMillis());
  182. SimpleDateFormat format= new SimpleDateFormat("M月d日 HH:mm", Locale.getDefault());
  183. String str_curDate = format.format(curDate);
  184. tv_content.append( Html.fromHtml("<font color='#696969' size='5'>"+chat_user +"("+str_curDate+"):"+"</font>"+"<br>"));
  185. tv_content.append( Html.fromHtml("<p><font color='#D2691E' size='5'>"+char_message+"</font><p>"+"<br>"));
  186. tv_title.setText(chat_user);
  187. }// messageArrived类结束标志
  188. //发布消息后,消息投递成功后返回方法
  189. @Override
  190. public void deliveryComplete(IMqttDeliveryToken token) {
  191. Log.i(TAG, "msg delivered");
  192. }
  193. });//mqttAndroidClient.setCallback类结束标志
  194. /**
  195. * 点"上传"按钮后,将数学、语文分数发送到阿里云物联网平台
  196. */
  197. btn_send.setOnClickListener((view)-> {
  198. String send_content=et_send_content.getText().toString();
  199. Date curDate = new Date(System.currentTimeMillis());
  200. SimpleDateFormat format= new SimpleDateFormat("M月d日 HH:mm", Locale.getDefault());
  201. String str_curDate = format.format(curDate);
  202. tv_content.append( Html.fromHtml("<font color='#696969' size='10'>"+NickName+"("+str_curDate+"):"+"</font>"+"<br>"));
  203. tv_content.append( Html.fromHtml("<p><font color='#3CB371' size='10'>"+send_content+"</font><p>"+"<br>"));
  204. et_send_content.setText("");
  205. //发布消息的payload数据包生成方法一:利用JSONObject,分两层将params内的数学、语文分数,和params外的id,version打成一个json数据包
  206. JSONObject Jobj_payload = new JSONObject();
  207. JSONObject Jobj_params = new JSONObject();
  208. try {
  209. Jobj_params.put("message",send_content);
  210. Jobj_params.put("user_id",NickName);
  211. Jobj_payload.put("id", DEVICENAME);
  212. Jobj_payload.put("version", "1.0");
  213. Jobj_payload.put("params", Jobj_params);
  214. } catch (JSONException e) {
  215. e.printStackTrace();
  216. }
  217. publishMessage(Jobj_payload.toString());
  218. et_send_content.setText("");
  219. // scrollView.fullScroll(ScrollView.FOCUS_DOWN);
  220. });
  221. scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
  222. @Override
  223. public void onGlobalLayout() {
  224. scrollView.post(new Runnable() {
  225. public void run() {
  226. scrollView.fullScroll(View.FOCUS_DOWN);
  227. }
  228. });
  229. }
  230. });
  231. }//oncreat结束标志
  232. /**
  233. * 设置阿里云物联网平台参数
  234. * @param IotInstanceType 实例类型,0:华东2(上海)服务器公共实例;1:企业实例
  235. */
  236. public void AliyunTopicHostSet(int IotInstanceType) {
  237. SUB_TOPIC ="/sys/" + PRODUCTKEY + "/" + DEVICENAME + "/thing/service/property/set";
  238. PUB_TOPIC = "/sys/" + PRODUCTKEY + "/" + DEVICENAME + "/thing/event/property/post";
  239. if(IotInstanceType==0)
  240. {
  241. host="tcp://" + PRODUCTKEY + ".iot-as-mqtt.cn-shanghai.aliyuncs.com:1883";//适用于公共实例华东2(上海)
  242. }
  243. else
  244. {
  245. host="tcp://" + IotInstanceId + ".mqtt.iothub.aliyuncs.com:1883";//试用于企业实例
  246. }
  247. }
  248. /**
  249. * 订阅特定的主题
  250. * @param topic mqtt主题
  251. */
  252. public void subscribeTopic(String topic) {
  253. try {
  254. mqttAndroidClient.subscribe(topic, 0, null, new IMqttActionListener() {
  255. @Override
  256. public void onSuccess(IMqttToken asyncActionToken) {
  257. Log.i(TAG, "subscribed succeed");
  258. }
  259. @Override
  260. public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
  261. Log.i(TAG, "subscribed failed");
  262. }
  263. });
  264. } catch (MqttException e) {
  265. e.printStackTrace();
  266. }
  267. }
  268. /**
  269. * 向默认的主题/user/update发布消息
  270. * @param payload 消息载荷
  271. */
  272. public void publishMessage(String payload) {
  273. try {
  274. if (!mqttAndroidClient.isConnected()) {
  275. mqttAndroidClient.connect();
  276. }
  277. MqttMessage message = new MqttMessage();
  278. message.setPayload(payload.getBytes());
  279. message.setQos(0);
  280. mqttAndroidClient.publish(PUB_TOPIC, message,null, new IMqttActionListener() {
  281. @Override
  282. public void onSuccess(IMqttToken asyncActionToken) {
  283. Log.i(TAG, "publish succeed!");
  284. }
  285. @Override
  286. public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
  287. Log.i(TAG, "publish failed!");
  288. }
  289. });
  290. } catch (MqttException e) {
  291. Log.e(TAG, e.toString());
  292. e.printStackTrace();
  293. }
  294. }
  295. }

三、物联网数据流转解析器配置

1、产品功能定义

产品名称:我的聊聊,在该产品下创建两个设备:20220001和20220002

2、数据源

3、数据目的

4、解析器脚本

  1. var data = payload("json");
  2. var select = {};
  3. select.put("message", getOrNull(data,"items","message","value"));
  4. select.put("user", getOrNull(data,"items","user_id","value"));
  5. if(deviceName()=="20220001")
  6. {
  7. writeIotTopic(1003, "/sys/***********/20220002/thing/service/property/set", select);
  8. }
  9. if(deviceName()=="20220002")
  10. {
  11. writeIotTopic(1003, "/sys/***********/20220001/thing/service/property/set", select);

因为数据源选择的是全部设备,所以20220001和20220002上传的数据都会流转到解析器来,所以在脚本中,要控制设备上传的数据不转发自己本身,只转发给另外一个用户。

四、测试

1、聊天界面

刘备端截图1

刘备端截图2

 2、物联网平台接收数据

曹操端上传数据

曹操端“聊天消息”记录

 五、本例今后需要改进的地方

1、登录的实用化改进

本例“我的聊聊”app两个登录账号以及两组阿里云物联网平台的三要素都是固定存在app内的,实际聊天工具应该把“我的聊聊”登录账号、密码、昵称以及对应的阿里云三要素存放到云服务器或者云数据库内。首先要访问数据库或者服务器web页面,验证账号和密码,通过之后,再从数据库中取出昵称、阿里云三要素,然后再使用这组三要素连接物联网平台,完成接入、订阅和发布的功能。

2、添加好友、建群功能的实现

本例只是实现了一对一聊天的基本功能,更加实用的聊天工具需要可以添加好友、建群,可以选择不同好友进行一对一聊天,可以群聊。这些功能需要app端相应功能,还要配合解析器脚本的合理化设计。

3、阿里云物联网平台API的调用

本例物联网平台设备的创建和云数据流转都是通过手工进行的,实际的项目需要能在app端调用API来自动创建。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/600627
推荐阅读
相关标签
  

闽ICP备14008679号