ToB企服应用市场:ToB评测及商务社交产业平台
标题: 【一步到位】Android Studio 实现安卓连接阿里云物联网云平台 [打印本页]
作者: 王海鱼 时间: 2024-10-9 22:39
标题: 【一步到位】Android Studio 实现安卓连接阿里云物联网云平台
软件下载
下载 Android Studio 和应用工具 - Android 开发者 | Android Developers (google.cn),最新版本目前是Android Studio Iguana | 2024.1.2,你可以到官网上去找之前的版本,手上有工作项目的不要去轻易尝试,说不定你就编译失败了,失败了也不要担心,办理就可以了。
本次利用Android Studio 4.0这里提供了一下版本的下载地址,可直接点击下:https://redirector.gvt1.com/edgedl/android/studio/install/4.0.0.16/android-studio-ide-193.6514223-windows.exe
软件安装
在非系统盘(C盘之外)的盘符下面新建一个文件夹定名为Android,作为软件安装目次(注意:目次不要出现中文,否则会堕落),并在文件夹下新建空文件夹定名为SDK,用于下载SDK。
我们双击下载好的Android studio
安装路径选择我们刚才新建的文件下,安装完成后,会进入Android Studio的启动页面,我们点击cancel(取消)。
接下来我们选择next,进入SDK下载界面,修改安装路径选择上面新建文件夹下的SDK路径,然后我们选择SDK安装位置并点击next。
等候Finish, 到这里Android studio安装就完成了!
创建项目
安装完成后桌面生成新的图标,双击图标打开。
第一次进入,并没有工程,所以我们选择新建项目“Start a new Android Studio project”。
选择空缺活动“Empty Activity”并点击“next”。
创建项目,SDA建议选择API21,自界说项目名称、项目存放路径(不能利用带中文的),其他默认,语言选择Java。
项目配置
按照如下路径,右键新建Java类,定名为AliyunIoTSignUtil,添加AliyunIoTSignUtil工具类。
复制代码到新建的类中,并保存。
- //第一行保留 自己的pack.com.example.
- import java.util.Arrays;
- import java.util.Map;
- import javax.crypto.Mac;
- import javax.crypto.SecretKey;
- import javax.crypto.spec.SecretKeySpec;
- public class AliyunIoTSignUtil {
- public static String sign(Map<String, String> params, String deviceSecret, String signMethod) {
- //将参数Key按字典顺序排序
- String[] sortedKeys = params.keySet().toArray(new String[]{});
- Arrays.sort(sortedKeys);
- //生成规范化请求字符串
- StringBuilder canonicalizedQueryString = new StringBuilder();
- for (String key : sortedKeys) {
- if ("sign".equalsIgnoreCase(key)) {
- continue;
- }
- canonicalizedQueryString.append(key).append(params.get(key));
- }
- try {
- String key = deviceSecret;
- return encryptHMAC(signMethod, canonicalizedQueryString.toString(), key);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- /**
- * HMACSHA1加密
- */
- public static String encryptHMAC(String signMethod, String content, String key) throws Exception {
- SecretKey secretKey = new SecretKeySpec(key.getBytes("utf-8"), signMethod);
- Mac mac = Mac.getInstance(secretKey.getAlgorithm());
- mac.init(secretKey);
- byte[] data = mac.doFinal(content.getBytes("utf-8"));
- return bytesToHexString(data);
- }
- public static final String bytesToHexString(byte[] bArray) {
- StringBuffer sb = new StringBuffer(bArray.length);
- String sTemp;
- for (int i = 0; i < bArray.length; i++) {
- sTemp = Integer.toHexString(0xFF & bArray[i]);
- if (sTemp.length() < 2) {
- sb.append(0);
- }
- sb.append(sTemp.toUpperCase());
- }
- return sb.toString();
- }
- }
复制代码右上角,展示形式改为Project。
按照如下路径,寻找文件并打开。
添加下面代码,打开网络权限。
- <uses-permission android:name="android.permission.INTERNET" />
- <!--允许程序获取网络状态-->
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
复制代码按照如下路径,打开对应文件。
对比下图,添加缺少的依靠。
- implementation 'com.google.android.material:material:1.0.0'
- implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.0'
复制代码 页面计划
项目新建后,会自动打开项目界面,如下图。
此时打开了两个文件,分别后缀是.java和.xml。可以理解为.xml是计划项目页面的部分,.java是计划项目逻辑关系的部分。
起首我们举行页面计划。
Android Studio支撑图形编辑,右上角有三种展示模式。分别为代码,代码与展示,图形计划。
起首我们通过图形界面放置四个文本框和二个按钮。
放置元素后,须要对其举行布局,Androi Stduio共有6种布局方式,分别为:线性布局“LinearLayout”、相对布局“RelativeLayout”、表格布局“TableLayout”、层布局“FrameLayout”
、绝对布局“AbsoluteLayout”、网格布局“GridLayout”,具体部分可网上自行了解。
我们这次利用的是线性布局,及元素在同一条水平或垂直的线上。
实例代码为:
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
- <LinearLayout
- android:id="@+id/linearLayoutTemperature"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:orientation="horizontal"
- android:layout_marginTop="96sp">
- <TextView
- android:id="@+id/textView1"
- android:layout_width="65dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="20dp"
- android:text="温度"
- android:textSize="20sp"
- android:textStyle="bold" />
- <TextView
- android:id="@+id/Temp"
- android:layout_width="71dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:text="NuLL"
- android:textSize="20sp" />
- </LinearLayout>
- <LinearLayout
- android:id="@+id/linearLayoutHumidity"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:orientation="horizontal"
- android:layout_marginTop="46sp">
- <TextView
- android:id="@+id/textView2"
- android:layout_width="65dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="20dp"
- android:text="湿度"
- android:textSize="20sp"
- android:textStyle="bold" />
- <TextView
- android:id="@+id/Humi"
- android:layout_width="71dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:text="NuLL"
- android:textSize="20sp" />
- </LinearLayout>
- <LinearLayout
- android:id="@+id/linearLayoutButtons"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:orientation="horizontal"
- android:layout_marginTop="96sp">
- <Button
- android:id="@+id/open"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="开" />
- <Button
- android:id="@+id/close"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="关" /> <!-- 修改为“关”以与按钮功能匹配 -->
- </LinearLayout>
- </LinearLayout>
复制代码将新创建的四个文本元素和两个按钮,举行线性布局,对应代码的功能可通过英语翻译大概了解,或自行查阅资料,这里不做解释。
我们设置了两个文本用于现实温度湿度数值,用两个按钮用于控制设备开关。
逻辑计划
实例代码:
- //package ..... 这一行保留自己的
- import androidx.appcompat.app.AppCompatActivity;
- import android.annotation.SuppressLint;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.util.Log;
- import android.view.View;
- import android.widget.Button;
- import android.widget.CompoundButton;
- import android.widget.TextView;
- import android.widget.Toast;
- import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
- import org.eclipse.paho.client.mqttv3.MqttCallback;
- import org.eclipse.paho.client.mqttv3.MqttClient;
- import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
- import org.eclipse.paho.client.mqttv3.MqttException;
- import org.eclipse.paho.client.mqttv3.MqttMessage;
- import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
- import org.json.JSONException;
- import org.json.JSONObject;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.concurrent.Executors;
- import java.util.concurrent.ScheduledExecutorService;
- import java.util.concurrent.TimeUnit;
- public class MainActivity extends AppCompatActivity {
- private MqttClient client;
- private MqttConnectOptions options;
- private Handler handler;
- private ScheduledExecutorService scheduler;
- //阿里云三元组
- private String productKey = "k0796zJ6ms6";
- private String deviceName = "QtDev";
- private String deviceSecret = "04c37a6b23ca9a936e8c760d56eca377";
- //Topic
- private final String pub_topic = "/sys/k0796zJ6ms6/QtDev/thing/event/property/post";
- private final String sub_topic = "/sys/k0796zJ6ms6/QtDev/thing/service/property/set";
- private int temp = 0;
- private int humi = 0;
- private TextView Temp;
- private TextView Humi;
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- Temp = findViewById(R.id.Temp);
- Humi = findViewById(R.id.Humi);
- Button btn_open = findViewById(R.id.open);
- Button btn_close = findViewById(R.id.close);
- btn_open.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- //开
- publish_message("{"params":{"Wind":1},"version":"1.0.0"}");
- }
- });
- btn_close.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- //关
- publish_message("{"params":{"Wind":0},"version":"1.0.0"}");
- }
- });
- mqtt_init();
- start_reconnect();
- handler = new Handler() {
- @SuppressLint("SetTextI18n")
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- switch (msg.what) {
- case 1: //开机校验更新回传
- break;
- case 2: // 反馈回传
- break;
- case 3: //MQTT 收到消息回传 UTF8Buffer msg=new UTF8Buffer(object.toString());
- String message = msg.obj.toString();
- Log.d("nicecode", "handleMessage: "+ message);
- try {
- //JSON解析获取数据
- JSONObject jsonObjectALL = null;
- jsonObjectALL = new JSONObject(message);
- JSONObject items = jsonObjectALL.getJSONObject("items");
- JSONObject obj_temp = items.getJSONObject("Temp");
- JSONObject obj_humi = items.getJSONObject("Humi");
- temp = obj_temp.getInt("value");
- humi = obj_humi.getInt("value");
- Temp.setText(temp + "");
- Humi.setText(humi + "");
- Log.d("nicecode", "temp: "+ temp);
- Log.d("nicecode", "humi: "+ humi);
- } catch (JSONException e) {
- e.printStackTrace();
- break;
- }
- break;
- case 30: //连接失败
- Toast.makeText(MainActivity.this, "连接失败", Toast.LENGTH_SHORT).show();
- break;
- case 31: //连接成功
- Toast.makeText(MainActivity.this, "连接成功", Toast.LENGTH_SHORT).show();
- try {
- client.subscribe(sub_topic, 1);
- } catch (MqttException e) {
- e.printStackTrace();
- }
- break;
- default:
- break;
- }
- }
- };
- }
- private void mqtt_init() {
- try {
- String clientId = "a1MoTKOqkVK.test_device1";
- Map<String, String> params = new HashMap<String, String>(16);
- params.put("productKey", productKey);
- params.put("deviceName", deviceName);
- params.put("clientId", clientId);
- String timestamp = String.valueOf(System.currentTimeMillis());
- params.put("timestamp", timestamp);
- // cn-shanghai
- String host_url ="tcp://"+ productKey + ".iot-as-mqtt.cn-shanghai.aliyuncs.com:1883";
- String client_id = clientId + "|securemode=2,signmethod=hmacsha1,timestamp=" + timestamp + "|";
- String user_name = deviceName + "&" + productKey;
- //example.自己的名字 参考package com.example.mqqttest;
- String password = com.example.mqqttest.AliyunIoTSignUtil.sign(params, deviceSecret, "hmacsha1");
- //host为主机名,test为clientid即连接MQTT的客户端ID,一般以客户端唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
- System.out.println(">>>" + host_url);
- System.out.println(">>>" + client_id);
- //connectMqtt(targetServer, mqttclientId, mqttUsername, mqttPassword);
- client = new MqttClient(host_url, client_id, new MemoryPersistence());
- //MQTT的连接设置
- options = new MqttConnectOptions();
- //设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,这里设置为true表示每次连接到服务器都以新的身份连接
- options.setCleanSession(false);
- //设置连接的用户名
- options.setUserName(user_name);
- //设置连接的密码
- options.setPassword(password.toCharArray());
- // 设置超时时间 单位为秒
- options.setConnectionTimeout(10);
- // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
- options.setKeepAliveInterval(60);
- //设置回调
- client.setCallback(new MqttCallback() {
- @Override
- public void connectionLost(Throwable cause) {
- //连接丢失后,一般在这里面进行重连
- System.out.println("connectionLost----------");
- }
- @Override
- public void deliveryComplete(IMqttDeliveryToken token) {
- //publish后会执行到这里
- System.out.println("deliveryComplete---------" + token.isComplete());
- }
- @Override
- public void messageArrived(String topicName, MqttMessage message)
- throws Exception {
- //subscribe后得到的消息会执行到这里面
- System.out.println("messageArrived----------");
- Message msg = new Message();
- //封装message包
- msg.what = 3; //收到消息标志位
- msg.obj =message.toString();
- //发送messge到handler
- handler.sendMessage(msg); // hander 回传
- }
- });
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- private void mqtt_connect() {
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- if (!(client.isConnected())) //如果还未连接
- {
- client.connect(options);
- Message msg = new Message();
- msg.what = 31;
- // 没有用到obj字段
- handler.sendMessage(msg);
- }
- } catch (Exception e) {
- e.printStackTrace();
- Message msg = new Message();
- msg.what = 30;
- // 没有用到obj字段
- handler.sendMessage(msg);
- }
- }
- }).start();
- }
- private void start_reconnect() {
- scheduler = Executors.newSingleThreadScheduledExecutor();
- scheduler.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
- if (!client.isConnected()) {
- mqtt_connect();
- }
- }
- }, 0 * 1000, 10 * 1000, TimeUnit.MILLISECONDS);
- }
- private void publish_message(String message) {
- if (client == null || !client.isConnected()) {
- return;
- }
- MqttMessage mqtt_message = new MqttMessage();
- mqtt_message.setPayload(message.getBytes());
- try {
- client.publish(pub_topic, mqtt_message);
- } catch (MqttException e) {
- e.printStackTrace();
- }
- }
复制代码自行修改阿里云三元组
注意:如下两行种的R.id.Temp与Humi,与你在.xml定名的id相同。
- Temp = findViewById(R.id.Temp);
- Humi = findViewById(R.id.Humi);
复制代码注意:com.example.mqqttest.利用自己的名字 参考package com.example.mqqttest;
- String password = com.example.mqqttest.AliyunIoTSignUtil.sign(params, deviceSecret, "hmacsha1");
复制代码可再次代码上举行二次加工。
项目运行
安装虚拟机
安装完成后启动虚拟机,并运行项目程序。
利用阿里云设备模拟器大概MQTT.fx举行硬件设备模拟,结果展示。
最后,大家就完成了本次计划。请求留下名贵的点赞收藏。
我是一个励志成为嵌入式全栈工程师的大三门生,求实习!!!
B站/CSDN:此乃刘同学
liustu.com.cn
项目展示链接:【Android Studio 实现安卓连接阿里云物联网云平台】https://www.bilibili.com/video/BV1rCpneCEfY?vd_source=4a3d8c11d455291dbb5507669d40a8b8
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) |
Powered by Discuz! X3.4 |