2023新版Onenet+AndroidStudio(GET获取数据,Onenet安全鉴权)
文章目录
-
- 概要
- 整体架构流程
- 技术名词解释
- 两个类的声明
- 鉴权生成(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> 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个小参数(如下图),
所以我们核心的是获取到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();//获得亮度
最后给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
😝朋友们如果有需要的话,可以V扫描下方二维码联系领取~
1️⃣零基础入门
学习路线
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
需要详细路线图的,下面获取
路线对应学习视频
同时每个成长路线对应的板块都有配套的视频提供:
2️⃣视频配套工具&国内外网安书籍、文档
工具
######视频
######书籍
资源较为敏感,未展示全面,需要的下面获取
### 3️⃣Python面试集锦
面试资料
简历模板
因篇幅有限,资料较为敏感仅展示部分资料,添加上方即可获取👆
------ 🙇♂️ 本文转自网络,如有侵权,请联系删除 🙇♂️ ------