package com.nbee.echolink.broadcast; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import com.nbee.echolink.R; import com.nbee.echolink.model.DeviceInfo; import com.nbee.echolink.response.ApiResponse; import com.nbee.echolink.service.MonitorService; import com.nbee.echolink.utils.DeviceInfoUtils; import java.io.IOException; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import timber.log.Timber; public class HeartbeatAlarmReceiver extends BroadcastReceiver { private Context thisContext; private String accessToken; private String SN; /** * 当接收到特定广播时,执行心跳发送逻辑的函数。 * * @param context 上下文对象,用于访问应用全局功能。 * @param intent 携带了广播的内容。 */ @Override public void onReceive(Context context, Intent intent) { // 初始化上下文对象,为后续操作提供context thisContext = context; // 执行发送心跳信号的逻辑 sendHeartbeatSignal(); // 在发送心跳后,重新设置下一次心跳发送的时间 MonitorService.scheduleHeartbeat(thisContext); } /** * 发送心跳信号的函数。 * 该函数不会返回任何值,用于向服务器发送一个心跳请求,以保持客户端的活动状态。 * 该请求为异步请求,请求失败或成功都会在回调函数中进行处理。 */ private void sendHeartbeatSignal() { // 获取心跳请求的URL String heartBeatURL = thisContext.getResources().getString(R.string.heart_beat_url); OkHttpClient client = new OkHttpClient(); Request request = buildRequest(heartBeatURL); // 发送异步请求 client.newCall(request).enqueue(new okhttp3.Callback() { @Override public void onFailure(okhttp3.Call call, IOException e) { // 请求失败时的处理逻辑 Timber.e(e, "请求 " + heartBeatURL + "失败"); } @Override public void onResponse(okhttp3.Call call, okhttp3.Response response) { try { if (!response.isSuccessful()) { // 处理响应错误的情况 Timber.d("Request to " + heartBeatURL + " returned error: " + response.code() + ", " + response.message()); } else { // 处理成功响应的逻辑 String responseBody = response.body().string(); // 获取响应体内容 Gson gson = new Gson(); ApiResponse apiResponse = gson.fromJson(responseBody, ApiResponse.class); if (apiResponse == null) { // 处理api响应为空的情况 Timber.d("apiResponse is null."); } if (!apiResponse.getCode().equals("0")) { // 处理响应状态码错误的情况 Timber.d("请求返回状态码错误,返回内容: " + apiResponse); } } } catch (IOException e) { // 处理响应处理过程中的IO异常 Timber.e(e, "IOException during handling response"); } catch (JsonSyntaxException e) { // 处理响应解析过程中的JSON格式异常 Timber.e(e, "JsonSyntaxException during parsing response"); } finally { // 确保响应体被关闭,避免资源泄露 response.close(); } } }); } /** * 构建一个网络请求。 * * @param apiUrl 请求的API地址。 * @param 请求返回的类型。 * @return 返回构建好的Request对象。 */ private Request buildRequest(String apiUrl) { // 从资源文件中读取序列号和访问令牌 // SN = context.getResources().getString(R.string.SN); SN = DeviceInfoUtils.getDeviceSerial(); Timber.i("SN: " + SN); accessToken = thisContext.getResources().getString(R.string.access_token); // 创建设备信息对象并设置设备相关属性 DeviceInfo deviceInfo = new DeviceInfo(); deviceInfo.setDeviceBrand(DeviceInfoUtils.getDeviceBrand()); deviceInfo.setDeviceModel(DeviceInfoUtils.getDeviceModel()); deviceInfo.setAndroidVersion("Android " + DeviceInfoUtils.getDeviceAndroidVersion()); deviceInfo.setSn(SN); // 使用Gson将设备信息对象转换为JSON字符串 Gson gson = new Gson(); String json = gson.toJson(deviceInfo); // 创建请求体,使用JSON格式 MediaType JSON = MediaType.get("application/json; charset=utf-8"); RequestBody body = RequestBody.create(json, JSON); // 构建请求对象,并设置请求头,包括accessToken和Content-Type Request request = new Request.Builder() .url(apiUrl) .addHeader("accessToken", accessToken) .addHeader("Content-Type", "application/json") .post(body) .build(); return request; } }