2023新版Onenet+AndroidStudio(GET获取数据,Onenet安全鉴权)

慈云数据 6个月前 (05-13) 技术支持 35 0

文章目录

    • 概要
    • 整体架构流程
    • 技术名词解释
    • 两个类的声明
    • 鉴权生成(Token)
    • MainActivity代码(Java)
    • 小结

      概要

      最近做了个大作业,是用AndroidStudio获取Onenet上面数据的。

      本文介绍两个方法,GET()和POST()。用的是java语言,kotlin语言可以直接搜kotlin,get方法,和java的没什么区别

      整体架构流程

      首先要引入依赖和库,比如联网的,Okhttp的库

      然后是核心的GET和POST代码,这里要注意的是鉴权,我找了好久才在官网找到安全鉴权的方式。(这里吐槽一下Onenet的开发者文档的可查询性实在是太弱了)

      最后是获取到返回数据。

      所有文件

      技术名词解释

      1,Okhttp:OkHttp是一个开源的Java库,用于处理HTTP请求。它是Square公司开发的,设计简单而灵活,是Android开发中广泛使用的HTTP客户端

      示例代码:

      import okhttp3.OkHttpClient;
      import okhttp3.Request;
      import okhttp3.Response;
      public class OkHttpExample {
          public static void main(String[] args) throws Exception {
              OkHttpClient client = new OkHttpClient();
              Request request = new Request.Builder()
                      .url("https://www.baidu.com")
                      .build();
              try (Response response = client.newCall(request).execute()) {
                  System.out.println(response.body().string());
              }
          }
      }
      

      2,安全鉴权:在OkHttp中,.header 方法用于设置HTTP请求头。通过这个方法,你可以添加自定义的请求头信息。以下是一个简单的示例,演示如何在OkHttp中使用.header方法:

      import okhttp3.OkHttpClient;
      import okhttp3.Request;
      import okhttp3.Response;
      public class OkHttpHeaderExample {
          public static void main(String[] args) throws Exception {
              OkHttpClient client = new OkHttpClient();
              // 构建请求时使用 .header 方法添加自定义的请求头
              Request request = new Request.Builder()
                      .url("https://www.example.com")
                      .header("Authorization", "Bearer your_access_token") // 添加 Authorization 请求头
                      .build();
              try (Response response = client.newCall(request).execute()) {
                  System.out.println(response.body().string());
              }
          }
      }
      

      两个类的声明

      第一个是JsonRootBean.java文件(这个文件和MainActivity平行)

      package com.example.myapplication;
      import java.util.List;
      public class JsonRootBean {//Json转换
          int code;
      List data;
          String msg;
          String request_id;
      }
      

      第二个是data.java

      package com.example.myapplication;
      import androidx.annotation.VisibleForTesting;
      import java.util.List;
      public class Data {//用list存放获取的数据流
          String identifier;
          String time;
          String value;
          String data_type;
          String access_mode;
          String name;
          String description;
      }
      

      鉴权生成(Token)

      Onenet的鉴权介绍网址:安全鉴权

      鉴权码生成代码:API鉴权

      我贴一下我的代码token.java

      package com.example.myapplication;
      import android.os.Build;
      import java.io.UnsupportedEncodingException;
      import java.net.URLEncoder;
      import java.security.InvalidKeyException;
      import java.security.NoSuchAlgorithmException;
      import java.util.Base64;
      import javax.crypto.Mac;
      import javax.crypto.spec.SecretKeySpec;
      public class Token {
          public static String TOKEN = "默认值";
          public static void setMyString(String newValue) {
              TOKEN = newValue;
          }
          public static String assembleToken(String version, String resourceName, String expirationTime, String signatureMethod, String accessKey)
                  throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
              StringBuilder sb = new StringBuilder();
              String res = URLEncoder.encode(resourceName, "UTF-8");
              String sig = URLEncoder.encode(generatorSignature(version, resourceName, expirationTime, accessKey, signatureMethod), "UTF-8");
              sb.append("version=")
                      .append(version)
                      .append("&res=")
                      .append(res)
                      .append("&et=")
                      .append(expirationTime)
                      .append("&method=")
                      .append(signatureMethod)
                      .append("&sign=")
                      .append(sig);
              return sb.toString();
          }
          public static String generatorSignature(String version, String resourceName, String expirationTime, String accessKey, String signatureMethod)
                  throws NoSuchAlgorithmException, InvalidKeyException {
              String encryptText = expirationTime + "\n" + signatureMethod + "\n" + resourceName + "\n" + version;
              String signature = null;
              byte[] bytes = HmacEncrypt(encryptText, accessKey, signatureMethod);
              if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                  signature = Base64.getEncoder().encodeToString(bytes);
              }
              return signature;
          }
          public static byte[] HmacEncrypt(String data, String key, String signatureMethod)
                  throws NoSuchAlgorithmException, InvalidKeyException {
              //根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
              SecretKeySpec signinKey = null;
              if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                  signinKey = new SecretKeySpec(Base64.getDecoder().decode(key),
                          "Hmac" + signatureMethod.toUpperCase());
              }
              //生成一个指定 Mac 算法 的 Mac 对象
              Mac mac = null;
              mac = Mac.getInstance("Hmac" + signatureMethod.toUpperCase());
              //用给定密钥初始化 Mac 对象
              mac.init(signinKey);
              //完成 Mac 操作
              return mac.doFinal(data.getBytes());
          }
          public enum SignatureMethod {
              SHA1, MD5, SHA256;
          }
          public static void main(String args) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
              String version = "2022-05-01";
              String resourceName = "userid/这里写你的用户id";
              String expirationTime = System.currentTimeMillis() / 1000 + 100 * 24 * 60 * 60 + "";
              String signatureMethod = SignatureMethod.SHA1.name().toLowerCase();
              String accessKey = "这里放你的AccessKey(在Onenet官网的账户信息里面)";
              String token = assembleToken(version, resourceName, expirationTime, signatureMethod, accessKey);
              setMyString(token);
          }
      }
      

      MainActivity代码(Java)

       public class MainActivity extends AppCompatActivity {
       String token="鉴权参数";
       protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);//UI的基本布局
              try {
                  Token.main("拿鉴权码,这里参数无所谓的");
              } catch (UnsupportedEncodingException | NoSuchAlgorithmException | InvalidKeyException e) {
                  throw new RuntimeException(e);
              }
              token=Token.TOKEN;//赋值Token,把鉴权信息拿到
      `        requestPermissions(new String[]{"android.permission.INTERNET"}, 1);
              Get();}
              
      

      如图上面是主函数代码,获取网络请求后直接GET就好了。

      public void Get(){
               new Thread(new Runnable() {
                          @Override
                          public void run() {
                     		while (true) {
                          try {
                              OkHttpClient client = new OkHttpClient();
                              //http(s)://iot-api.heclouds.com/thingmodel/query-device-property?product_id=w50WLDzGBb&device_name=light
                              //http://iot-api.heclouds.com/thingmodel/query-thing-model?product_id=w50WLDzGBb
                              Request request = new Request.Builder().url("http://iot-api.heclouds.com/thingmodel/query-device-property?product_id=这里输入你的产品id&device_name=你的设备名称")
                                      .header("Authorization",token)
                                      .build();
                              Response response = client.newCall(request).execute();
                              String responseData = response.body().string();
                                JsonRootBean app = new Gson().fromJson(responseData, JsonRootBean.class);
                             value=app.data.get(0).value.toString();//获得亮度
                              brightnessDisplay.post(new Runnable() {
                                  @Override
                                  public void run() {
                                      brightnessDisplay.setText(String.format("BrightnessRightNow:%s", value));
                                  }
                              });
                          } catch (IOException e) {
                              e.printStackTrace();}
                         try {
                             Thread.sleep(1000);
                         } catch (InterruptedException e) {
                             throw new RuntimeException(e);
                         }//延时一秒获取一次亮度
                     }
                  }
              }).start();
      

      在.header后面这个token,就是我们要的鉴权码。

      上面代码中的jsonRootbean是我自己的一个类,我GET获取的数据是一段json格式的数组

      {"code":0,
      "data":[{"identifier":"bright","time":1700127636130,"value":"0.600000","data_type":"float","access_mode":"读写","name":"bright"},
      {"identifier":"setbright","data_type":"int32","access_mode":"读写","name":"setbright"},
      {"identifier":"state","time":1698234341316,"value":"2","data_type":"enum","access_mode":"读写","name":"state","description":"工作模式"},
      {"identifier":"time","data_type":"date","access_mode":"读写","name":"time"}],
      "msg":"succ",
      "request_id":"f97096fb25a94f2884a043c510821485"}
      

      ONENET官网关于GET方法的返回数组

      可以看到有4个大参数,code,data,msg,request_id

      data是一个数组,在数组的每一个项里面又包含4个小参数(如下图),identifier,data_type,access_mode,name

      所以我们核心的是获取到data里面的这个value值,因此GET获取到数据后,采用了下面这个方式提取到value

       Response response = client.newCall(request).execute();
                              String responseData = response.body().string();
                                JsonRootBean app = new Gson().fromJson(responseData, JsonRootBean.class);
                             value=app.data.get(0).value.toString();//获得亮度
      

      小结

      搞定鉴权就简单了很多很多。有问题私信问

微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon