本例程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

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"android:background="@mipmap/back0"tools:context=".loginActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginTop="50dp"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="50dp"android:layout_marginTop="10dp"android:gravity="center"android:orientation="horizontal"><ImageViewandroid:id="@+id/pirlogo"android:layout_width="133dp"android:layout_height="54dp"app:layout_constraintTop_toTopOf="parent"app:layout_constraintHorizontal_bias="0.2"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintVertical_bias="0.25"android:src="@drawable/ic_stat_name"/></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="50dp"android:gravity="center"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="@color/chocolate"android:gravity="center"android:textSize="25dp"android:text="我的聊聊"/></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="50dp"android:layout_marginLeft="20dp"android:layout_marginRight="20dp"android:orientation="horizontal"><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="0.3"android:gravity="center"android:textColor="@color/forestgreen"android:textSize="18dp"android:text="用户名:"/><EditTextandroid:id="@+id/name"android:layout_width="0dp"android:layout_height="wrap_content"android:textColor="@color/black"android:layout_weight="1"/></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:layout_marginLeft="20dp"android:layout_marginRight="20dp"android:orientation="horizontal"><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:gravity="center"android:textSize="18dp"android:textColor="@color/forestgreen"android:layout_weight="0.3"android:text="密    码:"/><EditTextandroid:id="@+id/pwd"android:layout_width="0dp"android:layout_height="wrap_content"android:inputType="textPassword"android:textColor="@color/black"android:layout_weight="1"/></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:layout_marginLeft="20dp"android:layout_marginRight="20dp"android:orientation="horizontal"><Buttonandroid:id="@+id/login"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:layout_margin="5dp"android:background="@drawable/button0"android:textColor="@color/black"android:text="@string/login"/><Buttonandroid:id="@+id/settings"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:layout_margin="5dp"android:background="@drawable/button0"android:textColor="@color/black"android:text="@string/settings"/></LinearLayout></LinearLayout></androidx.constraintlayout.widget.ConstraintLayout>

(2)聊天界面activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"android:background="@color/wechat_bottombar"tools:context=".MainActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginLeft="0dp"android:layout_marginTop="0dp"android:layout_marginRight="0dp"android:background="@drawable/bg_stoke_4"android:layout_marginBottom="0dp"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="0dp"android:layout_marginTop="0dp"android:layout_marginRight="0dp"android:background="@drawable/bg_stoke_4"android:layout_marginBottom="0dp"android:layout_weight="0"android:orientation="horizontal"><TextViewandroid:id="@+id/tv_title"android:layout_width="match_parent"android:layout_height="wrap_content"android:scrollbars="vertical"android:background="@drawable/bg_stoke_4"android:layout_weight="1"android:textSize="16dp"android:typeface="sans"android:textColor="@color/black"android:textStyle="normal"android:padding="10dp"android:gravity="center"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginLeft="0dp"android:layout_marginTop="5dp"android:layout_marginRight="0dp"android:background="@drawable/bg_stoke_1"android:layout_marginBottom="0dp"android:layout_weight="1"android:orientation="horizontal"><ScrollViewandroid:id="@+id/sv_chat"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_marginTop="5dp"android:background="@drawable/bg_stoke_4"><TextViewandroid:id="@+id/tv_content"android:layout_width="match_parent"android:layout_height="wrap_content"android:scrollbars="vertical"android:background="@drawable/bg_stoke_4"android:focusable="true"android:layout_marginTop="5dp"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /></ScrollView></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="0dp"android:layout_marginTop="0dp"android:layout_marginRight="0dp"android:background="@drawable/bg_stoke_3"android:layout_marginBottom="0dp"android:layout_weight="0"android:gravity="center"android:orientation="horizontal"><EditTextandroid:id="@+id/et_send_content"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/white"android:layout_marginLeft="10dp"android:layout_marginTop="0dp"android:layout_marginRight="10dp"android:layout_marginBottom="0dp"android:textSize="16dp"android:typeface="sans"android:textColor="@color/black"android:textStyle="normal"android:padding="8dp"android:layout_weight="1"/><Buttonandroid:id="@+id/btn_send"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="5dp"android:layout_marginBottom="0dp"android:layout_weight="0"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintRight_toRightOf="parent"android:background="@drawable/button0"android:text="@string/chat_send2"android:textSize="16dp"/></LinearLayout></LinearLayout></androidx.constraintlayout.widget.ConstraintLayout>

