跳到主要内容OneNet 平台 Android Studio GET 获取数据与安全鉴权实现 | 极客日志Javajava
OneNet 平台 Android Studio GET 获取数据与安全鉴权实现
Android Studio 使用 Java 语言通过 OkHttp 客户端连接 OneNet 物联网平台。文章详细讲解了如何生成安全鉴权 Token,包括版本、资源名、过期时间等参数计算。展示了 JsonRootBean 和 Data 类的定义以解析返回的 JSON 数据。提供了 MainActivity 中发起 GET 请求获取设备属性值的完整代码示例,并说明了如何处理线程切换更新 UI。重点在于 OneNet 的安全鉴权机制及 HTTP 请求的正确配置。
MongoKing1 浏览 OneNet 平台 Android Studio GET 获取数据与安全鉴权实现
概要
本文介绍在 Android Studio 中使用 Java 语言通过 OkHttp 客户端获取 OneNet 平台数据的两种方法:GET 和 POST。重点在于安全鉴权的实现与 HTTP 请求的规范处理。
整体架构流程
- 引入依赖:添加联网权限及 OkHttp 库。
- 核心逻辑:编写 GET 和 POST 代码,关键在于生成安全鉴权 Token。
- 数据处理:解析返回的 JSON 数据并更新 UI。
技术名词解释
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 请求头。通过这个方法,可以添加自定义的请求头信息,如 Authorization。
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class OkHttpHeaderExample {
public static void main(String[] args) throws Exception {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://www.example.com")
.header("Authorization", "Bearer your_access_token")
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
}
}
两个类的声明
JsonRootBean.java
package com.example.myapplication;
import java.util.List;
public class JsonRootBean {
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 {
String identifier;
String time;
String value;
String data_type;
String access_mode;
String name;
String description;
}
鉴权生成(Token)
OneNet 的安全鉴权需要计算签名。以下是 Token 生成类的完整实现。
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 = null;
mac = Mac.getInstance("Hmac" + signatureMethod.toUpperCase());
mac.init(signinKey);
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 = "鉴权参数";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
Token.main(new String[]{});
} catch (UnsupportedEncodingException | NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException(e);
}
token = Token.TOKEN;
requestPermissions(new String[]{"android.permission.INTERNET"}, 1);
Get();
}
public void Get() {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://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();
}
}
数据解析说明
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"
}
可以看到有 4 个主要参数:code, data, msg, request_id。其中 data 是一个数组,每一项包含具体的属性信息。核心目标是获取 data 数组中对应属性的 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();
总结与注意事项
- 线程管理:网络请求必须在子线程执行,UI 更新必须在主线程,使用
post 或 Handler 机制。
- HTTPS 协议:建议生产环境使用 HTTPS 连接,避免数据被劫持。
- Token 有效期:生成的 Token 有过期时间,需根据业务需求定期刷新或延长有效期。
- 异常处理:务必捕获
IOException 等网络异常,防止应用崩溃。
- 权限配置:确保 AndroidManifest.xml 中已声明
android.permission.INTERNET 权限。
相关免费在线工具
- Keycode 信息
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
- Escape 与 Native 编解码
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
- JavaScript / HTML 格式化
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
- JavaScript 压缩与混淆
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online