IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 物联网平台搭建的全过程介绍(五)——基于阿里云物联网平台的Android聊天app源码 -> 正文阅读

[移动开发]物联网平台搭建的全过程介绍(五)——基于阿里云物联网平台的Android聊天app源码

本例程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">
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="50dp"
        android:orientation="vertical">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginTop="10dp"
            android:gravity="center"

            android:orientation="horizontal">
            <ImageView
                android: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>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="50dp"
            android:gravity="center"

            android:orientation="horizontal">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="@color/chocolate"
                android:gravity="center"
                android:textSize="25dp"
                android:text="我的聊聊"/>
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="50dp"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:orientation="horizontal">
            <TextView
                android: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="用户名:"/>
            <EditText
                android:id="@+id/name"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:textColor="@color/black"
                android:layout_weight="1"
                />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:orientation="horizontal">
            <TextView
                android: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="密    码:"/>
            <EditText
                android:id="@+id/pwd"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:inputType="textPassword"
                android:textColor="@color/black"
                android:layout_weight="1"
                />
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:orientation="horizontal">
            <Button
                android: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"
                />
            <Button
                android: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">

    <LinearLayout
        android: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">

        <LinearLayout
            android: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">

                <TextView
                    android: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>


    <LinearLayout
        android: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">

        <ScrollView
            android:id="@+id/sv_chat"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:background="@drawable/bg_stoke_4"
            >
        <TextView
            android: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>

        <LinearLayout
            android: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">

            <EditText
                android: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"
                />

            <Button
                android: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">

    <LinearLayout
        android: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">

        <LinearLayout
            android: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">

            <TextView
                android: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>

        <LinearLayout
            android: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">

            <TextView

                android: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"
                 />

            <TextView
                android: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>



        <LinearLayout
            android: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">


            <EditText
                android: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"

                />

            <Button
                android: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());

            // clientId
            this.clientId = productKey + "." + deviceName + "|timestamp=" + timestamp +
                    ",_v=paho-android-1.0.0,securemode=2,signmethod=hmacsha256|";

            // userName
            this.username = deviceName + "&" + productKey;

            // password
            String 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;


    @Override
    protected 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() {
            @Override
            public 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() {
            @Override
            public 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;//存放用户账号、密码、昵称信息

    @Override
    protected 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() {
            @Override
            public 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 {

    /* 设备三元组信息 */
    //20220002
    private String IotInstanceId="";
    private String PRODUCTKEY="";
    private String DEVICENAME="";
    private String DEVICESECRET="";

    //20221001
    private String PRODUCTKEY1="***********";
    private String DEVICENAME1="20220001";
    private String DEVICESECRET1="*********************************";

    //20220002
    private 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的TAG
    private 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")
    @Override
    protected 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、host
        AliyunTopicHostSet(0);

        //MQTT建连选项类,输入设备三元组productKey, deviceName和deviceSecret, 生成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();
        }



        /* 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() {
                //连接成功方法
                @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();
        }

        /**
         * mqtt回调类,此类内包含三个方法:connectionLost(掉线),messageArrived(订阅消息到达),deliveryComplete(发布消息送达)
         */
        mqttAndroidClient.setCallback(new MqttCallback() {

            //连接中断方法
            @Override
            public 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类结束标志

            //发布消息后,消息投递成功后返回方法
            @Override
            public 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() {
            @Override

            public 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() {
                @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();
        }
    }

    /**
     * 向默认的主题/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() {
                @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();
        }
    }
}

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

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来自动创建。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 11:27:25  更:2022-09-13 11:28:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 4:43:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码