(3)设置昵称settings.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"android:background="@color/wechat_bottombar"tools:context=".settingsActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginLeft="0dp"android:layout_marginTop="0dp"android:layout_marginRight="0dp"android:background="@drawable/bg_stoke_4"android:layout_marginBottom="0dp"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="0dp"android:layout_marginTop="0dp"android:layout_marginRight="0dp"android:background="@drawable/bg_stoke_1"android:layout_marginBottom="0dp"android:layout_weight="0"android:orientation="horizontal"><TextViewandroid:id="@+id/tv_setings_title"android:layout_width="match_parent"android:layout_height="wrap_content"android:scrollbars="vertical"android:background="@drawable/bg_stoke_4"android:layout_weight="1"android:textSize="16dp"android:typeface="sans"android:textColor="@color/black"android:textStyle="normal"android:padding="5dp"android:gravity="center"android:layout_marginTop="0dp"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="0dp"android:layout_marginTop="100dp"android:layout_marginRight="0dp"android:background="@drawable/bg_stoke_4"android:layout_marginBottom="0dp"android:layout_weight="0"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:scrollbars="vertical"android:background="@drawable/bg_stoke_4"android:layout_weight="1"android:textSize="16dp"android:typeface="sans"android:textColor="@color/black"android:textStyle="normal"android:padding="10dp"android:gravity="center"android:text="我的昵称:"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"/><TextViewandroid:id="@+id/tv_setings_nickname"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:textSize="18dp"android:textColor="@color/forestgreen"android:layout_weight="1"android:text="我的昵称"/></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="0dp"android:layout_marginTop="10dp"android:layout_marginRight="0dp"android:background="@drawable/bg_stoke_4"android:layout_marginBottom="0dp"android:layout_weight="0"android:gravity="center"android:orientation="horizontal"><EditTextandroid:id="@+id/et_settings_nickname"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/white"android:layout_marginLeft="10dp"android:layout_marginTop="0dp"android:layout_marginRight="10dp"android:layout_marginBottom="0dp"android:textSize="16dp"android:typeface="sans"android:textColor="@color/black"android:textStyle="normal"android:padding="8dp"android:layout_weight="1"/><Buttonandroid:id="@+id/btn_set"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="5dp"android:layout_marginBottom="0dp"android:layout_weight="0"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintRight_toRightOf="parent"android:background="@drawable/button0"android:text="@string/btn_set"android:textSize="16dp"/></LinearLayout></LinearLayout></androidx.constraintlayout.widget.ConstraintLayout>

二、java程序

1、工程文件目录图

2、java文件

(1)AiotMqttOption.java

package com.example.myaliyunchat;import java.math.BigInteger;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;/*** MQTT建连选项类,输入设备三元组productKey, deviceName和deviceSecret, 生成Mqtt建连参数clientId,username和password.*/
class AiotMqttOption {private String username = "";private String password = "";private String clientId = "";String getUsername() { return this.username;}String getPassword() { return this.password;}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());// clientIdthis.clientId = productKey + "." + deviceName + "|timestamp=" + timestamp +",_v=paho-android-1.0.0,securemode=2,signmethod=hmacsha256|";// userNamethis.username = deviceName + "&" + productKey;// passwordString macSrc = "clientId" + productKey + "." + 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;}
}

(2)登录loginActivity.java

