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
用于解析根节点 JSON 对象。
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)
主界面逻辑,包含网络请求与 UI 更新。
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();
// http(s)://iot-api.heclouds.com/thingmodel/query-device-property?product_id=w50WLDzGBb&device_name=light
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权限。