package com.example.myaliyunchat;import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class loginActivity extends AppCompatActivity {private EditText User_name,User_pwd;String loginer1="20220001";String loginer2="20220002";String Password1="123456";String Password2="654321";boolean check1;boolean check2;String str_name;String str_pwd;SharedPreferences sp_user;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login);User_name = this.findViewById(R.id.name);            //用户名输入框User_pwd = this.findViewById(R.id.pwd);              //密码输入框Button btnlogin = this.findViewById(R.id.login);         //登录按钮Button btn_set = this.findViewById(R.id.settings);sp_user=this.getSharedPreferences("sp_user",this.MODE_PRIVATE);User_name.setText(sp_user.getString("Name",null));User_pwd.setText(sp_user.getString("Password",null));btnlogin.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {SharedPreferences.Editor editor = sp_user.edit();str_name = User_name.getText().toString();str_pwd = User_pwd.getText().toString();check1=(str_name.equals(loginer1)) &&(str_pwd.equals(Password1));check2=(str_name.equals(loginer2)) &&(str_pwd.equals(Password2));if(check1 || check2){editor.putString("Name", str_name);editor.putString("Password", str_pwd);editor.apply();Intent intent = new Intent(loginActivity.this, MainActivity.class);startActivity(intent);}else{User_name.setText("");User_pwd.setText("");Toast toast = Toast.makeText(loginActivity.this, getText(R.string.wrong_neme_or_psw), Toast.LENGTH_LONG);toast.show();}}});btn_set.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent(loginActivity.this, settingsActivity.class);startActivity(intent);}});}}

(3)设置settingsActivity.java

package com.example.myaliyunchat;import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;public class settingsActivity extends AppCompatActivity {private EditText et_nickname;TextView tv_title,tv_nickname;String str_nickname;SharedPreferences sp_user;//存放用户账号、密码、昵称信息@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.settings);tv_title = this.findViewById(R.id.tv_setings_title);//标题栏et_nickname = this.findViewById(R.id.et_settings_nickname);//昵称输入框tv_nickname= this.findViewById(R.id.tv_setings_nickname);//昵称显示Button btn_set = this.findViewById(R.id.btn_set);         //设置确认tv_title.setText(R.string.settings_title);sp_user=this.getSharedPreferences("sp_user",this.MODE_PRIVATE);tv_nickname.setText(sp_user.getString("nickname",null));btn_set.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {SharedPreferences.Editor editor = sp_user.edit();str_nickname = et_nickname.getText().toString();editor.putString("nickname", str_nickname);editor.apply();tv_nickname.setText(sp_user.getString("nickname",null));et_nickname.setText("");}});}}

(4)主程序聊天MainActivity.java

package com.example.myaliyunchat;import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.TextView;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.json.JSONException;
import org.json.JSONObject;
import org.eclipse.paho.android.service.MqttAndroidClient;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Objects;public class MainActivity extends AppCompatActivity {/* 设备三元组信息 *///20220002private String IotInstanceId="";private String PRODUCTKEY="";private String DEVICENAME="";private String DEVICESECRET="";//20221001private String PRODUCTKEY1="***********";private String DEVICENAME1="20220001";private String DEVICESECRET1="*********************************";//20220002private String PRODUCTKEY2="***********";private String DEVICENAME2="20220002";private String DEVICESECRET2="*********************************";String loginName;String NickName;String loginer1="20220001";String loginer2="20220002";//系统默认昵称String NickName1="曹操";String NickName2="刘备";/* 自动Topic, 用于上报消息 */private String PUB_TOPIC;/* 自动Topic, 用于接受消息 */private String SUB_TOPIC;/* 阿里云Mqtt服务器域名 */String host;/*Mqtt建连参数*/private String clientId;private String userName;private String passWord;//设置log.e的TAGprivate final String TAG = "AiotMqtt";MqttAndroidClient mqttAndroidClient;SharedPreferences sp_user;//存放用户账号、密码、昵称信息//ui相关变量TextView tv_content,tv_title;EditText et_send_content;Button btn_send;ScrollView scrollView;@SuppressLint("WrongViewCast")@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);scrollView=this.findViewById(R.id.sv_chat);tv_content= this.findViewById(R.id.tv_content);tv_title= this.findViewById(R.id.tv_title);tv_content.setSelected(true);et_send_content=this.findViewById(R.id.et_send_content);tv_content.setTextSize(16);btn_send= findViewById(R.id.btn_send);sp_user=this.getSharedPreferences("sp_user",this.MODE_PRIVATE);loginName=sp_user.getString("Name",null);//根据登录账号的不同分别选择不同的阿里云三要素、昵称assert loginName != null;if(loginName.equals(loginer1)){PRODUCTKEY=PRODUCTKEY1;DEVICENAME=DEVICENAME1;DEVICESECRET=DEVICESECRET1;NickName=NickName1;}else if(loginName.equals(loginer2)){PRODUCTKEY=PRODUCTKEY2;DEVICENAME=DEVICENAME2;DEVICESECRET=DEVICESECRET2;NickName=NickName2;}else{PRODUCTKEY="";DEVICENAME="";DEVICESECRET="";NickName="";}if(Objects.requireNonNull(sp_user.getString("Name", null)).isEmpty()){if(loginName.equals(loginer1)){NickName=NickName1;}else if(loginName.equals(loginer2)){NickName=NickName2;}else{NickName="";}SharedPreferences.Editor editor = sp_user.edit();editor.putString("nickname", NickName);editor.apply();}NickName=sp_user.getString("nickname",null);//根据阿里云三要素构建subtopic、pubtopic、hostAliyunTopicHostSet(0);//MQTT建连选项类,输入设备三元组productKey, deviceName和deviceSecret, 生成Mqtt建连参数clientId,username和passwordAiotMqttOption 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();}/* Mqtt建连 */try {/* 创建MqttConnectOptions对象并配置username和password */final MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();mqttConnectOptions.setUserName(userName);mqttConnectOptions.setPassword(passWord.toCharArray());/* 创建MqttAndroidClient对象, 并设置回调接口 *///String plstring;mqttAndroidClient = new MqttAndroidClient(getApplicationContext(), host, clientId);mqttAndroidClient.connect(mqttConnectOptions,null, new IMqttActionListener() {//连接成功方法@Overridepublic void onSuccess(IMqttToken asyncActionToken) {Log.i(TAG, "connect succeed");subscribeTopic(SUB_TOPIC);}//连接失败方法@Overridepublic void onFailure(IMqttToken asyncActionToken, Throwable exception) {Log.i(TAG, "connect failed");}});} catch (MqttException e) {e.printStackTrace();}/*** mqtt回调类,此类内包含三个方法:connectionLost(掉线),messageArrived(订阅消息到达),deliveryComplete(发布消息送达)*/mqttAndroidClient.setCallback(new MqttCallback() {//连接中断方法@Overridepublic void connectionLost(Throwable cause) {Log.i(TAG, "connection lost");}@SuppressLint("SetTextI18n")@Override//订阅消息后,消息到达时方法public void messageArrived(String topic, MqttMessage message) throws Exception {Log.i(TAG, "topic: " + topic + ", msg: " + new String(message.getPayload()));String payload = new String(message.getPayload());
//                JSONObject Jobj_payload = new JSONObject(payload);
//                JSONObject Jobj_params=new JSONObject(Jobj_payload.getString("params"));JSONObject Jobj_params = new JSONObject(payload);String chat_user=Jobj_params.getString("user");String char_message=Jobj_params.getString("message");Date curDate = new Date(System.currentTimeMillis());SimpleDateFormat format= new SimpleDateFormat("M月d日 HH:mm", Locale.getDefault());String str_curDate = format.format(curDate);tv_content.append( Html.fromHtml("<font color='#696969' size='5'>"+chat_user +"("+str_curDate+"):"+"</font>"+"<br>"));tv_content.append( Html.fromHtml("<p><font color='#D2691E' size='5'>"+char_message+"</font><p>"+"<br>"));tv_title.setText(chat_user);}// messageArrived类结束标志//发布消息后,消息投递成功后返回方法@Overridepublic void deliveryComplete(IMqttDeliveryToken token) {Log.i(TAG, "msg delivered");}});//mqttAndroidClient.setCallback类结束标志/*** 点"上传"按钮后,将数学、语文分数发送到阿里云物联网平台*/btn_send.setOnClickListener((view)-> {String send_content=et_send_content.getText().toString();Date curDate = new Date(System.currentTimeMillis());SimpleDateFormat format= new SimpleDateFormat("M月d日 HH:mm", Locale.getDefault());String str_curDate = format.format(curDate);tv_content.append( Html.fromHtml("<font color='#696969' size='10'>"+NickName+"("+str_curDate+"):"+"</font>"+"<br>"));tv_content.append( Html.fromHtml("<p><font color='#3CB371' size='10'>"+send_content+"</font><p>"+"<br>"));et_send_content.setText("");//发布消息的payload数据包生成方法一:利用JSONObject,分两层将params内的数学、语文分数,和params外的id,version打成一个json数据包JSONObject Jobj_payload = new JSONObject();JSONObject Jobj_params = new JSONObject();try {Jobj_params.put("message",send_content);Jobj_params.put("user_id",NickName);Jobj_payload.put("id", DEVICENAME);Jobj_payload.put("version", "1.0");Jobj_payload.put("params", Jobj_params);} catch (JSONException e) {e.printStackTrace();}publishMessage(Jobj_payload.toString());et_send_content.setText("");
//            scrollView.fullScroll(ScrollView.FOCUS_DOWN);});scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {scrollView.post(new Runnable() {public void run() {scrollView.fullScroll(View.FOCUS_DOWN);}});}});}//oncreat结束标志/*** 设置阿里云物联网平台参数* @param IotInstanceType 实例类型,0:华东2(上海)服务器公共实例;1:企业实例*/public void AliyunTopicHostSet(int IotInstanceType) {SUB_TOPIC ="/sys/" + PRODUCTKEY + "/" + DEVICENAME + "/thing/service/property/set";PUB_TOPIC = "/sys/" + PRODUCTKEY + "/" + DEVICENAME + "/thing/event/property/post";if(IotInstanceType==0){host="tcp://" + PRODUCTKEY + ".iot-as-mqtt.cn-shanghai.aliyuncs.com:1883";//适用于公共实例华东2(上海)}else{host="tcp://" + IotInstanceId + ".mqtt.iothub.aliyuncs.com:1883";//试用于企业实例}}/*** 订阅特定的主题* @param topic mqtt主题*/public void subscribeTopic(String topic) {try {mqttAndroidClient.subscribe(topic, 0, null, new IMqttActionListener() {@Overridepublic void onSuccess(IMqttToken asyncActionToken) {Log.i(TAG, "subscribed succeed");}@Overridepublic void onFailure(IMqttToken asyncActionToken, Throwable exception) {Log.i(TAG, "subscribed failed");}});} catch (MqttException e) {e.printStackTrace();}}/*** 向默认的主题/user/update发布消息* @param payload 消息载荷*/public void publishMessage(String payload) {try {if (!mqttAndroidClient.isConnected()) {mqttAndroidClient.connect();}MqttMessage message = new MqttMessage();message.setPayload(payload.getBytes());message.setQos(0);mqttAndroidClient.publish(PUB_TOPIC, message,null, new IMqttActionListener() {@Overridepublic void onSuccess(IMqttToken asyncActionToken) {Log.i(TAG, "publish succeed!");}@Overridepublic void onFailure(IMqttToken asyncActionToken, Throwable exception) {Log.i(TAG, "publish failed!");}});} catch (MqttException e) {Log.e(TAG, e.toString());e.printStackTrace();}}
}

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

1、产品功能定义

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

2、数据源

3、数据目的

4、解析器脚本

var data = payload("json");var select = {};select.put("message", getOrNull(data,"items","message","value"));
select.put("user", getOrNull(data,"items","user_id","value"));if(deviceName()=="20220001")
{
writeIotTopic(1003, "/sys/***********/20220002/thing/service/property/set", select);
}if(deviceName()=="20220002")
{
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来自动创建。

物联网平台搭建的全过程介绍(五)——基于阿里云物联网平台的Android聊天app源码相关推荐

  1. 基于阿里云物联网的无人值守远程农业智慧盒DIY之(一)总体设计

    已更新的文章传送门 基于阿里云物联网的无人值守远程农业智慧盒DIY之(二)太阳能-蓄电池板的树莓派供电系统. 基于阿里云物联网的无人值守远程农业智慧盒DIY之(三)arduino土壤湿度监测短信平台. ...

  2. 基于阿里云物联网的无人值守远程农业智慧盒DIY之(二)太阳能-蓄电池板的树莓派供电系统。

    继续(一)总体设计的思路,进行太阳能供电系统的设计.https://iotmaker.blog.csdn.net/article/details/125244134?spm=1001.2014.300 ...

  3. 物联网平台搭建的全过程介绍(七)——本地数据批量上传阿里云物联网实例内TSDB

    在文章物联网平台搭建的全过程介绍(六)--物联网TSDB之基本知识及读写代码介绍中介绍了TSDB基础知识和读取和写入数据的基本操作.但在该文中只给出了单条数据写入的代码. 那么假如有这样一种情况,我物 ...

  4. 基于阿里云物联网平台的设备之间传输十六进制数据

    基于阿里云物联网平台的设备之间传输十六进制数据 文章目录 基于阿里云物联网平台的设备之间传输十六进制数据 1. 创建阿里云物联网产品 1.1 创建新的产品 1.2 为产品创建自定义topic 1.3 ...

  5. 基于阿里云物联网的无人值守远程农业智慧盒DIY之(三)arduino土壤湿度监测短信平台(1)

    基于阿里云物联网的无人值守远程农业智慧盒DIY之(三)arduino土壤湿度监测短信平台. csdn的网友Onetuzi今天留言催更.最近一直忙活别的事情,没有及时更新,希望大家见谅哈.为表达歉意,今 ...

  6. 基于阿里云IoT平台OTA进行APP确认升级的方案——业务架构类

    简介: 对于家居类及个人消费电子类的物联设备,基于用户体验的考虑,生产企业一般会为消费者提供通过手机APP进行确认升级的功能,典型的使用场景是通过手机APP对手环进行升级.本文主要介绍APP确认升级的 ...

  7. 基于苹果CMS系统的双端视频播放APP源码+视频教程

    是一款基于苹果CMS系统的移动端在线视频播放软件, 支持mp4.flv.m3u8.rmvb.mkv等主流视频格式的播放,现有安卓+ios版本. 基于苹果CMS系统的双端视频播放APP源码+视频教程.z ...

  8. 物联网平台搭建的全过程介绍(三)阿里云物联网设备接入订阅发布之Android studio例程

    物联网平台搭建系列内容前两节介绍的都是功能性的描述,今天以一个小例子,介绍具体的设备接入.订阅.发布的操作,例子的名字为:学生成绩录入平台,例子的界面如下图所示. 功能描述:当在阿里云物联网平台内下发 ...

  9. 物联网平台搭建的全过程介绍(二)——物联网平台通信思维导图

    目前物联网平台很多,本例以阿里云物联网平台为例,介绍一下物联网平台通信的思维导图和实现的步骤,本文仅做功能的宏观描述,具体操作会在后续文章内详细介绍.其他物联网原理基本大同小异.思维导图如下图所示: ...

最新文章

  1. 厉害了,用Python绘制动态可视化图表,并保存成gif格式
  2. 如何编写项目总结报告(转)
  3. python获取用户输入中文_python中的用户输入
  4. mysql大规模读写性能_十招搞定 MySQL 大规模数据库的性能和伸缩性优化
  5. CG CTF WEB php decode
  6. 做订购系统必须要明白的几点
  7. 解决jodconverter 2.2.1 版本不支持docx、xlsx、pptx 转换成PDF格式异常
  8. LeetCode(#26)————删除排序数组中的重复项
  9. 【计算机科学基础】控制复杂性的艺术
  10. Nginx基本数据结构之ngx_str_t
  11. Java--transient
  12. zookeeper 单机配置
  13. 华为Mate30和华为Mate30 Pro哪款实用?
  14. day19异常File类
  15. python set_Python Set联合
  16. HCIE-Security Day29:IPSec:实验(四)总部与分支机构之间建立IPSec PN(采用策略模板方式,总部采用固定IP)
  17. python 爬取起点中文网的小说(学习记录)
  18. Data Flow style(数据流体系风格)
  19. 异数OS-织梦师-PBFT(六) 走出区块链,加速破解PBFT
  20. Kafka ETL 之后,我们将如何定义新一代实时数据集成解决方案?

热门文章

  1. 稀里糊涂学-MySQL常用函数汇总(持续更新)
  2. 蓝牙5.0与蓝牙4.2的有哪些区别,你了解吗?
  3. 官宣!CATCTF不日开赛!!
  4. PPT学习(一)——PPT默认设置
  5. ORACLE 按照指定的ID 顺序排序
  6. window XP驱动开发(一)如何下载WDK
  7. JVM---垃圾回收概述及相关概念
  8. in作为介词的用法_in的用法是什么,用于什么中
  9. OLED的中英文和图片显示
  10. Element表格数据居中