活动介绍

"errorMsg": "JSON parse error: Cannot deserialize instance of `java.util.ArrayList` out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.ArrayList` out of START_OBJECT token\n at [Source: (PushbackInputStream); line: 1, column: 1]"

时间: 2025-03-24 18:06:10 浏览: 79
### 解决方案 当遇到 `JSON parse error: Cannot deserialize instance of 'java.util.ArrayList' out of START_OBJECT token` 错误时,这通常是由于前端传递的 JSON 数据结构与后端期望的数据类型不一致引起的。以下是详细的分析和解决方案: #### 1. **问题原因** 此错误的核心原因是 Jackson 序列化/反序列化工具试图将一个 JSON 对象 (`START_OBJECT`) 转换为 Java 的 `ArrayList` 类型,而这两种类型的结构并不兼容[^4]。 - 如果后端期待的是一个数组(即 JSON 中的 `[ ]`),但实际接收到的是单个对象(即 `{ }`),就会触发该错误。 - 前端可能发送了一个单独的对象而不是列表形式的数据。 #### 2. **解决方法** ##### 方法一:调整前端数据格式 如果前端确实应该传递一组数据,则需确保其以 JSON 数组的形式发送给服务器。例如: ```json [ { "id": 1, "name": "Item A" }, { "id": 2, "name": "Item B" } ] ``` 而非单一对象: ```json { "id": 1, "name": "Item A" } ``` 通过修改前端代码来满足后端需求可以有效解决问题[^5]。 ##### 方法二:更改后端参数定义 假如业务逻辑允许接收单个实体作为输入之一,在这种情况下可考虑改变控制器方法签名,使其能够接受更灵活的数据类型。比如改为支持接收单个 DTO 或者封装类包含 list 属性的方式处理请求体。 示例代码如下所示: ```java @PostMapping("/example") public ResponseEntity<?> handleRequest(@RequestBody DeliveryDTO deliveryDTO){ // Process the request... } // Or use wrapper class approach: class WrapperClass { private List<DeliveryDTO> deliveries; public void setDeliveries(List<DeliveryDTO> deliveries) { this.deliveries = deliveries;} public List<DeliveryDTO> getDeliveries() {return this.deliveries;} } ``` 上述方式提供了另一种途径去适配不同形态下的客户端提交内容[^3]。 ##### 方法三:自定义 Deserializer 对于某些特殊场景下无法简单地依靠调整前后端交互协议达成目标的情况,还可以借助于 Jackson 提供的功能来自定义 deserialization 行为。创建一个新的 deserializer 并注册它至 ObjectMapper 实现特定规则下的转换过程[^1]。 具体实现步骤包括但不限于以下几个方面: 1. 定义新的 deserializer 子类继承 JsonDeserializer<T>; 2. Override deserialize 方法完成定制化的解析流程; 3. 使用 @JsonDeserialize(using=CustomDeserializer.class) 注解标注相应字段或者全局配置 objectmapper 添加此类实例。 #### 3. **注意事项** 无论采取哪种策略都需要仔细验证最终效果并测试边界条件以防引入新 bug 。另外也要注意保持 API 文档清晰准确以便维护人员理解接口预期行为[^2]。 --- ### 示例代码片段 下面给出一段简单的例子展示如何设置自定义的 deserializers 来应对复杂情形: ```java import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import java.io.IOException; import java.util.Collections; import java.util.List; public class CustomListDeserializer extends StdDeserializer<List<MyObject>> { protected CustomListDeserializer() { super((Class<List<MyObject>>) null); } @Override public List<MyObject> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { ObjectMapper mapper = (ObjectMapper)jp.getCodec(); JsonNode node = mapper.readTree(jp); if(node.isArray()){ return mapper.convertValue(node, new TypeReference<List<MyObject>>() {}); }else{ MyObject obj = mapper.treeToValue(node, MyObject.class); return Collections.singletonList(obj); } } } ``` 随后可以在对应的 model 上应用这个 custom deserializer : ```java @JsonDeserialize(using = CustomListDeserializer.class) private List<MyObject> myObjects; ``` 这样即使传来的 json 是 single object ,也能被正确解释成只有一个 element 的 list 结构。 ---
阅读全文

相关推荐

我的代码又出现以下问题:D:\MyApplication3\app\src\main\java\com\tencent\example\myapplication\MainActivity.java:37: error: cannot find symbol TencentMapInitializer.setApiKey("C3ZBZ-22V6T-U3CXI-VUX44-U3OTF-WPBK7"); // �滻Ϊ�����ʵAPI Key ^ symbol: method setApiKey(String) location: class TencentMapInitializer D:\MyApplication3\app\src\main\java\com\tencent\example\myapplication\MainActivity.java:63: error: cannot find symbol style.interval(2000); // ��λ������޸���ʹ��interval()������equals()�� ^ symbol: method interval(int) location: variable style of type MyLocationStyle D:\MyApplication3\app\src\main\java\com\tencent\example\myapplication\MainActivity.java:108: error: cannot find symbol case TencentLocationManager.ERROR_OK: ^ symbol: variable ERROR_OK location: class TencentLocationManager D:\MyApplication3\app\src\main\java\com\tencent\example\myapplication\MainActivity.java:111: error: cannot find symbol case TencentLocationManager.ERROR_ILLEGAL_KEY: ^ symbol: variable ERROR_ILLEGAL_KEY location: class TencentLocationManager D:\MyApplication3\app\src\main\java\com\tencent\example\myapplication\MainActivity.java:114: error: cannot find symbol case TencentLocationManager.ERROR_NETWORK: ^ symbol: variable ERROR_NETWORK location: class TencentLocationManager D:\MyApplication3\app\src\main\java\com\tencent\example\myapplication\MainActivity.java:117: error: cannot find symbol case TencentLocationManager.ERROR_UNKNOWN: ^ symbol: variable ERROR_UNKNOWN location: class TencentLocationManager D:\MyApplication3\app\src\main\java\com\tencent\example\myapplication\MainActivity.java:131: error: cannot find symbol tencentMap.getMyLocationStyle().anchor(0.5f, 0.5f); // ���ö�λ��ê����� ^ symbol: method getMyLocationStyle() location: variable tencentMap of type TencentMap D:\MyApplication3\app\src\main\java\com\tencent\example\myapplication\MainActivity.java:132: error: cannot find symbol tencentMap.setMyLocation(latLng); ^ symbol: method setMyLocation(LatLng) location: variable tencentMap of type TencentMap 怎么解决

Caused by: java.lang.IllegalAccessException: Class org.apache.struts2.json.DefaultJSONWriter can not access a member of class org.joda.time.tz.DateTimeZoneBuilder$PrecalculatedZone with modifiers "public" List<ACDFileInfo> fileInfos这个字段序列化有问题package com.iaspec.ecfps.acd.client.model; import com.iaspec.ecfps.acd.client.model.ACDSubmissionStatus; import com.iaspec.ecfps.acd.client.model.BusinessService; import com.iaspec.ecfps.acd.client.model.ExceptionHandlingStatus; import com.iaspec.ecfps.acd.client.model.ExceptionType; import java.io.Serializable; import java.math.BigDecimal; import java.util.HashMap; import java.util.List; import java.util.Map; import org.joda.time.DateTime; import org.joda.time.LocalDate; import io.swagger.annotations.ApiModelProperty; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.XmlEnum; import javax.xml.bind.annotation.XmlEnumValue; import com.fasterxml.jackson.annotation.JsonProperty; public class ACDFileInfo implements Serializable { private static final long serialVersionUID = 7674217844605187519L; @ApiModelProperty(value = "") private String fileName = null; @ApiModelProperty(value = "") private Integer recordNum = null; @ApiModelProperty(value = "") private ACDSubmissionStatus status = null; @ApiModelProperty(value = "") private String errorMsg = null; @ApiModelProperty(value = "") private DateTime creationDt = null; @ApiModelProperty(value = "") private DateTime lastUpdateDt = null; @ApiModelProperty(value = "") private String custom1 = null; @ApiModelProperty(value = "") private Map<String, Object> custom2 = null; @ApiModelProperty(value = "") private LocalDate valueDate = null; @ApiModelProperty(example = "false", value = "") private Boolean isMorningBatch = nul

Exception in thread "main" com.alibaba.fastjson2.JSONException: expect ':', but ,, offset 58, character ", line 1, column 59, fastjson-version 2.0.26 {"returnCode":"SUC0000","errorMsg":null,"data":{"output":"运维方案如下:\n{\n \"queryLog\": [],\n \"queryDatabase\": [\n \"根据订单号MA7842207190000045从数据库找到YJF_BILL_DETAIL的所有信息\",\n \"根据流水号K6904000006111C从数据库找到SYT_HOSTACC_DETAIL的所有信息\"\n ],\n \"other\": [\n \"根据查到的结果判断订单的STATUS和转账流水的CHARGE_STATUS状态是否是未对账\",\n \"根据查到的结果判断订单和转账流水的转账码是否相同\",\n \"根据查到的结果判断订单VRACCNO和转账流水的MERCH_EACNO+INN_MSG是否相同\",\n \"根据查到的结果判断订单生成时间ORDER_TIME是否晚于转账的生成时间CREATE_TIME\"\n ]\n}","sessionId":"1927567944006807552","componentId":"INTERMEDIATE_OUTPUT-o06tj","intermediateDataStatus":"DONE","costTimeTotal":0,"inputTokens":0,"outputTokens":0,"usedTokens":0},"type":"DATA","traceId":"761479b398dd8bf0cc247dc8f6cfa9ed"} at com.alibaba.fastjson2.JSONReaderUTF16.readFieldNameHashCode(JSONReaderUTF16.java:1316) at com.alibaba.fastjson2.reader.ORG_3_2_Output.readObject(Unknown Source) at com.alibaba.fastjson2.reader.ORG_2_3_ResponseData.readObject(Unknown Source) at com.alibaba.fastjson2.reader.ORG_1_5_AiFactoryStreamRespDTO.readObject(Unknown Source) at com.alibaba.fastjson2.JSON.parseObject(JSON.java:786) at ai.infrastructure.client.dto.OmClient.main(OmClient.java:142)

08-04 12:17:44.700 30976 30976 E OplusA7ThreadExtImpl: Failed to parse DragConfig, errorMsg = Attempt to invoke virtual method 'android.view.viewdrag.bean.ConfigDragInfo android.view.viewdrag.bean.PackageDragConfigInfo.getConfigDragInfo()' on a null object reference java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.viewdrag.bean.ConfigDragInfo android.view.viewdrag.bean.PackageDragConfigInfo.getConfigDragInfo()' on a null object reference at android.view.viewdrag.OplusViewDragManager.setDragConfig(OplusViewDragManager.java:141) at android.view.viewdrag.OplusSmartLoopDragManager.init(OplusSmartLoopDragManager.java:82) at android.app.OplusActivityThreadExtImpl.hookHandleBindApplication(OplusActivityThreadExtImpl.java:996) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7940) at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2654) at android.os.Handler.dispatchMessage(Handler.java:112) at android.os.Looper.loopOnce(Looper.java:288) at android.os.Looper.loop(Looper.java:393) at android.app.ActivityThread.main(ActivityThread.java:9564) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:600) at com.android.internal.os.ChildZygoteInit.runZygoteServer(ChildZygoteInit.java:136) at com.android.internal.os.WebViewZygoteInit.main(WebViewZygoteInit.java:147) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:600) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1010)

2025-04-01 10:09:31.840 TRACE [org.springframework.web.servlet.DispatcherServlet] - GET "/big-screen/get-top-10-event-types", parameters={}, headers={masked} in DispatcherServlet 'dispatcherServlet' 2025-04-01 10:09:31.840 TRACE [o.s.w.s.m.m.a.RequestMappingHandlerMapping] - Mapped to com.syzn.dv.biz.bigscreen.northbound.controller.BigScreenController#getTop10EventTypes(BigScreenCommonReq) 2025-04-01 10:09:31.840 TRACE [org.springframework.web.method.HandlerMethod] - Arguments: [BigScreenCommonReq(direction=null, deviceType=null, startDate=null, endDate=null)] 2025-04-01 10:09:31.840 DEBUG [o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver] - Using @ExceptionHandler com.syzn.dv.config.GlobalExceptionHandler#customErrorHandler(RuntimeException) 2025-04-01 10:09:31.840 TRACE [org.springframework.web.method.HandlerMethod] - Arguments: [java.lang.NullPointerException] 2025-04-01 10:09:31.841 DEBUG [o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor] - Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json] 2025-04-01 10:09:31.841 TRACE [o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor] - Writing [Result(code=2000, msg=系统异常,请稍后重试, exception=, data=null, error=Error(errorCode=2000, errorMsg=系统异常,请稍后重试))] 2025-04-01 10:09:31.841 DEBUG [o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver] - Resolved [java.lang.NullPointerException] 2025-04-01 10:09:31.841 TRACE [org.springframework.web.servlet.DispatcherServlet] - No view rendering, null ModelAndView returned. 2025-04-01 10:09:31.841 DEBUG [org.springframework.web.servlet.DispatcherServlet] - Completed 200 OK, headers={masked} java.lang.NullPointerException at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936) at com.syzn.dv.biz.bigscreen.northbound.appservice.impl.BigScreenAppServiceHandlerContext.getHandler(BigScreenAppServiceHandlerContext.java:50) at com.syzn.dv.biz.bigscreen.northbound.controller.BigScreenController.getTop10EventTyp

开发文档:OPEN API/云直播/播放地址/播放地址接口(新)/获取播放地址 获取播放地址 接口功能: 该接口用于通过设备序列号、通道号获取单台设备的播放地址信息,无法获取永久有效期播放地址。 请求地址 https://open.ys7.com/api/lapp/v2/live/address/get 子账户token请求所需最小权限 "Permission":"Get" "Resource":"dev:序列号" 请求方式 POST 请求参数 参数名 类型 描述 是否必选 accessToken String 授权过程获取的access_token Y deviceSerial String 设备序列号例如427734222,均采用英文符号,限制最多50个字符 Y channelNo Integer 通道号,非必选,默认为1 N protocol Integer 流播放协议,1-ezopen、2-hls、3-rtmp、4-flv,默认为1 N code String ezopen协议地址的设备的视频加密密码 N expireTime Integer 过期时长,单位秒;针对hls/rtmp/flv设置有效期,相对时间;30秒-720天 N type String 地址的类型,1-预览,2-本地录像回放,3-云存储录像回放,非必选,默认为1;回放仅支持rtmp、ezopen、flv协议 N quality Integer 视频清晰度,1-高清(主码流)、2-流畅(子码流) N startTime String 本地录像/云存储录像回放开始时间,云存储开始结束时间必须在同一天,示例:2019-12-01 00:00:00 N stopTime String 本地录像/云存储录像回放结束时间,云存储开始结束时间必须在同一天,示例:2019-12-01 23:59:59 N supportH265 Integer 请判断播放端是否要求播放视频为H265编码格式,1表示需要,0表示不要求 N playbackSpeed String 回放倍速。倍速为 -1( 支持的最大倍速)、0.5、1、2、4、8、16; 仅支持protocol为4-flv 且 type为2-本地录像回放( 部分设备可能不支持16倍速) 或者 3-云存储录像回放 N gbchannel String 国标设备的通道编号,视频通道编号ID N HTTP请求报文 POST /api/lapp/v2/live/address/get HTTP/1.1 Host: open.ys7.com Content-Type: application/x-www-form-urlencoded accessToken=at.dunwhxt2azk02hcn7phqygsybbw0wv6p&deviceSerial=C78957921&channelNo=1 返回数据 { "msg": "Operation succeeded", "code": "200", "data": { "id": "254708522214232064", "url": "https://open.ys7.com/v3/openlive/C78957921_1_1.m3u8?expire=1606999273&id=254708522214232064&t=093e5c6668d981e0f0b8d2593d69bdc98060407d1b2f42eaaa17a62b15ee4f99&ev=100", "expireTime": "2020-12-03 20:41:13" } } OPEN API/云直播/录像文件查询/云存储录像查询/根据时间获取存储文件信息 根据时间获取存储文件信息 接口功能: 该接口用于根据时间获取存储文件信息。注: 请求地址: https://open.ys7.com/api/lapp/video/by/time 请求方式 POST 子账户token请求所需最小权限 无 请求参数; 参数名 类型 描述 是否必选 accessToken String 访问令牌 Y deviceSerial String 设备序列号,存在英文字母的设备序列号,字母需为大写 Y channelNo int 通道号,非必选,默认为1 N startTime long 起始时间,时间格式为:1378345128000。非必选,默认为当天0点 N endTime long 结束时间,时间格式为:1378345128000。非必选,默认为当前时间 N recType int 回放源,0-系统自动选择,1-云存储,2-本地录像。非必选,默认为0 N version String 返回分页结构,recType=1时,传2.0会返回分页结构; recType=2时,传2.0且pageSize不为空的情况才会返回分页结构 N pageSize int recType为1或2时,可指定返回的文件数量,云存储类型分页大小范围:1-1000,本地录像类型分页大小范围: 1-500 N HTTP请求报文 POST /api/lapp/alarm/video HTTP/1.1 Host: open.ys7.com Content-Type: application/x-www-form-urlencoded accessToken=at.dunwhxt2azk02hcn7phqygsybbw0wv6p&deviceSerial=427734203&channelNo=1&startTime=1378345128000&endTime=1378345128000&recType=0 返回数据 { “code”: “200”, “msg”: “操作成功”, “data”: [ { “recType”: 0, “startTime”: 1378345128000, “endTime”: 1378345128000, “deviceSerial”: “409864662”, “cameraNo”: “1”, “localType”: “ALLEVENT”, “channelType”: “D”, “id”: 20432171600, “fileId”: “20432171600”, “ownerId”: “chenyong”, “fileType”: 1, “fileName”: “”, “cloudType”: 1, “fileIndex”: “5d5b6d94-13e8-440b-a25b-00eda521c35f”, “fileSize”: 4011828, “locked”: 0, “createTime”: “2016-08-22 13:59:13”, “crypt”: 22, “keyChecksum”: “”, “videoLong”: 150000, “coverPic”: “https://218.244.139.5:0/api/cloud?method=download&fid=a14f8348-1dd1-11b2-aef9-dbed68cc4c3e&session=hik%24shipin7%231%23USK%23at.a2rwv07y6v44ozhqblhb0tly337hb4vq-4jktv8rbjh-193fe5b-cm38stbht”, “downloadPath”: “218.244.139.5:0”, “type”: 1 }, { “recType”: 0, “startTime”: 1378345128000, “endTime”: 1378345128000, “deviceSerial”: “409864662”, “cameraNo”: “1”, “localType”: “ALLEVENT”, “channelType”: “D”, “id”: 20432171600, “fileId”: “20432171600”, “ownerId”: “chenyong”, “fileType”: 1, “fileName”: “”, “cloudType”: 1, “fileIndex”: “5d5b6d94-13e8-440b-a25b-00eda521c35f”, “fileSize”: 4011828, “locked”: 0, “createTime”: “2016-08-22 13:59:13”, “crypt”: 22, “keyChecksum”: “”, “videoLong”: 150000, “coverPic”: “https://218.244.139.5:0/api/cloud?method=download&fid=a14f8348-1dd1-11b2-aef9-dbed68cc4c3e&session=hik%24shipin7%231%23USK%23at.a2rwv07y6v44ozhqblhb0tly337hb4vq-4jktv8rbjh-193fe5b-cm38stbht”, “downloadPath”: “218.244.139.5:0”, “type”: 1 } ] } } 返回数据 (分页结构返回) { “msg”: “操作成功!”, “code”: “200”, “data”: { “files”: [ { “recType”: 2, “startTime”: 1691627391000, “endTime”: 1691627443000, “deviceSerial”: “G12262381”, “channelNo”: 1, “localType”: “ALARM”, “channelType”: “D”, “id”: null, “fileId”: null, “ownerId”: null, “fileType”: 0, “fileName”: null, “cloudType”: 0, “fileIndex”: null, “fileSize”: 0, “locked”: 0, “createTime”: 0, “crypt”: 0, “keyChecksum”: null, “videoLong”: 0, “coverPic”: null, “downloadPath”: null, “type”: 1, “iStorageVersion”: null, “videoType”: null }, { “recType”: 2, “startTime”: 1691627491000, “endTime”: 1691627537000, “deviceSerial”: “G12262381”, “channelNo”: 1, “localType”: “ALARM”, “channelType”: “D”, “id”: null, “fileId”: null, “ownerId”: null, “fileType”: 0, “fileName”: null, “cloudType”: 0, “fileIndex”: null, “fileSize”: 0, “locked”: 0, “createTime”: 0, “crypt”: 0, “keyChecksum”: null, “videoLong”: 0, “coverPic”: null, “downloadPath”: null, “type”: 1, “iStorageVersion”: null, “videoType”: null }, { “recType”: 2, “startTime”: 1691627537000, “endTime”: 1691627586000, “deviceSerial”: “G12262381”, “channelNo”: 1, “localType”: “ALARM”, “channelType”: “D”, “id”: null, “fileId”: null, “ownerId”: null, “fileType”: 0, “fileName”: null, “cloudType”: 0, “fileIndex”: null, “fileSize”: 0, “locked”: 0, “createTime”: 0, “crypt”: 0, “keyChecksum”: null, “videoLong”: 0, “coverPic”: null, “downloadPath”: null, “type”: 1, “iStorageVersion”: null, “videoType”: null } ], “isAll”: false, “nextFileTime”: 1691627586000 } } OPEN API/云直播/录像文件查询/设备本地录像查询/查询设备本地录像 查询设备本地录像 接口URL GET https://open.ys7.com/api/v3/device/local/video/unify/query 请求 Header 名称 类型 必填 描述 示例指及参考API accessToken string Y 萤石开放平台令牌,支持托管 、子账号、设备小权限token,权限为Replay deviceSerial string Y 设备序列号 localIndex string N 通道号 query 名称 类型 必填 描述 示例指及参考API recordType int N 1:定时录像 2:事件录像 3:智能-车 4:智能-人形 5:自动浓缩录像,不填默认查询所有类型 startTime string Y 开始时间,时间格式为:1731988238,开始结束时间必须在同一天,开始时间不能大于结束时间 endTime string Y 结束时间,时间格式为:1732007943,开始结束时间必须在同一天,开始时间不能大于结束时间 isQueryByNvr int N 是否反查NVR录像:0-不反查(默认),1-反查NVR location int N 录像检索位置:1-本地录像检索(默认),2-CVR中心录像检索 pageSize int N 分页的页面大小,默认50,最大200 响应 返回数据 名称 类型 描述 示例 meta object meta -code int code -message string message -moreInfo object moreInfo data object data -records arrayrecords –startTime int startTime –endTime int endTime –type string type –size string size -fromNvr boolean fromNvr -deviceSerial string deviceSerial -localIndex string localIndex -hasMore boolean hasMore -nextFileTime int nextFileTime 返回示例 { “meta”: { “code”: 200, “message”: “操作成功”, “moreInfo”: null }, “data”: { “records”: [ { “startTime”: 1731945592, “endTime”: 1731949200, “type”: “ALARM”, //录像类型 “size”: “” //录像文件大小,单位:字节 } ], “fromNvr”: true, //该录像文件是否来自关联的nvr “deviceSerial”: “J79401957”, // fromNvr为true,则返回关联NVR设备序列号,否则返回入参填的设备序列号。 “localIndex”: “1”, // fromNvr为true,则返回关联NVR设备通道号,否则返回入参填的设备通道号。 “hasMore”: true, //是否存在更多录像文件 “nextFileTime”: 1732007943// hasMore为true时,该参数值为下一个录像文件的开始时间。如需分页查询,该参数值可作为下一页录像文件查询的开始时间。 } } SDK及示例/Android SDK/Android 回放/回放 回放 对摄像机存储于SD卡、云端的录像进行取流,查看当前摄像机的历史回放画面。 第一步创建播放器 可调用EZOpenSDK中的 createPlayer 方法创建播放器。 第二步配置播放器 播放器创建完成后需要进行设置代理,设置播放视图,验证码设置等配置。 第三步开始播放 调用startPlayback(EZCloudRecordFile cloudFile) 或 startPlayback(EZDeviceRecordFile deviceFile) 开始回放 第四步结束播放 调用stopPlayback结束回放 5.第五步释放播放器 调用release释放播放器 完整示例代码如下: public class EZPlayBackListActivity extends RootActivity implements TextureView.SurfaceTextureListener, Handler.Callback, … { private EZPlayer mPlaybackPlayer = null; /** 点击录像片段后调用 */ private void initEZPlayer() { if (mPlaybackPlayer != null) { // do something // 停止播放 mPlaybackPlayer.stopPlayback(); } else { // 创建播放器,也可以直接使用EZPlayer类中的方法创建 mPlaybackPlayer = getOpenSDK().createPlayer(mCameraInfo.getDeviceSerial(), mCameraInfo.getCameraNo()); // 设置Handler, 该handler将被用于从播放器向handler传递消息 mPlaybackPlayer.setHandler(playBackHandler); // 设置播放器的显示Surface mPlaybackPlayer.setSurfaceEx(mTextureView.getSurfaceTexture()); // 可选,设备开启了视频/图片加密功能后需设置,可根据EZDeviceInfo的isEncrypt属性判断 mPlaybackPlayer.setPlayVerifyCode(verifyCode); // 回放云端存储的视频,cloudFile由EZOpenSDK.searchRecordFileFromCloud接口获取 mPlaybackPlayer.startPlayback(cloudFile); // 或者 // 回放设备上存储的视频,deviceFile由EZOpenSDK.searchRecordFileFromDevice接口获取 mPlaybackPlayer.startPlayback(deviceFile); } } @Override protected void onStop() { super.onStop(); if (mPlaybackPlayer != null) { // 页面退出或用户主动停止播放时调用stopPlayback结束回放 mPlaybackPlayer.stopPlayback(); } // do something } @Override protected void onDestroy() { super.onDestroy(); if (mPlaybackPlayer != null) { // 调用release释放播放器 mPlaybackPlayer.release(); } // do something } @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { // 画面显示第一帧 case EZPlaybackConstants.MSG_REMOTEPLAYBACK_PLAY_SUCCUSS:// 录像回放成功 // do something break; case EZPlaybackConstants.MSG_REMOTEPLAYBACK_PLAY_START:// 播放开始|seek成功 // do something break; case EZPlaybackConstants.MSG_REMOTEPLAYBACK_STOP_SUCCESS:// 录像回放停止 // do something break; case EZPlaybackConstants.MSG_REMOTEPLAYBACK_PLAY_FINISH:// 录像回放完成 // do something break; case EZPlaybackConstants.MSG_REMOTEPLAYBACK_PLAY_FAIL:// 录像回放失败 ErrorInfo errorInfo = (ErrorInfo) msg.obj; int errorCode = errorInfo.errorCode; // 如果是需要验证码或者是验证码错误 if (errorCode == ErrorCode.ERROR_INNER_VERIFYCODE_NEED || errorCode == ErrorCode.ERROR_INNER_VERIFYCODE_ERROR) { // do something } else { // do something } break; default: break; } } } 说明 回放需先获取到视频信息,searchRecordFileFromCloud方法和searchRecordFileFromDevice方法分别是获取云端视频列表和设备存储视频列表的两个方法。 开始播放之后在handleMessage回调中会收到通知消息,播放成功消息为EZPlaybackConstants.MSG_REMOTEPLAYBACK_PLAY_SUCCUSS, 播放失败消息为EZPlaybackConstants.MSG_REMOTEPLAYBACK_PLAY_FAIL,如果是错误码ErrorCode.ERROR_INNER_VERIFYCODE_NEED = 400035(需要设备验证码)或者ErrorCode.ERROR_INNER_VERIFYCODE_ERROR = 400036(设备验证码不匹配),需要开发者自己处理让用户输入验证密码,然后调用EZPlayer.setPlayVerifyCode设置密码,重新启动播放。 注意:实际录像回放结束时间可能与录像片段的结束时间有偏差,如果时间点相近则认为回放结束,此为正常现象。严格依据上述开发文档检查并解决从MainActivity.java点击id.huifang后进入FanHui.java整个程序卡死无任何响应。MainActivity.java:package com.videogo.ui.login; import android.content.res.Configuration; import android.content.pm.ActivityInfo; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import com.videogo.exception.BaseException; import com.videogo.exception.ErrorCode; import com.videogo.openapi.EZConstants; import com.videogo.openapi.EZOpenSDK; import com.videogo.openapi.EZPlayer; import ezviz.ezopensdk.R; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.LinearLayout; import android.widget.ImageButton; import android.widget.Toast; import android.view.MotionEvent; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URLEncoder; import org.json.JSONObject; import android.content.Intent; import android.widget.Button; // 新增导入 import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback, Handler.Callback { private static final String TAG = “EZPreview”; private static final int MSG_VIDEO_SIZE_CHANGED = 1; private static final int MSG_REALPLAY_PLAY_SUCCESS = 2001; private static final int MSG_REALPLAY_PLAY_FAIL = 2002; private static final int MSG_SHOW_STREAM_TYPE = 3001; // 新增消息类型 private static final int DIRECTION_UP = 0; private static final int DIRECTION_DOWN = 1; private static final int DIRECTION_LEFT = 2; private static final int DIRECTION_RIGHT = 3; private static final int DIRECTION_ZOOM_IN = 8; // 物理放大 private static final int DIRECTION_ZOOM_OUT = 9; // 物理缩小 private static final int DIRECTION_FOCUS_NEAR = 10; // 调整近焦距 private static final int DIRECTION_FOCUS_FAR = 11; // 调整远焦距 private static final int SPEED_MEDIUM = 1; // 速度适中 private static final String PTZ_START_URL = “https://open.ys7.com/api/lapp/device/ptz/start”; private static final String PTZ_STOP_URL = “https://open.ys7.com/api/lapp/device/ptz/stop”; private boolean mIsSupportPTZ = false; // 设备是否支持云台 private ExecutorService mExecutorService; // 线程池 private volatile boolean isPTZActive = false; // 标记是否有云台操作正在进行 private volatile int activeDirection = -1; // 当前活动的方向 private boolean mHasShownConnectionSuccess = false; // 接收的参数键 private static final String KEY_APPKEY = “appkey”; private static final String KEY_SERIAL = “serial”; private static final String KEY_VERIFYCODE = “VerifyCode”; private static final String KEY_ACCESSTOKEN = “accessToken”; private static final String KEY_CAMERANO = “cameraNo”; private boolean mIsPlaying = false; private EZPlayer mEZPlayer; private SurfaceView mSurfaceView; private SurfaceHolder mSurfaceHolder; private ProgressBar mLiveProgressBar; private RelativeLayout mRlControl; private LinearLayout mLlHc; private ImageButton mIbRotate2; private RelativeLayout mRaTitle; // 从Intent中获取的参数 private String mAppKey; private String mDeviceSerial; private String mVerifyCode; private String mAccessToken; private int mCameraNo = 0; // 默认通道号0 private Handler mHandler; private boolean mP2PEnabled = true; // 新增:云台控制重试机制相关变量 private static final int MAX_PTZ_RETRIES = 2; private Map<Integer, Integer> ptzRetryCountMap = new ConcurrentHashMap<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activitymain); mHandler = new Handler(this); mRaTitle = findViewById(R.id.ra_title); // 1. 从Intent中获取参数 extractParametersFromIntent(); // 2. 初始化UI initUI(); initOrientationSensitiveViews(); View fanHui = findViewById(R.id.back); fanHui.setOnClickListener(v -> finish()); Button huifangBtn = findViewById(R.id.huifang); huifangBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 创建Intent跳转到FanHui活动 Intent intent = new Intent(MainActivity.this, FanHui.class); // 传递必要参数(可选) intent.putExtra("deviceSerial", mDeviceSerial); intent.putExtra("cameraNo", mCameraNo); intent.putExtra("accessToken", mAccessToken); intent.putExtra("appkey", mAppKey); intent.putExtra("verifyCode", mVerifyCode); startActivity(intent); } }); // 3. 初始化SDK并创建播放器 initSDKAndCreatePlayer(); } private void initOrientationSensitiveViews() { mLiveProgressBar = findViewById(R.id.liveProgressBar); mRlControl = findViewById(R.id.rl_control); mLlHc = findViewById(R.id.ll_hc); mIbRotate2 = findViewById(R.id.ib_rotate2); // 初始状态显示加载 if (mLiveProgressBar != null) { mLiveProgressBar.setVisibility(View.VISIBLE); } // 初始根据方向更新UI updateLayoutByOrientation(); // 创建线程池 mExecutorService = Executors.newFixedThreadPool(2); // 4. 初始化云台控制按钮 initPTZButtons(); } private void initPTZButtons() { // 竖屏布局的按钮 setupPTZButton(R.id.ptz_left_btn, DIRECTION_LEFT); setupPTZButton(R.id.ptz_right_btn, DIRECTION_RIGHT); setupPTZButton(R.id.ptz_top_btn, DIRECTION_UP); setupPTZButton(R.id.ptz_bottom_btn, DIRECTION_DOWN); setupPTZButton(R.id.zoom_add, DIRECTION_ZOOM_IN); // 物理放大 setupPTZButton(R.id.zoom_reduce, DIRECTION_ZOOM_OUT); // 物理缩小 setupPTZButton(R.id.focus_add, DIRECTION_FOCUS_NEAR); // 近焦距 setupPTZButton(R.id.foucus_reduce, DIRECTION_FOCUS_FAR); // 远焦距 setupUnsupportedButton(R.id.guangquan_add, "光圈+"); setupUnsupportedButton(R.id.guangquan_reduce, "光圈-"); // 横屏布局的按钮 setupPTZButton(R.id.ptz_left_btn2, DIRECTION_LEFT); setupPTZButton(R.id.ptz_right_btn2, DIRECTION_RIGHT); setupPTZButton(R.id.ptz_top_btn2, DIRECTION_UP); setupPTZButton(R.id.ptz_bottom_btn2, DIRECTION_DOWN); setupPTZButton(R.id.zoom_add2, DIRECTION_ZOOM_IN); setupPTZButton(R.id.zoom_reduce2, DIRECTION_ZOOM_OUT); setupPTZButton(R.id.focus_add2, DIRECTION_FOCUS_NEAR); // 近焦距 setupPTZButton(R.id.foucus_reduce2, DIRECTION_FOCUS_FAR); // 远焦距 } private void setupUnsupportedButton(int buttonId, String buttonName) { ImageButton button = findViewById(buttonId); if (button != null) { button.setOnClickListener(v -> { Toast.makeText(MainActivity.this, "SDK不支持此功能", Toast.LENGTH_SHORT).show(); }); } } private void setupPTZButton(int buttonId, final int direction) { ImageButton button = findViewById(buttonId); if (button != null) { button.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 按下时开始云台动作 controlPTZ(direction, SPEED_MEDIUM, true); return true; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // 如果这是当前活动的方向,则停止 if (isPTZActive && activeDirection == direction) { controlPTZ(direction, SPEED_MEDIUM, false); } return true; } return false; } }); } } // 重构后的云台控制方法 private void controlPTZ(final int direction, final int speed, final boolean isStart) { // 检查是否允许开始新操作 if (isStart) { if (isPTZActive) { // 如果有活动操作,先停止当前操作 controlPTZ(activeDirection, speed, false); // 延迟100ms后再开始新操作 new Handler().postDelayed(() -> controlPTZ(direction, speed, true), 100); return; } } // 重试次数检查 Integer retryCount = ptzRetryCountMap.getOrDefault(direction, 0); if (retryCount >= MAX_PTZ_RETRIES) { Log.w(TAG, "达到最大重试次数,放弃操作 direction=" + direction); ptzRetryCountMap.remove(direction); resetPTZState(); return; } mExecutorService.execute(() -> { try { String urlStr = isStart ? PTZ_START_URL : PTZ_STOP_URL; URL url = new URL(urlStr); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setDoOutput(true); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); // 构建POST数据 StringBuilder postData = new StringBuilder(); postData.append("accessToken=").append(URLEncoder.encode(mAccessToken, "UTF-8")); postData.append("&deviceSerial=").append(URLEncoder.encode(mDeviceSerial, "UTF-8")); postData.append("&channelNo=").append(mCameraNo); if (isStart) { postData.append("&direction=").append(direction); postData.append("&speed=").append(speed); } else { // 停止时带上方向参数(建议) postData.append("&direction=").append(direction); } // 发送请求 OutputStream os = conn.getOutputStream(); os.write(postData.toString().getBytes("UTF-8")); os.flush(); os.close(); // 处理响应 int responseCode = conn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { // 读取响应内容 InputStream is = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); // 解析JSON响应 JSONObject json = new JSONObject(response.toString()); String code = json.optString("code", "0"); String msg = json.optString("msg", "未知错误"); if ("200".equals(code)) { Log.d(TAG, "PTZ控制成功: " + (isStart ? "开始" : "停止") + " | 方向: " + direction); // 更新状态 if (isStart) { isPTZActive = true; activeDirection = direction; } else { isPTZActive = false; activeDirection = -1; } // 成功时重置重试计数器 ptzRetryCountMap.remove(direction); } else { // 增加重试计数 ptzRetryCountMap.put(direction, retryCount + 1); if (isStart) { Log.w(TAG, "PTZ控制失败,尝试重试 direction=" + direction + ", retry=" + (retryCount + 1)); controlPTZ(direction, speed, true); } else { // 停止命令失败需要特殊处理 handleStopFailure(direction); } handlePTZError(code, msg, isStart); } } else { // 增加重试计数 ptzRetryCountMap.put(direction, retryCount + 1); if (isStart) { Log.w(TAG, "PTZ控制失败,尝试重试 direction=" + direction + ", retry=" + (retryCount + 1)); controlPTZ(direction, speed, true); } else { // 停止命令失败需要特殊处理 handleStopFailure(direction); } Log.e(TAG, "HTTP错误: " + responseCode); runOnUiThread(() -> Toast.makeText(MainActivity.this, "网络请求失败: " + responseCode, Toast.LENGTH_SHORT).show()); } conn.disconnect(); } catch (Exception e) { // 增加重试计数 ptzRetryCountMap.put(direction, retryCount + 1); if (isStart && retryCount < MAX_PTZ_RETRIES) { Log.w(TAG, "PTZ控制异常,尝试重试", e); controlPTZ(direction, speed, true); } else { handleStopFailure(direction); } Log.e(TAG, "PTZ控制异常", e); runOnUiThread(() -> Toast.makeText(MainActivity.this, "云台控制出错: " + e.getMessage(), Toast.LENGTH_SHORT).show()); } }); } // 新增:处理停止失败的情况 private void handleStopFailure(int direction) { runOnUiThread(() -> { // 紧急停止:发送不带方向参数的停止命令 emergencyStopPTZ(); Toast.makeText(MainActivity.this, "云台停止失败,已执行紧急停止", Toast.LENGTH_SHORT).show(); }); // 重置状态 resetPTZState(); } // 新增:紧急停止方法(不带方向参数) private void emergencyStopPTZ() { mExecutorService.execute(() -> { try { URL url = new URL(PTZ_STOP_URL); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setDoOutput(true); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); // 构建不带方向参数的POST数据 StringBuilder postData = new StringBuilder(); postData.append("accessToken=").append(URLEncoder.encode(mAccessToken, "UTF-8")); postData.append("&deviceSerial=").append(URLEncoder.encode(mDeviceSerial, "UTF-8")); postData.append("&channelNo=").append(mCameraNo); // 发送请求 OutputStream os = conn.getOutputStream(); os.write(postData.toString().getBytes("UTF-8")); os.flush(); os.close(); // 处理响应 int responseCode = conn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { // 读取响应内容 InputStream is = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); // 解析JSON响应 JSONObject json = new JSONObject(response.toString()); String code = json.optString("code", "0"); if ("200".equals(code)) { Log.d(TAG, "紧急停止成功"); } else { Log.w(TAG, "紧急停止失败: " + json.optString("msg", "未知错误")); } } else { Log.e(TAG, "紧急停止HTTP错误: " + responseCode); } conn.disconnect(); } catch (Exception e) { Log.e(TAG, "紧急停止异常", e); } }); } // 新增:重置云台状态 private void resetPTZState() { isPTZActive = false; activeDirection = -1; ptzRetryCountMap.clear(); } private void handlePTZError(String code, String msg, boolean isStart) { String errorMessage = msg; // 根据文档映射错误信息 switch (code) { case "10001": errorMessage = "参数错误"; break; case "10002": errorMessage = "accessToken异常或过期"; break; case "20002": errorMessage = "设备不存在"; break; case "20007": errorMessage = "设备不在线"; break; case "60000": errorMessage = "设备不支持云台控制"; mIsSupportPTZ = false; // 更新设备支持状态 break; case "60001": errorMessage = "用户无云台控制权限"; break; case "60020": errorMessage = "不支持该命令"; break; // 添加其他错误码处理... } final String finalMsg = errorMessage; runOnUiThread(() -> { Toast.makeText(MainActivity.this, (isStart ? "开始" : "停止") + "云台控制失败: " + finalMsg, Toast.LENGTH_LONG).show(); // 对于特定错误,重置云台状态 if ("10002".equals(code) || "60000".equals(code)) { isPTZActive = false; activeDirection = -1; } }); } @Override public void onConfigurationChanged(@NonNull Configuration newConfig) { super.onConfigurationChanged(newConfig); // 方向变化时重新初始化视图 initOrientationSensitiveViews(); updateLayoutByOrientation(); } @Override protected void onResume() { super.onResume(); if (mLiveProgressBar != null) { if (mIsPlaying) { mLiveProgressBar.setVisibility(View.GONE); } else { mLiveProgressBar.setVisibility(View.VISIBLE); } } } private void updateLayoutByOrientation() { int orientation = getResources().getConfiguration().orientation; if (orientation == Configuration.ORIENTATION_PORTRAIT) { // 竖屏模式 mRaTitle.setVisibility(View.VISIBLE); mRlControl.setVisibility(View.VISIBLE); mLlHc.setVisibility(View.GONE); mIbRotate2.setVisibility(View.GONE); } else { // 横屏模式 mRaTitle.setVisibility(View.GONE); mRlControl.setVisibility(View.GONE); mLlHc.setVisibility(View.VISIBLE); mIbRotate2.setVisibility(View.VISIBLE); } } /** * 从Intent中提取传递的参数 */ private void extractParametersFromIntent() { Bundle extras = getIntent().getExtras(); if (extras != null) { mAppKey = extras.getString(KEY_APPKEY, ""); mDeviceSerial = extras.getString(KEY_SERIAL, ""); mVerifyCode = extras.getString(KEY_VERIFYCODE, ""); mAccessToken = extras.getString(KEY_ACCESSTOKEN, ""); mCameraNo = extras.getInt(KEY_CAMERANO, 0); Log.d(TAG, "Received parameters:"); Log.d(TAG, "AppKey: " + mAppKey); Log.d(TAG, "DeviceSerial: " + mDeviceSerial); Log.d(TAG, "VerifyCode: " + mVerifyCode); Log.d(TAG, "AccessToken: " + mAccessToken); Log.d(TAG, "CameraNo: " + mCameraNo); } else { Log.e(TAG, "No parameters received from intent"); // 如果没有参数,可以显示错误信息并退出 finish(); } } /** * 初始化UI组件 */ private void initUI() { mSurfaceView = findViewById(R.id.realplay_sv); if (mSurfaceView != null) { mSurfaceHolder = mSurfaceView.getHolder(); mSurfaceHolder.addCallback(this); } else { Log.e(TAG, "SurfaceView not found with ID realplay_sv"); } } /** * 初始化SDK并创建播放器 */ private void initSDKAndCreatePlayer() { try { // 1. 初始化SDK EZOpenSDK.initLib(getApplication(), mAppKey); EZOpenSDK.getInstance().setAccessToken(mAccessToken); // +++ 开启P2P取流方式 +++ EZOpenSDK.enableP2P(true); // 开启P2P取流 Log.d(TAG, "P极取流已启用"); mP2PEnabled = true; // 2. 创建播放器 createPlayer(); } catch (Exception e) { Log.e(TAG, "SDK初始化失败", e); Toast.makeText(this, "SDK初始化失败", Toast.LENGTH_SHORT).show(); } } /** * 创建播放器并开始播放 */ private void createPlayer() { try { // 1. 创建播放器实例 mEZPlayer = EZOpenSDK.getInstance().createPlayer(mDeviceSerial, mCameraNo); // 2. 配置播放器 mEZPlayer.setHandler(mHandler); if (mSurfaceHolder != null) { mEZPlayer.setSurfaceHold(mSurfaceHolder); } if (mVerifyCode != null && !mVerifyCode.isEmpty()) { mEZPlayer.setPlayVerifyCode(mVerifyCode); } Toast.makeText(MainActivity.this, "连接成功", Toast.LENGTH_SHORT).show(); // 3. 开始播放 mEZPlayer.startRealPlay(); mIsPlaying = true; // 标记为正在播放 } catch (Exception e) { Log.e(TAG, "Player creation failed", e); mIsPlaying = false; // 标记为未播放 } } // 处理屏幕旋转按钮点击 public void changeScreen(View view) { Log.d(TAG, "Change screen orientation requested"); int currentOrientation = getResources().getConfiguration().orientation; if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } // 更新UI布局 updateLayoutByOrientation(); } // Surface回调接口实现 @Override public void surfaceCreated(@NonNull SurfaceHolder holder) { if (mEZPlayer != null) { mEZPlayer.setSurfaceHold(holder); } } @Override public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {} @Override public void surfaceDestroyed(@NonNull SurfaceHolder holder) { if (mEZPlayer != null) { mEZPlayer.setSurfaceHold(null); } } @Override protected void onStop() { super.onStop(); // 确保云台停止 if (isPTZActive && activeDirection != -1) { Log.d(TAG, "Activity停止,强制停止云台"); controlPTZ(activeDirection, SPEED_MEDIUM, false); } if (mEZPlayer != null) { mEZPlayer.stopRealPlay(); mIsPlaying = false; // 标记为已停止 } } // Handler回调处理播放状态 @Override public boolean handleMessage(@NonNull Message msg) { Log.d(TAG, "handleMessage: " + msg.what); switch (msg.what) { case MSG_VIDEO_SIZE_CHANGED: break; case MSG_REALPLAY_PLAY_SUCCESS: Log.i(TAG, "播放成功"); mIsPlaying = true; // 获取并显示取流方式 int streamType = mEZPlayer.getStreamFetchType(); String streamTypeName = getStreamTypeName(streamType); Log.d(TAG, "当前取流方式: " + streamTypeName); // 发送消息显示取流方式 Message showMsg = new Message(); showMsg.what = MSG_SHOW_STREAM_TYPE; showMsg.obj = streamTypeName; mHandler.sendMessage(showMsg); runOnUiThread(() -> { if (mLiveProgressBar != null) { mLiveProgressBar.setVisibility(View.GONE); } if (!mHasShownConnectionSuccess) { mHasShownConnectionSuccess = true; } }); // 在播放成功后检查设备是否支持云台 checkDevicePTZSupport(); break; case MSG_REALPLAY_PLAY_FAIL: Log.e(TAG, "播放失败"); mIsPlaying = false; runOnUiThread(() -> { if (mLiveProgressBar != null) { mLiveProgressBar.setVisibility(View.VISIBLE); } }); BaseException error = (BaseException) msg.obj; int errorCode = error.getErrorCode(); if (errorCode == ErrorCode.ERROR_INNER_VERIFYCODE_NEED || errorCode == ErrorCode.ERROR_INNER_VERIFYCODE_ERROR) { mVerifyCode = "123456"; if (mEZPlayer != null) { mEZPlayer.setPlayVerifyCode(mVerifyCode); mEZPlayer.startRealPlay(); } } else { Log.e(TAG, "播放失败,错误码: " + errorCode); } break; case MSG_SHOW_STREAM_TYPE: String type = (String) msg.obj; Toast.makeText(MainActivity.this, "取流方式: " + type + (mP2PEnabled ? " (P2P已启用)" : ""), Toast.LENGTH_LONG).show(); break; } return true; } private void checkDevicePTZSupport() { new Thread(() -> { try { // 这里使用SDK方法检查设备能力 // 如果SDK没有提供方法,可以使用HTTP API查询设备能力 // 简化处理:假设所有设备都支持云台 mIsSupportPTZ = true; // 实际项目中应该查询设备能力 // mIsSupportPTZ = queryDevicePTZCapability(); } catch (Exception e) { Log.e(TAG, "Failed to check PTZ support", e); } }).start(); } @Override protected void onDestroy() { super.onDestroy(); if (mExecutorService != null) { mExecutorService.shutdown(); } // 移除Handler回调避免内存泄漏 if (mHandler != null) { mHandler.removeCallbacksAndMessages(null); } if (mEZPlayer != null) { mEZPlayer.release(); mEZPlayer = null; } } private String getStreamTypeName(int type) { switch (type) { case 0: return "流媒体"; case 1: return "P2P"; case 2: return "内网直连"; case 4: return "云存储"; default: return "未知(" + type + ")"; } } } FanHui.java:package com.videogo.ui.login; import android.app.AlertDialog; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.DatePicker; import android.widget.ImageButton; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.videogo.exception.BaseException; import com.videogo.exception.ErrorCode; import com.videogo.openapi.EZConstants; import com.videogo.openapi.EZPlayer; import androidx.appcompat.app.AppCompatActivity; import com.videogo.openapi.EZOpenSDK; import ezviz.ezopensdk.R; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class FanHui extends AppCompatActivity implements SurfaceHolder.Callback { private static final String TAG = "EZPlayback"; private String mAppKey; private String mDeviceSerial; private String mVerifyCode; private String mAccessToken; private int mCameraNo; private TextView mDateTextView; private int mSelectedYear, mSelectedMonth, mSelectedDay; private static final String KEY_APPKEY = "appkey"; private static final String KEY_SERIAL = "serial"; private static final String KEY_VERIFYCODE = "VerifyCode"; private static final String KEY_ACCESSTOKEN = "accessToken"; private static final String KEY_CAMERANO = "cameraNo"; // 回放录像相关 private static final String VIDEO_BY_TIME_URL = "https://open.ys7.com/api/lapp/video/by/time"; private ExecutorService mExecutorService; private ListView mListView; private PlaybackAdapter mAdapter; private List<VideoInfo> mVideoList = new ArrayList<>(); // 播放器相关 private EZPlayer mEZPlayer; private SurfaceView mPlaybackSurfaceView; private SurfaceHolder mSurfaceHolder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ez_playback_list_page); // 创建线程池 mExecutorService = Executors.newFixedThreadPool(2); extractParametersFromIntent(); final Calendar calendar = Calendar.getInstance(); mSelectedYear = calendar.get(Calendar.YEAR); mSelectedMonth = calendar.get(Calendar.MONTH); mSelectedDay = calendar.get(Calendar.DAY_OF_MONTH); // 初始化视图 initViews(); // 设置日期显示模块 setupDatePicker(); // 默认加载当天的录像 loadVideosForSelectedDate(); // 初始化SDK initSDK(); } private void initSDK() { try { // 初始化萤石云SDK EZOpenSDK.initLib(getApplication(), mAppKey); EZOpenSDK.getInstance().setAccessToken(mAccessToken); } catch (Exception e) { Log.e(TAG, "SDK初始化失败", e); Toast.makeText(this, "SDK初始化失败", Toast.LENGTH_SHORT).show(); } } private void initViews() { // 查找ListView mListView = findViewById(R.id.listView); if (mListView == null) { Log.e(TAG, "ListView not found with ID listView"); return; } // 初始化适配器 mAdapter = new PlaybackAdapter(); mListView.setAdapter(mAdapter); // 设置点击事件 mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { VideoInfo video = mVideoList.get(position); playVideo(video); } }); // 获取播放器视图 - 使用SurfaceView mPlaybackSurfaceView = findViewById(R.id.remote_playback_wnd_sv); if (mPlaybackSurfaceView != null) { // 设置SurfaceHolder回调 mSurfaceHolder = mPlaybackSurfaceView.getHolder(); mSurfaceHolder.addCallback(this); } else { Log.e(TAG, "SurfaceView not found with ID remote_playback_wnd_sv"); } } // SurfaceHolder回调方法 @Override public void surfaceCreated(SurfaceHolder holder) { Log.d(TAG, "Surface created"); // 当Surface创建时,如果有播放器实例,设置SurfaceHolder if (mEZPlayer != null) { mEZPlayer.setSurfaceHold(holder); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.d(TAG, "Surface changed: " + width + "x" + height); } @Override public void surfaceDestroyed(SurfaceHolder holder) { Log.d(TAG, "Surface destroyed"); // 当Surface销毁时,释放播放器资源 stopPlayback(); } private void setupDatePicker() { mDateTextView = findViewById(R.id.date_text); ImageButton datePickerButton = findViewById(R.id.date_picker_button); updateDateDisplay(); datePickerButton.setOnClickListener(v -> showDatePickerDialog()); } private void updateDateDisplay() { String formattedDate = String.format(Locale.getDefault(), "%d年%02d月%02d日", mSelectedYear, mSelectedMonth + 1, // 月份需要+1 mSelectedDay); mDateTextView.setText(formattedDate); } private void showDatePickerDialog() { final AlertDialog dlg = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog).create(); dlg.show(); Window window = dlg.getWindow(); window.setContentView(R.layout.datepicker_layout); // 设置对话框宽度 WindowManager.LayoutParams lp = window.getAttributes(); lp.width = WindowManager.LayoutParams.MATCH_PARENT; window.setAttributes(lp); // 获取并初始化 DatePicker DatePicker dpPicker = window.findViewById(R.id.dpPicker); // 隐藏不需要的视图 ViewGroup rootView = (ViewGroup) dpPicker.getChildAt(0); if (rootView != null) { ViewGroup childView = (ViewGroup) rootView.getChildAt(0); if (childView != null) { childView.getChildAt(2).setVisibility(View.VISIBLE); // 确保月选择器可见 childView.getChildAt(1).setVisibility(View.VISIBLE); } } dpPicker.init(mSelectedYear, mSelectedMonth, mSelectedDay, null); // 设置按钮事件 RelativeLayout yesButton = window.findViewById(R.id.YES); RelativeLayout noButton = window.findViewById(R.id.NO); yesButton.setOnClickListener(v -> { mSelectedYear = dpPicker.getYear(); mSelectedMonth = dpPicker.getMonth(); mSelectedDay = dpPicker.getDayOfMonth(); updateDateDisplay(); dlg.dismiss(); // 加载新选择的日期的录像 loadVideosForSelectedDate(); }); noButton.setOnClickListener(v -> dlg.dismiss()); } private void extractParametersFromIntent() { Bundle extras = getIntent().getExtras(); if (extras != null) { mAppKey = extras.getString(KEY_APPKEY, ""); mDeviceSerial = extras.getString(KEY_SERIAL, ""); mVerifyCode = extras.getString(KEY_VERIFYCODE, ""); mAccessToken = extras.getString(KEY_ACCESSTOKEN, ""); mCameraNo = extras.getInt(KEY_CAMERANO, 0); Log.d(TAG, "Received parameters:"); Log.d(TAG, "AppKey: " + mAppKey); Log.d(TAG, "DeviceSerial: " + mDeviceSerial); Log.d(TAG, "VerifyCode: " + mVerifyCode); Log.d(TAG, "AccessToken: " + mAccessToken); Log.d(TAG, "CameraNo: " + mCameraNo); } else { Log.e(TAG, "No parameters received from intent"); } } private void loadVideosForSelectedDate() { // 计算开始和结束时间戳 Calendar cal = Calendar.getInstance(); cal.set(mSelectedYear, mSelectedMonth, mSelectedDay, 0, 0, 0); long startTime = cal.getTimeInMillis(); cal.set(mSelectedYear, mSelectedMonth, mSelectedDay, 23, 59, 59); long endTime = cal.getTimeInMillis(); // 发起网络请求获取录像 fetchVideosByTime(startTime, endTime); } private void fetchVideosByTime(long startTime, long endTime) { mExecutorService.execute(() -> { try { URL url = new URL(VIDEO_BY_TIME_URL); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setDoOutput(true); conn.setConnectTimeout(10000); conn.setReadTimeout(10000); // 构建POST数据(添加分页参数) StringBuilder postData = new StringBuilder(); postData.append("accessToken=").append(URLEncoder.encode(mAccessToken, "UTF-8")); postData.append("&deviceSerial=").append(URLEncoder.encode(mDeviceSerial, "UTF-8")); postData.append("&channelNo=").append(mCameraNo); postData.append("&startTime=").append(startTime); postData.append("&endTime=").append(endTime); postData.append("&recType=").append(0); // 系统自动选择 postData.append("&version=2.0"); // 添加分页版本 postData.append("&pageSize=100"); // 添加分页大小 // 发送请求 OutputStream os = conn.getOutputStream(); os.write(postData.toString().getBytes("UTF-8")); os.flush(); os.close(); // 处理响应 int responseCode = conn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { // 读取响应内容 InputStream is = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); // 解析JSON响应 JSONObject json = new JSONObject(response.toString()); String code = json.optString("code", "0"); if ("200".equals(code)) { JSONArray data = json.getJSONArray("data"); List<VideoInfo> videos = parseVideoData(data); runOnUiThread(() -> { mVideoList.clear(); mVideoList.addAll(videos); mAdapter.notifyDataSetChanged(); }); } else { String msg = json.optString("msg", "未知错误"); Log.e(TAG, "获取录像失败: " + msg); runOnUiThread(() -> Toast.makeText(FanHui.this, "获取录像失败: " + msg, Toast.LENGTH_SHORT).show()); } } else { Log.e(TAG, "HTTP错误: " + responseCode); runOnUiThread(() -> Toast.makeText(FanHui.this, "网络请求失败: " + responseCode, Toast.LENGTH_SHORT).show()); } conn.disconnect(); } catch (Exception e) { Log.e(TAG, "获取录像异常", e); runOnUiThread(() -> Toast.makeText(FanHui.this, "获取录像出错: " + e.getMessage(), Toast.LENGTH_SHORT).show()); } }); } private List<VideoInfo> parseVideoData(JSONArray data) throws JSONException { List<VideoInfo> videos = new ArrayList<>(); SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); for (int i = 0; i < data.length(); i++) { JSONObject videoObj = data.getJSONObject(i); VideoInfo video = new VideoInfo(); video.id = videoObj.optString("id"); video.startTime = videoObj.optLong("startTime"); video.endTime = videoObj.optLong("endTime"); video.recType = videoObj.optInt("recType"); // 格式化时间显示 Date startDate = new Date(video.startTime); Date endDate = new Date(video.endTime); video.timeRange = sdf.format(startDate) + " - " + sdf.format(endDate); videos.add(video); } return videos; } private void playVideo(VideoInfo video) { // 停止当前播放 stopPlayback(); try { // 创建播放器实例 mEZPlayer = EZOpenSDK.getInstance().createPlayer(mDeviceSerial, mCameraNo); // 配置播放器 - 设置回调处理器 mEZPlayer.setHandler(mHandler); // 设置验证码 mEZPlayer.setPlayVerifyCode(mVerifyCode); // 关联播放视图 - 使用SurfaceHolder(修复方法名) if (mSurfaceHolder != null) { mEZPlayer.setSurfaceHold(mSurfaceHolder); } else { Log.e(TAG, "无法关联播放视图"); Toast.makeText(this, "播放视图未初始化", Toast.LENGTH_SHORT).show(); } // 创建Calendar对象作为参数 Calendar startCal = Calendar.getInstance(); startCal.setTimeInMillis(video.startTime); Calendar endCal = Calendar.getInstance(); endCal.setTimeInMillis(video.endTime); // 开始回放 mEZPlayer.startPlayback(startCal, endCal); Toast.makeText(this, "开始播放录像: " + video.timeRange, Toast.LENGTH_SHORT).show(); } catch (Exception e) { Log.e(TAG, "播放录像失败", e); Toast.makeText(this, "播放录像失败: " + e.getMessage(), Toast.LENGTH_SHORT).show(); } } private void stopPlayback() { if (mEZPlayer != null) { mEZPlayer.stopPlayback(); mEZPlayer.release(); mEZPlayer = null; } } // 播放器回调处理器 private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case EZConstants.EZRealPlayConstants.MSG_REALPLAY_PLAY_SUCCESS: Log.i(TAG, "回放播放成功"); break; case EZConstants.EZRealPlayConstants.MSG_REALPLAY_PLAY_FAIL: Log.e(TAG, "回放播放失败"); BaseException error = (BaseException) msg.obj; int errorCode = error.getErrorCode(); String errorMsg = "播放失败: " + errorCode; // 根据错误码提供更具体的错误信息 if (errorCode == ErrorCode.ERROR_INNER_VERIFYCODE_NEED) { errorMsg = "需要验证码"; } else if (errorCode == ErrorCode.ERROR_INNER_VERIFYCODE_ERROR) { errorMsg = "验证码错误"; } else if (errorCode == ErrorCode.ERROR_TRANSF_ACCESSTOKEN_ERROR) { errorMsg = "accessToken无效"; } Toast.makeText(FanHui.this, errorMsg, Toast.LENGTH_LONG).show(); break; } } }; @Override protected void onDestroy() { super.onDestroy(); stopPlayback(); if (mExecutorService != null) { mExecutorService.shutdown(); } } // 录像信息数据结构 private static class VideoInfo { String id; long startTime; long endTime; int recType; String timeRange; } // 列表适配器 private class PlaybackAdapter extends BaseAdapter { @Override public int getCount() { return mVideoList.size(); } @Override public Object getItem(int position) { return mVideoList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = getLayoutInflater().inflate(R.layout.video_item_layout, parent, false); holder = new ViewHolder(); holder.timeTextView = convertView.findViewById(R.id.time_text); holder.durationTextView = convertView.findViewById(R.id.duration_text); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } VideoInfo video = mVideoList.get(position); // 计算持续时间(分钟) long durationMinutes = (video.endTime - video.startTime) / (1000 * 60); holder.timeTextView.setText(video.timeRange); holder.durationTextView.setText(durationMinutes + "分钟"); return convertView; } class ViewHolder { TextView timeTextView; TextView durationTextView; } } }

MainActivity.java:package com.videogo.ui.login; import android.content.res.Configuration; import android.content.pm.ActivityInfo; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import com.videogo.exception.BaseException; import com.videogo.exception.ErrorCode; import com.videogo.openapi.EZConstants; import com.videogo.openapi.EZOpenSDK; import com.videogo.openapi.EZPlayer; import ezviz.ezopensdk.R; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.LinearLayout; import android.widget.ImageButton; import android.widget.Toast; import android.view.MotionEvent; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URLEncoder; import org.json.JSONObject; import android.content.Intent; import android.widget.Button; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback, Handler.Callback { private static final String TAG = "EZPreview"; private static final int MSG_VIDEO_SIZE_CHANGED = 1; private static final int MSG_REALPLAY_PLAY_SUCCESS = 2001; private static final int MSG_REALPLAY_PLAY_FAIL = 2002; private static final int MSG_SHOW_STREAM_TYPE = 3001; // 新增消息类型 private static final int DIRECTION_UP = 0; private static final int DIRECTION_DOWN = 1; private static final int DIRECTION_LEFT = 2; private static final int DIRECTION_RIGHT = 3; private static final int DIRECTION_ZOOM_IN = 8; // 物理放大 private static final int DIRECTION_ZOOM_OUT = 9; // 物理缩小 private static final int DIRECTION_FOCUS_NEAR = 10; // 调整近焦距 private static final int DIRECTION_FOCUS_FAR = 11; // 调整远焦距 private static final int SPEED_MEDIUM = 1; // 速度适中 private static final String PTZ_START_URL = "https://open.ys7.com/api/lapp/device/ptz/start"; private static final String PTZ_STOP_URL = "https://open.ys7.com/api/lapp/device/ptz/stop"; private boolean mIsSupportPTZ = false; // 设备是否支持云台 private ExecutorService mExecutorService; // 线程池 private volatile boolean isPTZActive = false; // 标记是否有云台操作正在进行 private volatile int activeDirection = -1; // 当前活动的方向 private boolean mHasShownConnectionSuccess = false; // 接收的参数键 private static final String KEY_APPKEY = "appkey"; private static final String KEY_SERIAL = "serial"; private static final String KEY_VERIFYCODE = "VerifyCode"; private static final String KEY_ACCESSTOKEN = "accessToken"; private static final String KEY_CAMERANO = "cameraNo"; private boolean mIsPlaying = false; private EZPlayer mEZPlayer; private SurfaceView mSurfaceView; private SurfaceHolder mSurfaceHolder; private ProgressBar mLiveProgressBar; private RelativeLayout mRlControl; private LinearLayout mLlHc; private ImageButton mIbRotate2; private RelativeLayout mRaTitle; // 从Intent中获取的参数 private String mAppKey; private String mDeviceSerial; private String mVerifyCode; private String mAccessToken; private int mCameraNo = 0; // 默认通道号0 private Handler mHandler; private boolean mP2PEnabled = true; // 新增:云台控制重试机制相关变量 private static final int MAX_PTZ_RETRIES = 2; private Map<Integer, Integer> ptzRetryCountMap = new ConcurrentHashMap<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activitymain); mHandler = new Handler(this); mRaTitle = findViewById(R.id.ra_title); // 1. 从Intent中获取参数 extractParametersFromIntent(); // 2. 初始化UI initUI(); initOrientationSensitiveViews(); View fanHui = findViewById(R.id.back); fanHui.setOnClickListener(v -> finish()); Button huifangBtn = findViewById(R.id.huifang); huifangBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 创建Intent跳转到FanHui活动 Intent intent = new Intent(MainActivity.this, FanHui.class); // 传递必要参数(可选) intent.putExtra("deviceSerial", mDeviceSerial); intent.putExtra("cameraNo", mCameraNo); intent.putExtra("accessToken", mAccessToken); intent.putExtra("appkey", mAppKey); intent.putExtra("verifyCode", mVerifyCode); startActivity(intent); } }); // 3. 初始化SDK并创建播放器 initSDKAndCreatePlayer(); } private void initOrientationSensitiveViews() { mLiveProgressBar = findViewById(R.id.liveProgressBar); mRlControl = findViewById(R.id.rl_control); mLlHc = findViewById(R.id.ll_hc); mIbRotate2 = findViewById(R.id.ib_rotate2); // 初始状态显示加载 if (mLiveProgressBar != null) { mLiveProgressBar.setVisibility(View.VISIBLE); } // 初始根据方向更新UI updateLayoutByOrientation(); // 创建线程池 mExecutorService = Executors.newFixedThreadPool(2); // 4. 初始化云台控制按钮 initPTZButtons(); } private void initPTZButtons() { // 竖屏布局的按钮 setupPTZButton(R.id.ptz_left_btn, DIRECTION_LEFT); setupPTZButton(R.id.ptz_right_btn, DIRECTION_RIGHT); setupPTZButton(R.id.ptz_top_btn, DIRECTION_UP); setupPTZButton(R.id.ptz_bottom_btn, DIRECTION_DOWN); setupPTZButton(R.id.zoom_add, DIRECTION_ZOOM_IN); // 物理放大 setupPTZButton(R.id.zoom_reduce, DIRECTION_ZOOM_OUT); // 物理缩小 setupPTZButton(R.id.focus_add, DIRECTION_FOCUS_NEAR); // 近焦距 setupPTZButton(R.id.foucus_reduce, DIRECTION_FOCUS_FAR); // 远焦距 setupUnsupportedButton(R.id.guangquan_add, "光圈+"); setupUnsupportedButton(R.id.guangquan_reduce, "光圈-"); // 横屏布局的按钮 setupPTZButton(R.id.ptz_left_btn2, DIRECTION_LEFT); setupPTZButton(R.id.ptz_right_btn2, DIRECTION_RIGHT); setupPTZButton(R.id.ptz_top_btn2, DIRECTION_UP); setupPTZButton(R.id.ptz_bottom_btn2, DIRECTION_DOWN); setupPTZButton(R.id.zoom_add2, DIRECTION_ZOOM_IN); setupPTZButton(R.id.zoom_reduce2, DIRECTION_ZOOM_OUT); setupPTZButton(R.id.focus_add2, DIRECTION_FOCUS_NEAR); // 近焦距 setupPTZButton(R.id.foucus_reduce2, DIRECTION_FOCUS_FAR); // 远焦距 } private void setupUnsupportedButton(int buttonId, String buttonName) { ImageButton button = findViewById(buttonId); if (button != null) { button.setOnClickListener(v -> { Toast.makeText(MainActivity.this, "SDK不支持此功能", Toast.LENGTH_SHORT).show(); }); } } private void setupPTZButton(int buttonId, final int direction) { ImageButton button = findViewById(buttonId); if (button != null) { button.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 按下时开始云台动作 controlPTZ(direction, SPEED_MEDIUM, true); return true; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // 如果这是当前活动的方向,则停止 if (isPTZActive && activeDirection == direction) { controlPTZ(direction, SPEED_MEDIUM, false); } return true; } return false; } }); } } // 重构后的云台控制方法 private void controlPTZ(final int direction, final int speed, final boolean isStart) { // 检查是否允许开始新操作 if (isStart) { if (isPTZActive) { // 如果有活动操作,先停止当前操作 controlPTZ(activeDirection, speed, false); // 延迟100ms后再开始新操作 new Handler().postDelayed(() -> controlPTZ(direction, speed, true), 100); return; } } // 重试次数检查 Integer retryCount = ptzRetryCountMap.getOrDefault(direction, 0); if (retryCount >= MAX_PTZ_RETRIES) { Log.w(TAG, "达到最大重试次数,放弃操作 direction=" + direction); ptzRetryCountMap.remove(direction); resetPTZState(); return; } mExecutorService.execute(() -> { try { String urlStr = isStart ? PTZ_START_URL : PTZ_STOP_URL; URL url = new URL(urlStr); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setDoOutput(true); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); // 构建POST数据 StringBuilder postData = new StringBuilder(); postData.append("accessToken=").append(URLEncoder.encode(mAccessToken, "UTF-8")); postData.append("&deviceSerial=").append(URLEncoder.encode(mDeviceSerial, "UTF-8")); postData.append("&channelNo=").append(mCameraNo); if (isStart) { postData.append("&direction=").append(direction); postData.append("&speed=").append(speed); } else { // 停止时带上方向参数(建议) postData.append("&direction=").append(direction); } // 发送请求 OutputStream os = conn.getOutputStream(); os.write(postData.toString().getBytes("UTF-8")); os.flush(); os.close(); // 处理响应 int responseCode = conn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { // 读取响应内容 InputStream is = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); // 解析JSON响应 JSONObject json = new JSONObject(response.toString()); String code = json.optString("code", "0"); String msg = json.optString("msg", "未知错误"); if ("200".equals(code)) { Log.d(TAG, "PTZ控制成功: " + (isStart ? "开始" : "停止") + " | 方向: " + direction); // 更新状态 if (isStart) { isPTZActive = true; activeDirection = direction; } else { isPTZActive = false; activeDirection = -1; } // 成功时重置重试计数器 ptzRetryCountMap.remove(direction); } else { // 增加重试计数 ptzRetryCountMap.put(direction, retryCount + 1); if (isStart) { Log.w(TAG, "PTZ控制失败,尝试重试 direction=" + direction + ", retry=" + (retryCount + 1)); controlPTZ(direction, speed, true); } else { // 停止命令失败需要特殊处理 handleStopFailure(direction); } handlePTZError(code, msg, isStart); } } else { // 增加重试计数 ptzRetryCountMap.put(direction, retryCount + 1); if (isStart) { Log.w(TAG, "PTZ控制失败,尝试重试 direction=" + direction + ", retry=" + (retryCount + 1)); controlPTZ(direction, speed, true); } else { // 停止命令失败需要特殊处理 handleStopFailure(direction); } Log.e(TAG, "HTTP错误: " + responseCode); runOnUiThread(() -> Toast.makeText(MainActivity.this, "网络请求失败: " + responseCode, Toast.LENGTH_SHORT).show()); } conn.disconnect(); } catch (Exception e) { // 增加重试计数 ptzRetryCountMap.put(direction, retryCount + 1); if (isStart && retryCount < MAX_PTZ_RETRIES) { Log.w(TAG, "PTZ控制异常,尝试重试", e); controlPTZ(direction, speed, true); } else { handleStopFailure(direction); } Log.e(TAG, "PTZ控制异常", e); runOnUiThread(() -> Toast.makeText(MainActivity.this, "云台控制出错: " + e.getMessage(), Toast.LENGTH_SHORT).show()); } }); } // 新增:处理停止失败的情况 private void handleStopFailure(int direction) { runOnUiThread(() -> { // 紧急停止:发送不带方向参数的停止命令 emergencyStopPTZ(); Toast.makeText(MainActivity.this, "云台停止失败,已执行紧急停止", Toast.LENGTH_SHORT).show(); }); // 重置状态 resetPTZState(); } // 新增:紧急停止方法(不带方向参数) private void emergencyStopPTZ() { mExecutorService.execute(() -> { try { URL url = new URL(PTZ_STOP_URL); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setDoOutput(true); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); // 构建不带方向参数的POST数据 StringBuilder postData = new StringBuilder(); postData.append("accessToken=").append(URLEncoder.encode(mAccessToken, "UTF-8")); postData.append("&deviceSerial=").append(URLEncoder.encode(mDeviceSerial, "UTF-8")); postData.append("&channelNo=").append(mCameraNo); // 发送请求 OutputStream os = conn.getOutputStream(); os.write(postData.toString().getBytes("UTF-8")); os.flush(); os.close(); // 处理响应 int responseCode = conn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { // 读取响应内容 InputStream is = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); // 解析JSON响应 JSONObject json = new JSONObject(response.toString()); String code = json.optString("code", "0"); if ("200".equals(code)) { Log.d(TAG, "紧急停止成功"); } else { Log.w(TAG, "紧急停止失败: " + json.optString("msg", "未知错误")); } } else { Log.e(TAG, "紧急停止HTTP错误: " + responseCode); } conn.disconnect(); } catch (Exception e) { Log.e(TAG, "紧急停止异常", e); } }); } // 新增:重置云台状态 private void resetPTZState() { isPTZActive = false; activeDirection = -1; ptzRetryCountMap.clear(); } private void handlePTZError(String code, String msg, boolean isStart) { String errorMessage = msg; // 根据文档映射错误信息 switch (code) { case "10001": errorMessage = "参数错误"; break; case "10002": errorMessage = "accessToken异常或过期"; break; case "20002": errorMessage = "设备不存在"; break; case "20007": errorMessage = "设备不在线"; break; case "60000": errorMessage = "设备不支持云台控制"; mIsSupportPTZ = false; // 更新设备支持状态 break; case "60001": errorMessage = "用户无云台控制权限"; break; case "60020": errorMessage = "不支持该命令"; break; // 添加其他错误码处理... } final String finalMsg = errorMessage; runOnUiThread(() -> { Toast.makeText(MainActivity.this, (isStart ? "开始" : "停止") + "云台控制失败: " + finalMsg, Toast.LENGTH_LONG).show(); // 对于特定错误,重置云台状态 if ("10002".equals(code) || "60000".equals(code)) { isPTZActive = false; activeDirection = -1; } }); } @Override public void onConfigurationChanged(@NonNull Configuration newConfig) { super.onConfigurationChanged(newConfig); // 方向变化时重新初始化视图 initOrientationSensitiveViews(); updateLayoutByOrientation(); } @Override protected void onResume() { super.onResume(); if (mLiveProgressBar != null) { if (mIsPlaying) { mLiveProgressBar.setVisibility(View.GONE); } else { mLiveProgressBar.setVisibility(View.VISIBLE); } } } private void updateLayoutByOrientation() { int orientation = getResources().getConfiguration().orientation; if (orientation == Configuration.ORIENTATION_PORTRAIT) { // 竖屏模式 mRaTitle.setVisibility(View.VISIBLE); mRlControl.setVisibility(View.VISIBLE); mLlHc.setVisibility(View.GONE); mIbRotate2.setVisibility(View.GONE); } else { // 横屏模式 mRaTitle.setVisibility(View.GONE); mRlControl.setVisibility(View.GONE); mLlHc.setVisibility(View.VISIBLE); mIbRotate2.setVisibility(View.VISIBLE); } } /** * 从Intent中提取传递的参数 */ private void extractParametersFromIntent() { Bundle extras = getIntent().getExtras(); if (extras != null) { mAppKey = extras.getString(KEY_APPKEY, ""); mDeviceSerial = extras.getString(KEY_SERIAL, ""); mVerifyCode = extras.getString(KEY_VERIFYCODE, ""); mAccessToken = extras.getString(KEY_ACCESSTOKEN, ""); mCameraNo = extras.getInt(KEY_CAMERANO, 0); Log.d(TAG, "Received parameters:"); Log.d(TAG, "AppKey: " + mAppKey); Log.d(TAG, "DeviceSerial: " + mDeviceSerial); Log.d(TAG, "VerifyCode: " + mVerifyCode); Log.d(TAG, "AccessToken: " + mAccessToken); Log.d(TAG, "CameraNo: " + mCameraNo); } else { Log.e(TAG, "No parameters received from intent"); // 如果没有参数,可以显示错误信息并退出 finish(); } } /** * 初始化UI组件 */ private void initUI() { mSurfaceView = findViewById(R.id.realplay_sv); if (mSurfaceView != null) { mSurfaceHolder = mSurfaceView.getHolder(); mSurfaceHolder.addCallback(this); } else { Log.e(TAG, "SurfaceView not found with ID realplay_sv"); } } /** * 初始化SDK并创建播放器 */ private void initSDKAndCreatePlayer() { try { // 1. 初始化SDK EZOpenSDK.initLib(getApplication(), mAppKey); EZOpenSDK.getInstance().setAccessToken(mAccessToken); // +++ 开启P2P取流方式 +++ EZOpenSDK.enableP2P(true); // 开启P2P取流 Log.d(TAG, "P极取流已启用"); mP2PEnabled = true; // 2. 创建播放器 createPlayer(); } catch (Exception e) { Log.e(TAG, "SDK初始化失败", e); Toast.makeText(this, "SDK初始化失败", Toast.LENGTH_SHORT).show(); } } /** * 创建播放器并开始播放 */ private void createPlayer() { try { // 1. 创建播放器实例 mEZPlayer = EZOpenSDK.getInstance().createPlayer(mDeviceSerial, mCameraNo); // 2. 配置播放器 mEZPlayer.setHandler(mHandler); if (mSurfaceHolder != null) { mEZPlayer.setSurfaceHold(mSurfaceHolder); } if (mVerifyCode != null && !mVerifyCode.isEmpty()) { mEZPlayer.setPlayVerifyCode(mVerifyCode); } Toast.makeText(MainActivity.this, "连接成功", Toast.LENGTH_SHORT).show(); // 3. 开始播放 mEZPlayer.startRealPlay(); mIsPlaying = true; // 标记为正在播放 } catch (Exception e) { Log.e(TAG, "Player creation failed", e); mIsPlaying = false; // 标记为未播放 } } // 处理屏幕旋转按钮点击 public void changeScreen(View view) { Log.d(TAG, "Change screen orientation requested"); int currentOrientation = getResources().getConfiguration().orientation; if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } // 更新UI布局 updateLayoutByOrientation(); } // Surface回调接口实现 @Override public void surfaceCreated(@NonNull SurfaceHolder holder) { if (mEZPlayer != null) { mEZPlayer.setSurfaceHold(holder); } } @Override public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {} @Override public void surfaceDestroyed(@NonNull SurfaceHolder holder) { if (mEZPlayer != null) { mEZPlayer.setSurfaceHold(null); } } @Override protected void onStop() { super.onStop(); // 确保云台停止 if (isPTZActive && activeDirection != -1) { Log.d(TAG, "Activity停止,强制停止云台"); controlPTZ(activeDirection, SPEED_MEDIUM, false); } if (mEZPlayer != null) { mEZPlayer.stopRealPlay(); mIsPlaying = false; // 标记为已停止 } } // Handler回调处理播放状态 @Override public boolean handleMessage(@NonNull Message msg) { Log.d(TAG, "handleMessage: " + msg.what); switch (msg.what) { case MSG_VIDEO_SIZE_CHANGED: break; case MSG_REALPLAY_PLAY_SUCCESS: Log.i(TAG, "播放成功"); mIsPlaying = true; // 获取并显示取流方式 int streamType = mEZPlayer.getStreamFetchType(); String streamTypeName = getStreamTypeName(streamType); Log.d(TAG, "当前取流方式: " + streamTypeName); // 发送消息显示取流方式 Message showMsg = new Message(); showMsg.what = MSG_SHOW_STREAM_TYPE; showMsg.obj = streamTypeName; mHandler.sendMessage(showMsg); runOnUiThread(() -> { if (mLiveProgressBar != null) { mLiveProgressBar.setVisibility(View.GONE); } if (!mHasShownConnectionSuccess) { mHasShownConnectionSuccess = true; } }); // 在播放成功后检查设备是否支持云台 checkDevicePTZSupport(); break; case MSG_REALPLAY_PLAY_FAIL: Log.e(TAG, "播放失败"); mIsPlaying = false; runOnUiThread(() -> { if (mLiveProgressBar != null) { mLiveProgressBar.setVisibility(View.VISIBLE); } }); BaseException error = (BaseException) msg.obj; int errorCode = error.getErrorCode(); if (errorCode == ErrorCode.ERROR_INNER_VERIFYCODE_NEED || errorCode == ErrorCode.ERROR_INNER_VERIFYCODE_ERROR) { mVerifyCode = "123456"; if (mEZPlayer != null) { mEZPlayer.setPlayVerifyCode(mVerifyCode); mEZPlayer.startRealPlay(); } } else { Log.e(TAG, "播放失败,错误码: " + errorCode); } break; case MSG_SHOW_STREAM_TYPE: String type = (String) msg.obj; Toast.makeText(MainActivity.this, "取流方式: " + type + (mP2PEnabled ? " (P2P已启用)" : ""), Toast.LENGTH_LONG).show(); break; } return true; } private void checkDevicePTZSupport() { new Thread(() -> { try { // 这里使用SDK方法检查设备能力 // 如果SDK没有提供方法,可以使用HTTP API查询设备能力 // 简化处理:假设所有设备都支持云台 mIsSupportPTZ = true; // 实际项目中应该查询设备能力 // mIsSupportPTZ = queryDevicePTZCapability(); } catch (Exception e) { Log.e(TAG, "Failed to check PTZ support", e); } }).start(); } @Override protected void onDestroy() { super.onDestroy(); if (mExecutorService != null) { mExecutorService.shutdown(); } // 移除Handler回调避免内存泄漏 if (mHandler != null) { mHandler.removeCallbacksAndMessages(null); } if (mEZPlayer != null) { mEZPlayer.release(); mEZPlayer = null; } } private String getStreamTypeName(int type) { switch (type) { case 0: return "流媒体"; case 1: return "P2P"; case 2: return "内网直连"; case 4: return "云存储"; default: return "未知(" + type + ")"; } } } FanHui.java:package com.videogo.ui.login; import android.app.AlertDialog; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.text.TextUtils; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.DatePicker; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import android.content.res.Configuration; import com.videogo.exception.BaseException; import com.videogo.exception.ErrorCode; import com.videogo.openapi.EZPlayer; import androidx.appcompat.app.AppCompatActivity; import com.videogo.openapi.EZOpenSDK; import ezviz.ezopensdk.R; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import android.content.pm.ActivityInfo; import com.videogo.widget.CheckTextButton; public class FanHui extends AppCompatActivity implements SurfaceHolder.Callback { private static final String TAG = "EZPlayback"; private String mAppKey; private String mDeviceSerial; private String mVerifyCode; private String mAccessToken; private int mCameraNo; private TextView mDateTextView; private int mSelectedYear, mSelectedMonth, mSelectedDay; private static final String KEY_APPKEY = "appkey"; private static final String KEY_SERIAL = "deviceSerial"; private static final String KEY_VERIFYCODE = "verifyCode"; private static final String KEY_ACCESSTOKEN = "accessToken"; private static final String KEY_CAMERANO = "cameraNo"; private static final int MSG_PLAYBACK_PLAY_SUCCESS = 3001; private static final int MSG_PLAYBACK_PLAY_FAIL = 3002; private static final int MSG_PLAYBACK_STOP = 3003; // 更新API地址为云存储专用接口 private static final String VIDEO_BY_TIME_URL = "https://open.ys7.com/api/lapp/video/by/time"; // private static final String PLAYBACK_URL_API = "https://open.ys7.com/api/lapp/v2/live/address/get"; private boolean isFullScreen = false; private com.videogo.widget.TitleBar mTitleBar; private ViewGroup mPlaybackArea; private LinearLayout mControlArea; private RelativeLayout mDisplayLayout; private ImageButton mExitFullScreenButton; private ExecutorService mExecutorService; private ListView mListView; private PlaybackAdapter mAdapter; private List<VideoInfo> mVideoList = new ArrayList<>(); private LinearLayout mNoVideoLayout; // 播放器相关 private EZPlayer mEZPlayer; private SurfaceView mPlaybackSurfaceView; private SurfaceHolder mSurfaceHolder; private boolean isVideoPlaying = false; // 跟踪视频播放状态 private ImageButton mPauseButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ez_playback_list_page); View fanHui = findViewById(R.id.fanhui); fanHui.setOnClickListener(v -> finish()); // 创建线程池 mExecutorService = Executors.newFixedThreadPool(2); extractParametersFromIntent(); final Calendar calendar = Calendar.getInstance(); mSelectedYear = calendar.get(Calendar.YEAR); mSelectedMonth = calendar.get(Calendar.MONTH); mSelectedDay = calendar.get(Calendar.DAY_OF_MONTH); // 初始化视图 initViews(); mPlaybackArea = findViewById(R.id.remote_playback_area); mControlArea = findViewById(R.id.control_area); mDisplayLayout = findViewById(R.id.display_layout); mExitFullScreenButton = findViewById(R.id.exit_btn); // 设置日期显示模块 setupDatePicker(); // 使用MainActivity已初始化的SDK实例 EZOpenSDK.getInstance().setAccessToken(mAccessToken); // 默认加载当天的录像 loadVideosForSelectedDate(); setupFullscreenButton(); mTitleBar = findViewById(R.id.title); if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT ); mPlaybackArea.setLayoutParams(params); } } private void initViews() { // 查找ListView mListView = findViewById(R.id.listView); if (mListView == null) { Log.e(TAG, "ListView not found with ID listView"); return; } mNoVideoLayout = findViewById(R.id.novideo_img_cloud); // 初始化适配器 mAdapter = new PlaybackAdapter(); mListView.setAdapter(mAdapter); // 设置点击事件 mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { VideoInfo video = mVideoList.get(position); playVideo(video); } }); // 获取播放器视图 - 使用SurfaceView mPlaybackSurfaceView = findViewById(R.id.remote_playback_wnd_sv); mPauseButton = findViewById(R.id.remote_playback_pause_btn); mPauseButton.setOnClickListener(v -> togglePlayPause()); if (mPlaybackSurfaceView != null) { // 设置SurfaceHolder回调 mSurfaceHolder = mPlaybackSurfaceView.getHolder(); mSurfaceHolder.addCallback(this); } else { Log.e(TAG, "SurfaceView not found with ID remote_playback_wnd_sv"); } } private void togglePlayPause() { if (mEZPlayer == null) return; if (isVideoPlaying) { // 当前正在播放 → 暂停 try { mEZPlayer.pausePlayback(); mPauseButton.setImageResource(R.drawable.play_full_play_sel); // 切换为播放图标 isVideoPlaying = false; } catch (Exception e) { Log.e(TAG, "暂停播放失败", e); } } else { // 当前已暂停 → 继续播放 try { mEZPlayer.resumePlayback(); mPauseButton.setImageResource(R.drawable.play_full_pause_sel); // 切换为暂停图标 isVideoPlaying = true; } catch (Exception e) { Log.e(TAG, "继续播放失败", e); } } } // SurfaceHolder回调方法 @Override public void surfaceCreated(SurfaceHolder holder) { Log.d(TAG, "Surface created"); // 当Surface创建时,如果有播放器实例,设置SurfaceHolder if (mEZPlayer != null) { mEZPlayer.setSurfaceHold(holder); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.d(TAG, "Surface changed: " + width + "x" + height); } @Override public void surfaceDestroyed(SurfaceHolder holder) { Log.d(TAG, "Surface destroyed"); // 当Surface销毁时,释放播放器资源 stopPlayback(); } private void setupDatePicker() { mDateTextView = findViewById(R.id.date_text); ImageButton datePickerButton = findViewById(R.id.date_picker_button); updateDateDisplay(); datePickerButton.setOnClickListener(v -> showDatePickerDialog()); } private void updateDateDisplay() { String formattedDate = String.format(Locale.getDefault(), "%d年%02d月%02d日", mSelectedYear, mSelectedMonth + 1, // 月份需要+1 mSelectedDay); mDateTextView.setText(formattedDate); } private void showDatePickerDialog() { final AlertDialog dlg = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog).create(); dlg.show(); Window window = dlg.getWindow(); window.setContentView(R.layout.datepicker_layout); // 设置对话框宽度 WindowManager.LayoutParams lp = window.getAttributes(); lp.width = WindowManager.LayoutParams.MATCH_PARENT; window.setAttributes(lp); // 获取并初始化 DatePicker DatePicker dpPicker = window.findViewById(R.id.dpPicker); // 确保日期选择器正确显示所有组件 ViewGroup rootView = (ViewGroup) dpPicker.getChildAt(0); if (rootView != null) { ViewGroup childView = (ViewGroup) rootView.getChildAt(0); if (childView != null) { // 确保所有选择器组件可见 for (int i = 0; i < childView.getChildCount(); i++) { childView.getChildAt(i).setVisibility(View.VISIBLE); } } } dpPicker.init(mSelectedYear, mSelectedMonth, mSelectedDay, null); // 设置按钮事件 RelativeLayout yesButton = window.findViewById(R.id.YES); RelativeLayout noButton = window.findViewById(R.id.NO); yesButton.setOnClickListener(v -> { mSelectedYear = dpPicker.getYear(); mSelectedMonth = dpPicker.getMonth(); mSelectedDay = dpPicker.getDayOfMonth(); updateDateDisplay(); dlg.dismiss(); // 加载新选择的日期的录像 loadVideosForSelectedDate(); }); noButton.setOnClickListener(v -> dlg.dismiss()); } private void extractParametersFromIntent() { Bundle extras = getIntent().getExtras(); if (extras != null) { mAppKey = extras.getString(KEY_APPKEY, ""); mDeviceSerial = extras.getString(KEY_SERIAL, "").toUpperCase(); mVerifyCode = extras.getString(KEY_VERIFYCODE, ""); mAccessToken = extras.getString(KEY_ACCESSTOKEN, ""); mCameraNo = extras.getInt(KEY_CAMERANO, 1); // 默认为通道1 Log.d(TAG, "Received parameters:"); Log.d(TAG, "AppKey: " + mAppKey); Log.d(TAG, "DeviceSerial (Upper): " + mDeviceSerial); Log.d(TAG, "VerifyCode: " + mVerifyCode); Log.d(TAG, "AccessToken: " + mAccessToken); Log.d(TAG, "CameraNo: " + mCameraNo); } else { Log.e(TAG, "No parameters received from intent"); } } private void loadVideosForSelectedDate() { if (TextUtils.isEmpty(mDeviceSerial) || TextUtils.isEmpty(mAccessToken)) { Toast.makeText(this, "设备参数不完整", Toast.LENGTH_SHORT).show(); return; } // 计算开始和结束时间戳 Calendar cal = Calendar.getInstance(); cal.set(mSelectedYear, mSelectedMonth, mSelectedDay, 0, 0, 0); long startTime = cal.getTimeInMillis(); long maxEndTime = System.currentTimeMillis(); cal.set(mSelectedYear, mSelectedMonth, mSelectedDay, 23, 59, 59); long endTime = Math.min(cal.getTimeInMillis(), maxEndTime); // 发起网络请求获取录像 fetchVideosByTime(startTime, endTime); } private void fetchVideosByTime(long startTime, long endTime) { if (isFinishing() || isDestroyed()) return; // 加载开始时隐藏无录像提示 runOnUiThread(() -> { if (mNoVideoLayout != null) { mNoVideoLayout.setVisibility(View.GONE); } if (!isFinishing()) { Toast.makeText(FanHui.this, "正在加载可播录像", Toast.LENGTH_SHORT).show(); } }); final String deviceSerial = mDeviceSerial.toUpperCase(); mExecutorService.execute(() -> { HttpURLConnection conn = null; try { String currentUrl = VIDEO_BY_TIME_URL; int redirectCount = 0; final int MAX_REDIRECTS = 3; while (redirectCount < MAX_REDIRECTS) { URL url = new URL(currentUrl); conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setDoOutput(true); conn.setConnectTimeout(15000); conn.setReadTimeout(30000); // 构建POST数据 StringBuilder postData = new StringBuilder(); postData.append("accessToken=").append(URLEncoder.encode(mAccessToken, "UTF-8")); postData.append("&deviceSerial=").append(URLEncoder.encode(deviceSerial, "UTF-8")); postData.append("&channelNo=").append(mCameraNo); postData.append("&startTime=").append(startTime); postData.append("&endTime=").append(endTime); postData.append("&recType=0"); // 1-云存储录像 0-系统自动选择 postData.append("&version=2.0"); // 分页版本 postData.append("&pageSize=100"); // 分页大小 OutputStream os = conn.getOutputStream(); os.write(postData.toString().getBytes("UTF-8")); os.flush(); os.close(); int responseCode = conn.getResponseCode(); // 处理重定向 if (responseCode == HttpURLConnection.HTTP_MOVED_TEMP || responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_SEE_OTHER) { String newUrl = conn.getHeaderField("Location"); if (newUrl == null) break; currentUrl = newUrl; redirectCount++; conn.disconnect(); continue; } // 处理正常响应 if (responseCode == HttpURLConnection.HTTP_OK) { InputStream is = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); // 明确指定UTF-8编码 StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); String responseString = response.toString(); Log.d(TAG, "API响应: " + responseString); // 记录原始响应 // 检查是否是HTML响应 if (responseString.startsWith("<html>") || responseString.startsWith("<!DOCTYPE")) { Log.e(TAG, "服务器返回HTML: " + responseString); runOnUiThread(() -> { if (!isFinishing()) { Toast.makeText(FanHui.this, "服务器返回错误页面", Toast.LENGTH_LONG).show(); } }); return; } // 解析JSON响应 try { JSONObject json = new JSONObject(responseString); String code = json.optString("code", "0"); if ("200".equals(code)) { Object dataObj = json.opt("data"); List<VideoInfo> videos = new ArrayList<>(); if (dataObj == null) { // 处理data为null的情况(无录像) Log.w(TAG, "API返回data为null,表示没有录像"); } else if (dataObj instanceof JSONArray) { // 处理数组格式响应 JSONArray dataArray = (JSONArray) dataObj; videos = parseVideoData(dataArray); } else if (dataObj instanceof JSONObject) { // 处理分页格式响应 JSONObject dataObject = (JSONObject) dataObj; // 使用 optJSONArray 安全处理 null 值 JSONArray filesArray = dataObject.optJSONArray("files"); if (filesArray != null) { videos = parseVideoData(filesArray); } else { JSONArray recordsArray = dataObject.optJSONArray("records"); if (recordsArray != null) { videos = parseVideoData(recordsArray); } else { JSONArray listArray = dataObject.optJSONArray("list"); if (listArray != null) { videos = parseVideoData(listArray); } else { Log.w(TAG, "分页结构缺少有效的录像数组字段"); // 尝试从其他可能字段获取 if (dataObject.has("videoList")) { videos = parseVideoData(dataObject.optJSONArray("videoList")); } else { Log.w(TAG, "API 返回的分页结构不包含有效录像数据: " + dataObject.toString()); } } } } } else { Log.w(TAG, "未知的data类型: " + dataObj.getClass().getSimpleName()); // 尝试强制转换 try { videos = parseVideoData(new JSONArray().put(dataObj)); } catch (Exception e) { Log.e(TAG, "强制转换失败", e); } } // 更新UI显示录像列表 List<VideoInfo> finalVideos = videos; runOnUiThread(() -> { mVideoList.clear(); mVideoList.addAll(finalVideos); mAdapter.notifyDataSetChanged(); // 根据录像数据控制提示布局可见性 if (finalVideos.isEmpty()) { Toast.makeText(FanHui.this, "该时间段没有录像", Toast.LENGTH_SHORT).show(); if (mNoVideoLayout != null) { mNoVideoLayout.setVisibility(View.VISIBLE); // 显示无录像提示 } } else { if (mNoVideoLayout != null) { mNoVideoLayout.setVisibility(View.GONE); // 隐藏无录像提示 } } }); } else { String msg = json.optString("msg", "未知错误"); Log.e(TAG, "获取录像失败: " + msg); runOnUiThread(() -> Toast.makeText(FanHui.this, "获取录像失败: " + msg, Toast.LENGTH_SHORT).show()); } } catch (JSONException e) { Log.e(TAG, "JSON解析错误: " + e.getMessage(), e); // 添加原始响应内容日志 Log.e(TAG, "原始响应内容: " + responseString); runOnUiThread(() -> Toast.makeText(FanHui.this, "数据格式错误: " + e.getMessage(), Toast.LENGTH_LONG).show()); } break; // 跳出重定向循环 } else { Log.e(TAG, "HTTP错误: " + responseCode); if (!isFinishing() && !isDestroyed()) { runOnUiThread(() -> Toast.makeText(FanHui.this, "网络请求失败: " + responseCode, Toast.LENGTH_SHORT).show()); } break; } } if (redirectCount >= MAX_REDIRECTS) { Log.e(TAG, "重定向次数超过限制"); runOnUiThread(() -> { if (!isFinishing()) { Toast.makeText(FanHui.this, "重定向次数过多", Toast.LENGTH_SHORT).show(); } }); } } catch (Exception e) { Log.e(TAG, "获取录像异常", e); if (!isFinishing() && !isDestroyed()) { runOnUiThread(() -> Toast.makeText(FanHui.this, "获取录像出错: " + e.getMessage(), Toast.LENGTH_SHORT).show()); } } finally { if (conn != null) { conn.disconnect(); } } }); } private List<VideoInfo> parseVideoData(JSONArray records) throws JSONException { List<VideoInfo> videos = new ArrayList<>(); SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); for (int i = 0; i < records.length(); i++) { JSONObject record = records.getJSONObject(i); VideoInfo video = new VideoInfo(); // 兼容多种ID字段名 video.id = record.optString("id", record.optString("fileId", record.optString("recordId", "N/A"))); // 兼容多种开始时间字段 video.startTime = record.optLong("startTime", record.optLong("beginTime", record.optLong("start_time", 0))); // 兼容多种结束时间字段 video.endTime = record.optLong("endTime", record.optLong("stopTime", record.optLong("end_time", 0))); // 检查时间有效性 if (video.startTime == 0 || video.endTime == 0) { Log.w(TAG, "跳过无效时间段: start=" + video.startTime + ", end=" + video.endTime); continue; } // 格式化时间显示 try { Date startDate = new Date(video.startTime); Date endDate = new Date(video.endTime); video.timeRange = sdf.format(startDate) + " - " + sdf.format(endDate); videos.add(video); } catch (Exception e) { Log.e(TAG, "时间格式化失败", e); } } return videos; } private void playVideo(VideoInfo video) { // 停止当前播放 stopPlayback(); // 获取播放地址 playWithTimeRange(video); } private void playWithTimeRange(VideoInfo video) { try { // 创建播放器实例 mEZPlayer = EZOpenSDK.getInstance().createPlayer(mDeviceSerial, mCameraNo); // 设置回调处理器 mEZPlayer.setHandler(mHandler); // 设置验证码 mEZPlayer.setPlayVerifyCode(mVerifyCode); // 关联播放视图 if (mSurfaceHolder != null) { mEZPlayer.setSurfaceHold(mSurfaceHolder); } // 开始播放云存储录像 - 直接使用时间范围 Calendar startCal = Calendar.getInstance(); startCal.setTimeInMillis(video.startTime); Calendar endCal = Calendar.getInstance(); endCal.setTimeInMillis(video.endTime); // 开始播放云存储录像 - 使用Calendar对象 mEZPlayer.startPlayback(startCal, endCal); Toast.makeText(this, "开始播放录像: " + video.timeRange, Toast.LENGTH_SHORT).show(); } catch (Exception e) { Log.e(TAG, "播放录像失败", e); Toast.makeText(this, "播放录像失败: " + e.getMessage(), Toast.LENGTH_SHORT).show(); } isVideoPlaying = true; runOnUiThread(() -> { if (mPauseButton != null) { mPauseButton.setImageResource(R.drawable.play_full_pause_sel); } }); } private void setupFullscreenButton() { CheckTextButton fullscreenButton = findViewById(R.id.fullscreen_button); fullscreenButton.setOnClickListener(v -> toggleFullscreen()); // 确保退出按钮在横屏模式下可点击 mExitFullScreenButton.setOnClickListener(v -> toggleFullscreen()); mExitFullScreenButton.setClickable(true); // 明确设置可点击 } private void toggleFullscreen() { if (isFullScreen) { // 退出全屏 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); // 恢复UI布局 mControlArea.setVisibility(View.VISIBLE); mDisplayLayout.setVisibility(View.VISIBLE); mExitFullScreenButton.setVisibility(View.GONE); mTitleBar.setVisibility(View.VISIBLE); // 恢复播放器布局 RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, getResources().getDimensionPixelSize(R.dimen.playback_height) // 300dp ); mPlaybackArea.setLayoutParams(params); } else { // 进入全屏 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); // 隐藏其他UI元素 mControlArea.setVisibility(View.GONE); mDisplayLayout.setVisibility(View.GONE); mExitFullScreenButton.setVisibility(View.VISIBLE); mTitleBar.setVisibility(View.GONE); // 设置播放器全屏 RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT ); mPlaybackArea.setLayoutParams(params); // 强制SurfaceView重绘 if (mSurfaceHolder != null) { mSurfaceHolder.setFixedSize(getScreenWidth(), getScreenHeight()); } } isFullScreen = !isFullScreen; } private int getScreenWidth() { return getResources().getDisplayMetrics().widthPixels; } // 获取屏幕高度 private int getScreenHeight() { return getResources().getDisplayMetrics().heightPixels; } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // 横屏时隐藏标题栏 if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { mTitleBar.setVisibility(View.GONE); // 确保播放器填充屏幕 RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT ); mPlaybackArea.setLayoutParams(params); } else { mTitleBar.setVisibility(View.VISIBLE); // 恢复竖屏布局 RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, getResources().getDimensionPixelSize(R.dimen.playback_height) // 300dp ); mPlaybackArea.setLayoutParams(params); } // 确保播放器正确重绘 if (mEZPlayer != null && mSurfaceHolder != null) { mEZPlayer.setSurfaceHold(mSurfaceHolder); } } private void stopPlayback() { if (mEZPlayer != null) { try { mEZPlayer.stopPlayback(); mEZPlayer.release(); } catch (Exception e) { Log.e(TAG, "停止播放失败", e); } mEZPlayer = null; } // 重置播放状态 isVideoPlaying = false; runOnUiThread(() -> { if (mPauseButton != null) { mPauseButton.setImageResource(R.drawable.play_full_pause_sel); } }); } // 播放器回调处理器 - 增强回调处理 private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_PLAYBACK_PLAY_SUCCESS: Log.i(TAG, "回放播放成功"); Toast.makeText(FanHui.this, "回放播放成功", Toast.LENGTH_SHORT).show(); isVideoPlaying = true; // 确保状态同步 break; case MSG_PLAYBACK_PLAY_FAIL: Log.e(TAG, "回放播放失败"); BaseException error = (BaseException) msg.obj; int errorCode = error.getErrorCode(); String errorMsg = "播放失败: " + errorCode; if (errorCode == ErrorCode.ERROR_INNER_VERIFYCODE_NEED) { errorMsg = "需要验证码"; } else if (errorCode == ErrorCode.ERROR_INNER_VERIFYCODE_ERROR) { errorMsg = "验证码错误"; } else if (errorCode == ErrorCode.ERROR_TRANSF_ACCESSTOKEN_ERROR) { errorMsg = "accessToken无效"; } else if (errorCode == ErrorCode.ERROR_TRANSF_DEVICE_OFFLINE) { errorMsg = "设备离线"; } Toast.makeText(FanHui.this, errorMsg, Toast.LENGTH_LONG).show(); break; case MSG_PLAYBACK_STOP: Log.i(TAG, "回放停止"); isVideoPlaying = false; // 确保状态同步 break; } } }; @Override protected void onPause() { super.onPause(); stopPlayback(); shutdownExecutor(); } @Override protected void onResume() { super.onResume(); // 重新创建线程池 if (mExecutorService == null) { mExecutorService = Executors.newFixedThreadPool(2); } } @Override protected void onDestroy() { super.onDestroy(); stopPlayback(); shutdownExecutor(); } private void shutdownExecutor() { if (mExecutorService != null) { try { mExecutorService.shutdownNow(); if (!mExecutorService.awaitTermination(1, TimeUnit.SECONDS)) { Log.w(TAG, "线程池未能在超时时间内关闭"); } } catch (InterruptedException e) { Log.e(TAG, "线程池关闭被中断", e); Thread.currentThread().interrupt(); } mExecutorService = null; } } // 录像信息数据结构 public static class VideoInfo { String id; long startTime; long endTime; String timeRange; } // 列表适配器 public class PlaybackAdapter extends BaseAdapter { @Override public int getCount() { return mVideoList.size(); } @Override public Object getItem(int position) { return mVideoList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = getLayoutInflater().inflate(R.layout.video_item_layout, parent, false); holder = new ViewHolder(); holder.timeTextView = convertView.findViewById(R.id.time_text); holder.durationTextView = convertView.findViewById(R.id.duration_text); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } VideoInfo video = mVideoList.get(position); // 计算持续时间(分钟) long durationMinutes = (video.endTime - video.startTime) / (1000 * 60); holder.timeTextView.setText(video.timeRange); holder.durationTextView.setText(durationMinutes + "分钟"); return convertView; } class ViewHolder { TextView timeTextView; TextView durationTextView; } } } 用最简单的方式最少的代码修改量实现从MainActivity进入FanHui后,再次返回MainActivity时MainActivity继续播放直播预览视频。

package com.hw.camunda.config.Interceptor; import com.hw.camunda.exception.BaseException; import com.hw.camunda.exception.ErrorMsg; import com.hw.camunda.service.impl.CustomUserDetailsService; import com.hw.camunda.utils.JwtUtil; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; @Component public class TokenInterceptor implements HandlerInterceptor { @Resource private CustomUserDetailsService userDetailsService; // 允许的过期后刷新时间(分钟) private static final int ALLOW_EXPIRED_MINUTES = 10; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 从请求头中获取token String token = request.getHeader("Authorization"); if (token == null || token.isEmpty()) { throw new BaseException(ErrorMsg.JWT_TOKEN_INVALID); } // 去掉可能的"Bearer "前缀 if (token.startsWith("Bearer ")) { token = token.substring(7); } try { // 先尝试验证token(未过期的情况) JwtUtil.validateToken(token); } catch (BaseException e) { // 如果捕获到过期异常,我们尝试刷新 if (e.getErrorCode().toString().equals(ErrorMsg.LOGIN_TOKEN_EXPIRE.getCode()+"")) { // 尝试刷新令牌 try { token = JwtUtil.refreshToken(token, ALLOW_EXPIRED_MINUTES); // 将新令牌设置到响应头,客户端需要保存并替换旧令牌 response.setHeader("New-Access-Token", token); } catch (BaseException ex) { // 刷新失败,抛出异常(可能是过期时间超过10分钟或无效token) throw ex; } } else { // 其他验证失败的情况(如无效token) throw e; } } UserDetails userDetails = userDetailsService.loadUserByUsername(token); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authenticationToken); return true; } } security是不是每次请求都要执行才能做鉴权UserDetails userDetails = userDetailsService.loadUserByUsername(token); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authenticationToken);

package com.videogo.ui.login; import android.app.AlertDialog; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.TextureView; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.DatePicker; import android.widget.ImageButton; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.videogo.exception.BaseException; import com.videogo.exception.ErrorCode; import com.videogo.openapi.EZConstants; import com.videogo.openapi.EZPlayer; import androidx.appcompat.app.AppCompatActivity; import com.videogo.openapi.EZOpenSDK; import ezviz.ezopensdk.R; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class FanHui extends AppCompatActivity { private static final String TAG = "EZPlayback"; private String mAppKey; private String mDeviceSerial; private String mVerifyCode; private String mAccessToken; private int mCameraNo; private TextView mDateTextView; private int mSelectedYear, mSelectedMonth, mSelectedDay; private static final String KEY_APPKEY = "appkey"; private static final String KEY_SERIAL = "serial"; private static final String KEY_VERIFYCODE = "VerifyCode"; private static final String KEY_ACCESSTOKEN = "accessToken"; private static final String KEY_CAMERANO = "cameraNo"; // 回放录像相关 private static final String VIDEO_BY_TIME_URL = "https://open.ys7.com/api/lapp/video/by/time"; private ExecutorService mExecutorService; private ListView mListView; private PlaybackAdapter mAdapter; private List<VideoInfo> mVideoList = new ArrayList<>(); // 播放器相关 private EZPlayer mEZPlayer; private TextureView mPlaybackTextureView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ez_playback_list_page); // 创建线程池 mExecutorService = Executors.newFixedThreadPool(2); extractParametersFromIntent(); final Calendar calendar = Calendar.getInstance(); mSelectedYear = calendar.get(Calendar.YEAR); mSelectedMonth = calendar.get(Calendar.MONTH); mSelectedDay = calendar.get(Calendar.DAY_OF_MONTH); // 初始化视图 initViews(); // 设置日期显示模块 setupDatePicker(); // 默认加载当天的录像 loadVideosForSelectedDate(); // 初始化SDK initSDK(); } private void initSDK() { try { // 初始化萤石云SDK EZOpenSDK.initLib(getApplication(), mAppKey); EZOpenSDK.getInstance().setAccessToken(mAccessToken); } catch (Exception e) { Log.e(TAG, "SDK初始化失败", e); Toast.makeText(this, "SDK初始化失败", Toast.LENGTH_SHORT).show(); } } private void initViews() { // 查找ListView mListView = findViewById(R.id.listView); if (mListView == null) { Log.e(TAG, "ListView not found with ID listView"); return; } // 初始化适配器 mAdapter = new PlaybackAdapter(); mListView.setAdapter(mAdapter); // 设置点击事件 mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { VideoInfo video = mVideoList.get(position); playVideo(video); } }); // 获取播放器视图 mPlaybackTextureView = findViewById(R.id.remote_playback_wnd_sv); if (mPlaybackTextureView == null) { Log.e(TAG, "TextureView not found with ID remote_playback_wnd_sv"); } } private void setupDatePicker() { mDateTextView = findViewById(R.id.date_text); ImageButton datePickerButton = findViewById(R.id.date_picker_button); updateDateDisplay(); datePickerButton.setOnClickListener(v -> showDatePickerDialog()); } private void updateDateDisplay() { String formattedDate = String.format(Locale.getDefault(), "%d年%02d月%02d日", mSelectedYear, mSelectedMonth + 1, // 月份需要+1 mSelectedDay); mDateTextView.setText(formattedDate); } private void showDatePickerDialog() { final AlertDialog dlg = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog).create(); dlg.show(); Window window = dlg.getWindow(); window.setContentView(R.layout.datepicker_layout); // 设置对话框宽度 WindowManager.LayoutParams lp = window.getAttributes(); lp.width = WindowManager.LayoutParams.MATCH_PARENT; window.setAttributes(lp); // 获取并初始化 DatePicker DatePicker dpPicker = window.findViewById(R.id.dpPicker); // 隐藏不需要的视图 ViewGroup rootView = (ViewGroup) dpPicker.getChildAt(0); if (rootView != null) { ViewGroup childView = (ViewGroup) rootView.getChildAt(0); if (childView != null) { childView.getChildAt(2).setVisibility(View.VISIBLE); // 确保月选择器可见 childView.getChildAt(1).setVisibility(View.VISIBLE); } } dpPicker.init(mSelectedYear, mSelectedMonth, mSelectedDay, null); // 设置按钮事件 RelativeLayout yesButton = window.findViewById(R.id.YES); RelativeLayout noButton = window.findViewById(R.id.NO); yesButton.setOnClickListener(v -> { mSelectedYear = dpPicker.getYear(); mSelectedMonth = dpPicker.getMonth(); mSelectedDay = dpPicker.getDayOfMonth(); updateDateDisplay(); dlg.dismiss(); // 加载新选择的日期的录像 loadVideosForSelectedDate(); }); noButton.setOnClickListener(v -> dlg.dismiss()); } private void extractParametersFromIntent() { Bundle extras = getIntent().getExtras(); if (extras != null) { mAppKey = extras.getString(KEY_APPKEY, ""); mDeviceSerial = extras.getString(KEY_SERIAL, ""); mVerifyCode = extras.getString(KEY_VERIFYCODE, ""); mAccessToken = extras.getString(KEY_ACCESSTOKEN, ""); mCameraNo = extras.getInt(KEY_CAMERANO, 0); Log.d(TAG, "Received parameters:"); Log.d(TAG, "AppKey: " + mAppKey); Log.d(TAG, "DeviceSerial: " + mDeviceSerial); Log.d(TAG, "VerifyCode: " + mVerifyCode); Log.d(TAG, "AccessToken: " + mAccessToken); Log.d(TAG, "CameraNo: " + mCameraNo); } else { Log.e(TAG, "No parameters received from intent"); } } private void loadVideosForSelectedDate() { // 计算开始和结束时间戳 Calendar cal = Calendar.getInstance(); cal.set(mSelectedYear, mSelectedMonth, mSelectedDay, 0, 0, 0); long startTime = cal.getTimeInMillis(); cal.set(mSelectedYear, mSelectedMonth, mSelectedDay, 23, 59, 59); long endTime = cal.getTimeInMillis(); // 发起网络请求获取录像 fetchVideosByTime(startTime, endTime); } private void fetchVideosByTime(long startTime, long endTime) { mExecutorService.execute(() -> { try { URL url = new URL(VIDEO_BY_TIME_URL); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setDoOutput(true); conn.setConnectTimeout(10000); conn.setReadTimeout(10000); // 构建POST数据 StringBuilder postData = new StringBuilder(); postData.append("accessToken=").append(URLEncoder.encode(mAccessToken, "UTF-8")); postData.append("&deviceSerial=").append(URLEncoder.encode(mDeviceSerial, "UTF-8")); postData.append("&channelNo=").append(mCameraNo); postData.append("&startTime=").append(startTime); postData.append("&endTime=").append(endTime); postData.append("&recType=").append(0); // 系统自动选择 // 发送请求 OutputStream os = conn.getOutputStream(); os.write(postData.toString().getBytes("UTF-8")); os.flush(); os.close(); // 处理响应 int responseCode = conn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { // 读取响应内容 InputStream is = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); // 解析JSON响应 JSONObject json = new JSONObject(response.toString()); String code = json.optString("code", "0"); if ("200".equals(code)) { JSONArray data = json.getJSONArray("data"); List<VideoInfo> videos = parseVideoData(data); runOnUiThread(() -> { mVideoList.clear(); mVideoList.addAll(videos); mAdapter.notifyDataSetChanged(); }); } else { String msg = json.optString("msg", "未知错误"); Log.e(TAG, "获取录像失败: " + msg); runOnUiThread(() -> Toast.makeText(FanHui.this, "获取录像失败: " + msg, Toast.LENGTH_SHORT).show()); } } else { Log.e(TAG, "HTTP错误: " + responseCode); runOnUiThread(() -> Toast.makeText(FanHui.this, "网络请求失败: " + responseCode, Toast.LENGTH_SHORT).show()); } conn.disconnect(); } catch (Exception e) { Log.e(TAG, "获取录像异常", e); runOnUiThread(() -> Toast.makeText(FanHui.this, "获取录像出错: " + e.getMessage(), Toast.LENGTH_SHORT).show()); } }); } private List<VideoInfo> parseVideoData(JSONArray data) throws JSONException { List<VideoInfo> videos = new ArrayList<>(); SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); for (int i = 0; i < data.length(); i++) { JSONObject videoObj = data.getJSONObject(i); VideoInfo video = new VideoInfo(); video.id = videoObj.optString("id"); video.startTime = videoObj.optLong("startTime"); video.endTime = videoObj.optLong("endTime"); video.recType = videoObj.optInt("recType"); // 格式化时间显示 Date startDate = new Date(video.startTime); Date endDate = new Date(video.endTime); video.timeRange = sdf.format(startDate) + " - " + sdf.format(endDate); videos.add(video); } return videos; } private void playVideo(VideoInfo video) { // 停止当前播放 stopPlayback(); try { // 创建播放器实例 mEZPlayer = EZOpenSDK.getInstance().createPlayer(mDeviceSerial, mCameraNo); // 配置播放器 - 设置回调处理器 mEZPlayer.setHandler(mHandler); // 设置验证码 mEZPlayer.setPlayVerifyCode(mVerifyCode); // 关联播放视图 if (mPlaybackTextureView != null) { mEZPlayer.setSurfaceTexture(mPlaybackTextureView.getSurfaceTexture()); } else { Log.e(TAG, "无法关联播放视图"); Toast.makeText(this, "播放视图未初始化", Toast.LENGTH_SHORT).show(); } // 创建Calendar对象作为参数 Calendar startCal = Calendar.getInstance(); startCal.setTimeInMillis(video.startTime); Calendar endCal = Calendar.getInstance(); endCal.setTimeInMillis(video.endTime); // 开始回放 mEZPlayer.startPlayback(startCal, endCal); Toast.makeText(this, "开始播放录像: " + video.timeRange, Toast.LENGTH_SHORT).show(); } catch (Exception e) { Log.e(TAG, "播放录像失败", e); Toast.makeText(this, "播放录像失败: " + e.getMessage(), Toast.LENGTH_SHORT).show(); } } private void stopPlayback() { if (mEZPlayer != null) { mEZPlayer.stopPlayback(); mEZPlayer.release(); mEZPlayer = null; } } // 播放器回调处理器 private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case EZConstants.EZRealPlayConstants.MSG_REALPLAY_PLAY_SUCCESS: Log.i(TAG, "回放播放成功"); break; case EZConstants.EZRealPlayConstants.MSG_REALPLAY_PLAY_FAIL: Log.e(TAG, "回放播放失败"); BaseException error = (BaseException) msg.obj; int errorCode = error.getErrorCode(); String errorMsg = "播放失败: " + errorCode; // 根据错误码提供更具体的错误信息 if (errorCode == ErrorCode.ERROR_INNER_VERIFYCODE_NEED) { errorMsg = "需要验证码"; } else if (errorCode == ErrorCode.ERROR_INNER_VERIFYCODE_ERROR) { errorMsg = "验证码错误"; } else if (errorCode == ErrorCode.ERROR_TRANSF_ACCESSTOKEN_ERROR) { errorMsg = "accessToken无效"; } Toast.makeText(FanHui.this, errorMsg, Toast.LENGTH_LONG).show(); break; case EZConstants.EZRealPlayConstants.MSG_VIDEO_SIZE_CHANGED: Log.d(TAG, "视频尺寸变化"); break; } } }; @Override protected void onDestroy() { super.onDestroy(); stopPlayback(); if (mExecutorService != null) { mExecutorService.shutdown(); } } // 录像信息数据结构 private static class VideoInfo { String id; long startTime; long endTime; int recType; String timeRange; } // 列表适配器 private class PlaybackAdapter extends BaseAdapter { @Override public int getCount() { return mVideoList.size(); } @Override public Object getItem(int position) { return mVideoList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = getLayoutInflater().inflate(R.layout.video_item_layout, parent, false); holder = new ViewHolder(); holder.timeTextView = convertView.findViewById(R.id.time_text); holder.durationTextView = convertView.findViewById(R.id.duration_text); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } VideoInfo video = mVideoList.get(position); // 计算持续时间(分钟) long durationMinutes = (video.endTime - video.startTime) / (1000 * 60); holder.timeTextView.setText(video.timeRange); holder.durationTextView.setText(durationMinutes + "分钟"); return convertView; } class ViewHolder { TextView timeTextView; TextView durationTextView; } } } 依据上述代码解决报错:Cannot resolve method 'setSurfaceTexture' in 'EZPlayer' Cannot resolve symbol 'MSG_VIDEO_SIZE_CHANGED'

java.io.FileNotFoundException: http://localhost:8080/api/course/list at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1913) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1515) at com.ndky.StudentManagementGUI.sendGetRequest(StudentManagementGUI.java:355) at com.ndky.StudentManagementGUI.refreshTable(StudentManagementGUI.java:115) at com.ndky.StudentManagementGUI.lambda$openWindow$6(StudentManagementGUI.java:107) at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022) at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348) at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402) at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259) at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:262) at java.awt.Component.processMouseEvent(Component.java:6539) at javax.swing.JComponent.processMouseEvent(JComponent.java:3324) at java.awt.Component.processEvent(Component.java:6304) at java.awt.Container.processEvent(Container.java:2239) at java.awt.Component.dispatchEventImpl(Component.java:4889) at java.awt.Container.dispatchEventImpl(Container.java:2297) at java.awt.Component.dispatchEvent(Component.java:4711) at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4904) at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4535) at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4476) at java.awt.Container.dispatchEventImpl(Container.java:2283) at java.awt.Window.dispatchEventImpl(Window.java:2746) at java.awt.Component.dispatchEvent(Component.java:4711) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:760) at java.awt.EventQueue.access$500(EventQueue.java:97) at java.awt.EventQueue$3.run(EventQueue.java:709) at java.awt.EventQueue$3.run(EventQueue.java:703) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74) at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:84) at java.awt.EventQueue$4.run(EventQueue.java:733) at java.awt.EventQueue$4.run(EventQueue.java:731) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74) at java.awt.EventQueue.dispatchEvent(EventQueue.java:730) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

我用了方案1,现在报错了:12:42:58.678 跳转登录页成功 at pages/index/index.vue:16 12:43:07.960 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7 12:43:07.960 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7 12:43:07.960 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7 12:43:07.960 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7 12:43:07.960 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7 12:43:08.012 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7 12:43:08.012 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7 12:43:08.012 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7 12:43:08.012 [JS Framework] Failed to execute the callback function: TypeError: Cannot read property 'left' of null 12:43:08.012 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7 12:43:08.012 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7 12:43:08.012 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7 12:43:08.013 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7 12:43:08.013 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7 12:43:08.013 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7 12:43:08.013 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7 12:43:08.013 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7 12:43:08.013 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7 12:43:08.013 reportJSException >>>> exception function:__WEEX_CALL_JAVASCRIPT__, exception:JavaScript execute error!Uncaught TypeError: Cannot read property 'left' of null at (app-service.js:1701:40) 12:43:08.013 Uncaught TypeError: Cannot read properties of undefined (reading '$') at uni-app-view.umd.js:7

package com.hw.camunda.config.filter; import com.hw.camunda.config.SecurityProperties; import com.hw.camunda.exception.BaseException; import com.hw.camunda.exception.ErrorMsg; import com.hw.camunda.service.impl.CustomUserDetailsService; import com.hw.camunda.utils.JwtUtil; import jakarta.annotation.Resource; import jakarta.servlet.*; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.annotation.Order; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; @Order(1) @Component public class TokenFilter extends OncePerRequestFilter { private final CustomUserDetailsService userDetailsService; private final SecurityProperties securityProperties; @Autowired public TokenFilter(SecurityProperties securityProperties,CustomUserDetailsService userDetailsService) { this.securityProperties = securityProperties; this.userDetailsService = userDetailsService; } // 允许的过期后刷新时间(分钟) private static final int ALLOW_EXPIRED_MINUTES = 10; @Override public boolean shouldNotFilter(HttpServletRequest request) { String uri = request.getRequestURI(); return securityProperties.getPermitUrls().contains(uri); } @Override public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { // 从请求头中获取token String token = request.getHeader("Authorization"); if (token == null || token.isEmpty()) { throw new BaseException(ErrorMsg.JWT_TOKEN_INVALID); } // 去掉可能的"Bearer "前缀 if (token.startsWith("Bearer ")) { token = token.substring(7); } try { // 先尝试验证token(未过期的情况) JwtUtil.validateToken(token); } catch (BaseException e) { // 如果捕获到过期异常,我们尝试刷新 if (e.getErrorCode().toString().equals(ErrorMsg.LOGIN_TOKEN_EXPIRE.getCode()+"")) { // 尝试刷新令牌 try { token = JwtUtil.refreshToken(token, ALLOW_EXPIRED_MINUTES); // 将新令牌设置到响应头,客户端需要保存并替换旧令牌 response.setHeader("New-Access-Token", token); } catch (BaseException ex) { // 刷新失败,抛出异常(可能是过期时间超过10分钟或无效token) throw ex; } } else { // 其他验证失败的情况(如无效token) throw e; } } //最好保存到redis中 UserDetails userDetails = userDetailsService.loadUserByUsername(token); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authenticationToken); chain.doFilter(request, response); } } 还有什么办法注入 private final CustomUserDetailsService userDetailsService; private final SecurityProperties securityProperties; package com.hw.camunda.config; import com.alibaba.fastjson2.JSONObject; import com.hw.camunda.config.filter.TokenFilter; import com.hw.camunda.exception.ErrorMsg; import com.hw.camunda.service.impl.CustomUserDetailsService; import com.hw.camunda.utils.JsonResult; import jakarta.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; @Configuration @EnableWebSecurity @EnableMethodSecurity // 启用方法级注解鉴权 public class SecurityConfig { private final CustomUserDetailsService userDetailsService; private final SecurityProperties securityProperties; @Autowired public SecurityConfig(SecurityProperties securityProperties,CustomUserDetailsService userDetailsService) { this.securityProperties = securityProperties; this.userDetailsService = userDetailsService; } /** * 安全过滤链配置 - 清晰定义拦截规则 * 优先级:从上到下匹配规则 */ @Bean SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(AbstractHttpConfigurer::disable) .addFilterBefore(new TokenFilter(securityProperties,userDetailsService), UsernamePasswordAuthenticationFilter.class) .authorizeHttpRequests(auth -> { for (String permitUrl : securityProperties.getPermitUrls()) { auth.requestMatchers(permitUrl).permitAll(); } auth.requestMatchers("/api/**").authenticated() .anyRequest().denyAll(); } ); http.exceptionHandling(e -> e .authenticationEntryPoint((req, res, ex) -> { // 将异常转换为JSON响应 res.setStatus(HttpStatus.UNAUTHORIZED.value()); res.setContentType("application/json"); res.setCharacterEncoding("UTF-8"); res.getWriter().write(JSONObject.toJSONString(JsonResult.error(ErrorMsg.JWT_TOKEN_INVALID))); }) ); return http.build(); } }

extern uint8 DiagDtcMessageElement[50]; App_CanCbk_DtcMessageInfoType App_CanCbk_DtcMessageInfo; typedef struct sApp_CanCbk_DtcMessageElementType { uint8 MessageInfoStatus; // 1: Wait to Send 0: Free uint32 DtcId; uint8 DtcStatus; uint8 DtcSnapshotData[40]; uint8 DtcExtendedData[7]; } App_CanCbk_DtcMessageElementType; #define DTC_MESSAGE_INFO_LIST_SIZE 10 typedef struct sApp_CanCbk_DtcMessageInfoType { uint8 CheckSendIndex; uint8 LastReportDtcIndex; App_CanCbk_DtcMessageElementType DtcMessageElement[DTC_MESSAGE_INFO_LIST_SIZE]; } App_CanCbk_DtcMessageInfoType; 这个是一个结构体,先分析一下这个结构体,下面我把一些东西存入这个结构体,如下 static uint16 Diag_Dem_Cfg_Memoryentry_Counter = 0U; static uint16 Current_Dem_Cfg_Memoryentry_Counter_Index = 0U; static void RCpApDiagnostic_CtapDiagnostic_D_Set_FaultReport_To_Com(void) { Std_ReturnType ERRStatus = 0U; boolean FailedStatus1 = FALSE; boolean FailedStatus2 = FALSE; boolean FailedStatus3 = FALSE; boolean FailedStatus4 = FALSE; boolean FailedStatus5 = FALSE; boolean FailedStatus6 = FALSE; boolean FailedStatus7 = FALSE; boolean FailedStatus8 = FALSE; for(uint16 i = 0 ; i < 17 ; i ++ ) { DiagDtcMessageElement[i] = 0x0; if((Dem_Cfg_CombinedGroupInternalStatus.raw[i] & 0x01) == 0x01); { switch (i) { case 0: DiagDtcMessageElement[i] = 0x01; break; case 1: DiagDtcMessageElement[i] = 0x01; break; case 2: DiagDtcMessageElement[i] = 0x01; break; case 3: DiagDtcMessageElement[i] = 0x01; break; case 4: DiagDtcMessageElement[i] = 0x01; break; case 5: DiagDtcMessageElement[i] = 0x01; break; case 6: DiagDtcMessageElement[i] = 0x01; break; case 7: DiagDtcMessageElement[i] = 0x01; break; case 8: DiagDtcMessageElement[i] = 0x01; break; case 9: DiagDtcMessageElement[i] = 0x01; break; case 10: DiagDtcMessageElement[i] = 0x01; break; case 11: DiagDtcMessageElement[i] = 0x01; break; case 12: DiagDtcMessageElement[i] = 0x01; break; case 13: DiagDtcMessageElement[i] = 0x01; break; case 14: DiagDtcMessageElement[i] = 0x01; break; case 15: DiagDtcMessageElement[i] = 0x01; break; case 16: DiagDtcMessageElement[i] = 0x01; break; } } } if ((Rte_Call_Event_DemEventParameter_MCU_SMU_RT_FAILURE_GetEventFailed(&FailedStatus1) == RTE_E_OK) && (FailedStatus1 == TRUE)) { DiagDtcMessageElement[17] = 0x01; } else { DiagDtcMessageElement[17] = 0; } if ((Rte_Call_Event_DemEventParameter_ECU_NOT_PROGRAMMED_FAILURE_GetEventFailed(&FailedStatus2) == RTE_E_OK) && (FailedStatus2 == TRUE)) { DiagDtcMessageElement[36] = 0x01; } else { DiagDtcMessageElement[36] = 0; } if ((Rte_Call_Event_DemEventParameter_PROXI_NOT_WRITE_FAILURE_GetEventFailed(&FailedStatus3) == RTE_E_OK) && (FailedStatus3 == TRUE)) { DiagDtcMessageElement[38] = 0x01; } else { DiagDtcMessageElement[38] = 0; } if ((Rte_Call_Event_DemEventParameter_SOFTWARE_VERSION_INFORMATIO_CROSS_COMPARE_FAILURE_GetEventFailed(&FailedStatus4) == RTE_E_OK) && (FailedStatus4 == TRUE)) { DiagDtcMessageElement[39] = 0x01; } else { DiagDtcMessageElement[39] = 0; } if ((Rte_Call_Event_DemEventParameter_STOM_SECURITY_CERTIFICATE_FAILURE_GetEventFailed(&FailedStatus5) == RTE_E_OK) && (FailedStatus5 == TRUE)) { DiagDtcMessageElement[40] = 0x01; } else { DiagDtcMessageElement[40] = 0; } if ((Rte_Call_Event_DemEventParameter_BCM_CONFIG_CODE_MISMATCH_FAILURE_GetEventFailed(&FailedStatus6) == RTE_E_OK) && (FailedStatus6 == TRUE)) { DiagDtcMessageElement[42] = 0x01; } else { DiagDtcMessageElement[42] = 0; } if ((Rte_Call_Event_DemEventParameter_CAN_ESC_IWSS_VEHICLE_SPEED_SIGNAL_MISMATCH_FAILURE_GetEventFailed(&FailedStatus7) == RTE_E_OK) && (FailedStatus7 == TRUE)) { DiagDtcMessageElement[43] = 0x01; } else { DiagDtcMessageElement[43] = 0; } if ((Rte_Call_Event_DemEventParameter_CAN_CURRENT_VIN_MISMATCH_FAILURE_GetEventFailed(&FailedStatus8) == RTE_E_OK) && (FailedStatus8 == TRUE)) { DiagDtcMessageElement[44] = 0x01; } else { DiagDtcMessageElement[44] = 0; } RECIVERSTATUS(ERRStatus); } uint16 PreDiagDtcMessageElement[50] = {0}; static void RCpApDiagnostic_CtapDiagnostic_D_Set_FaultReport_To_19Serverce(void) { Std_ReturnType ERRStatus = 0U; uint8 FaultReportID = 0U; uint8 Current_Fault_Index = 0U; Current_Fault_Index = App_CanCbk_DtcMessageInfo.LastReportDtcIndex; for(uint16 i = 0; i < 50; i ++) { if(PreDiagDtcMessageElement[i] != DiagDtcMessageElement[i]) { PreDiagDtcMessageElement[i] = DiagDtcMessageElement[i]; if(DiagDtcMessageElement[i] == 0x01) { switch (i) { case 0: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x405200 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 1: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x559211 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 2: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x559301 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 3: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x610016 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 4: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x610117 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 5: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x62104b ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 6: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x621700 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 7: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x621749 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 8: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc11500 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 9: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc15c00 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 10: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc24300 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 11: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45b86 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 12: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45d00 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 13: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc54400 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 14: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xd07000 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 15: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xd07300 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 16: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xd85400 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 17: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x621100 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 18: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x405154 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 19: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x621096 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 20: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x611b00 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 21: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x45284a ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 22: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x621762 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 23: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45d85 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 24: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45d27 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 25: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc54485 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 26: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc54427 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 27: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45d41 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 28: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45d82 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 29: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45b82 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 30: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45b00 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 31: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc15a00 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 32: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xd85441 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 33: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xd85482 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 34: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc54441 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 35: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc54482 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 36: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x621c51 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 37: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x452900 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 38: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x621f55 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 39: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xd60000 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 40: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xd61000 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 41: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x55934a ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 42: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x622355 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 43: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45b83 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; case 44: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x620355 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x01 ; Current_Dem_Cfg_Memoryentry_Counter_Index = Current_Fault_Index ; Diag_Dem_Cfg_Memoryentry_Counter ++; break; } } else { switch (i) { case 0: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x405200 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 1: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x559211 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 2: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x559301 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 3: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x610016 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 4: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x610117 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 5: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x62104b ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 6: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x621700 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 7: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x621749 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 8: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc11500 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 9: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc15c00 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 10: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc24300 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 11: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45b86 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 12: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45d00 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 13: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc54400 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 14: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xd07000 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 15: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xd07300 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 16: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xd85400 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 17: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x621100 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 18: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x405154 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 19: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xd07000 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 20: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x611b00 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 21: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x45284a ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 22: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x621762 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 23: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45d85 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 24: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45d27 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 25: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc54485 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 26: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc54427 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 27: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45d41 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 28: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45d82 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 29: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45b82 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 30: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45b00 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 31: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc15a00 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 32: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xd85441 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 33: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xd85482 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 34: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc54441 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 35: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc54482 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 36: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x621c51 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 37: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x452900 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 38: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x621f55 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 39: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xd60000 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 40: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xd61000 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 41: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x55934a ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 42: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x622355 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 43: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0xc45b83 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; case 44: App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].MessageInfoStatus = 0x01 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcId = 0x620355 ; App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Fault_Index].DtcStatus = 0x0 ; break; } } } } RECIVERSTATUS(ERRStatus); } uint16 PreDiag_Dem_Cfg_Memoryentry_Counter = 0; static void RCpApDiagnostic_CtapDiagnostic_D_Set_FaultReport_To_19Serverce_Data(void) { if(PreDiag_Dem_Cfg_Memoryentry_Counter != Diag_Dem_Cfg_Memoryentry_Counter) { PreDiag_Dem_Cfg_Memoryentry_Counter = Diag_Dem_Cfg_Memoryentry_Counter; switch (Diag_Dem_Cfg_Memoryentry_Counter) { case 1: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_0.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_0.ExtendedData[0][k]; } break; case 2: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_1.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_1.ExtendedData[0][k]; } break; case 3: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_2.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_2.ExtendedData[0][k]; } break; case 4: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_3.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_3.ExtendedData[0][k]; } break; case 5: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_4.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_4.ExtendedData[0][k]; } break; case 6: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_5.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_5.ExtendedData[0][k]; } break; case 7: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_6.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_6.ExtendedData[0][k]; } break; case 8: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_7.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_7.ExtendedData[0][k]; } break; case 9: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_8.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_8.ExtendedData[0][k]; } break; case 10: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_9.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_9.ExtendedData[0][k]; } break; case 11: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_10.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_10.ExtendedData[0][k]; } break; case 12: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_11.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_11.ExtendedData[0][k]; } break; case 13: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_12.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_12.ExtendedData[0][k]; } break; case 14: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_13.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_13.ExtendedData[0][k]; } break; case 15: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_14.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_14.ExtendedData[0][k]; } break; case 16: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_15.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_15.ExtendedData[0][k]; } break; case 17: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_16.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_16.ExtendedData[0][k]; } break; case 18: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_17.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_17.ExtendedData[0][k]; } break; case 19: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_18.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_18.ExtendedData[0][k]; } break; case 20: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_19.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_19.ExtendedData[0][k]; } break; case 21: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_20.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_20.ExtendedData[0][k]; } break; case 22: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_21.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_21.ExtendedData[0][k]; } break; case 23: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_22.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_22.ExtendedData[0][k]; } break; case 24: for(uint16 j= 0; j < 40; j ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcSnapshotData[j] = Dem_Cfg_PrimaryEntry_23.SnapshotData[0][j]; } for(uint16 k= 0; k < 7; k ++) { App_CanCbk_DtcMessageInfo.DtcMessageElement[Current_Dem_Cfg_Memoryentry_Counter_Index].DtcExtendedData[k] = Dem_Cfg_PrimaryEntry_23.ExtendedData[0][k]; } break; } } } 帮我这个小白详细讲解一下逻辑,然后在梳理一下

最新推荐

recommend-type

基于Java医院药品管理系统论文

基于Java医院药品管理系统论文
recommend-type

Mockingbird v2:PocketMine-MP新防作弊机制详解

标题和描述中所涉及的知识点如下: 1. Mockingbird反作弊系统: Mockingbird是一个正在开发中的反作弊系统,专门针对PocketMine-MP服务器。PocketMine-MP是Minecraft Pocket Edition(Minecraft PE)的一个服务器软件,允许玩家在移动平台上共同游戏。随着游戏的普及,作弊问题也随之而来,因此Mockingbird的出现正是为了应对这种情况。 2. Mockingbird的版本迭代: 从描述中提到的“Mockingbird的v1变体”和“v2版本”的变化来看,Mockingbird正在经历持续的开发和改进过程。软件版本迭代是常见的开发实践,有助于修复已知问题,改善性能和用户体验,添加新功能等。 3. 服务器性能要求: 描述中强调了运行Mockingbird的服务器需要具备一定的性能,例如提及“WitherHosting的$ 1.25计划”,这暗示了反作弊系统对服务器资源的需求较高。这可能是因为反作弊机制需要频繁处理大量的数据和事件,以便及时检测和阻止作弊行为。 4. Waterdog问题: Waterdog是另一种Minecraft服务器软件,特别适合 PocketMine-MP。描述中提到如果将Mockingbird和Waterdog结合使用可能会遇到问题,这可能是因为两者在某些机制上的不兼容或Mockingbird对Waterdog的特定实现尚未完全优化。 5. GitHub使用及问题反馈: 作者鼓励用户通过GitHub问题跟踪系统来报告问题、旁路和功能建议。这是一个公共代码托管平台,广泛用于开源项目协作,便于开发者和用户进行沟通和问题管理。作者还提到请用户在GitHub上发布问题而不是在评论区留下不好的评论,这体现了良好的社区维护和用户交流的实践。 6. 软件标签: “pocketmine”和“anticheat”(反作弊)作为标签,说明Mockingbird是一个特别为PocketMine-MP平台开发的反作弊软件。而“PHP”则可能指的是Mockingbird的开发语言,虽然这个信息与常见的Java或C++等开发Minecraft相关软件的语言不同,但并不排除使用PHP进行服务器端开发的可能性,尤其是对于处理动态网页、服务器端脚本等场景。 7. 压缩包文件: “Mockingbird-stable”是一个文件名称,很可能表示这是一个包含最新稳定版Mockingbird反作弊系统的压缩包。通常,这样的文件名中包含“stable”意味着这是一个经过充分测试且推荐用于生产环境的版本。 8. 社区协作和用户参与: 特别感谢部分提到了shur,这可能是对某位贡献者或社区成员的感激之情。这种感谢表明了软件开发不仅是开发者个人的劳动成果,同时也依赖于社区的支持和参与,包括提供反馈、报告问题、贡献代码和文档等。 总结以上内容,我们可以看到Mockingbird作为一款反作弊系统,其开发和维护需要依赖于社区的广泛参与和支持,同时还需要强大的服务器后端作为支撑。通过不断迭代更新版本,开发者希望解决现有问题,提高反作弊效率,并希望与社区保持良好的沟通,以持续优化产品。
recommend-type

“历史人物独白解说”视频:数据处理的6种革命性技术

# 1. 数据处理的历史回顾与技术演进 数据处理的历史,从最初的简单机械记录,到如今复杂的数据处理体系,不仅反映了技术的演进,也映射了人类社会进步的轨迹。在计算机技术发展初期,数据处理主要依靠打孔卡片和磁带,通过批处理的方式进行,效率低下且出错率高。随着技术的发展,上世纪70年代,关系型数据库的出现大大提高了数据处理的效率和准确性,为数据处理技术的发展奠定了基础。 随后,随着互
recommend-type

怎么判断多级运放电路的稳定性?

<think>首先,用户的问题是关于判断多级运算放大器电路的稳定性。我需要根据系统级指令来构建回答。 系统级指令: - 所有行内数学表达式必须使用$...$格式。 - 独立公式必须使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如[^1]。 用户可见层指令: - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 参考引用: - 引用[1]:关于集成运算放大电路的设计、组成和性能评估。 - 引用[2]:高频电路中运放的带宽限制,一级放大电路的增益通常为100倍,过高会引起振
recommend-type

利用AHP和节点集中度解决影响力最大化问题的Flask应用教程

从给定的文件信息中,我们可以提取以下相关知识点进行详细说明: ### 标题知识点 **IM问题与AHP结合** IM问题(Influence Maximization)是网络分析中的一个核心问题,旨在识别影响网络中信息传播的关键节点。为了求解IM问题,研究者们常常结合使用不同的算法和策略,其中AHP(Analytic Hierarchy Process,分析层次结构过程)作为一种决策分析方法,被用于评估网络节点的重要性。AHP通过建立层次模型,对各个因素进行比较排序,从而量化影响度,并通过一致性检验保证决策结果的有效性。将AHP应用于IM问题,意味着将分析网络节点影响的多个维度,比如节点的中心性(centrality)和影响力。 **集中度措施** 集中度(Centralization)是衡量网络节点分布状况的指标,它反映了网络中节点之间的连接关系。在网络分析中,集中度常用于识别网络中的“枢纽”或“中心”节点。例如,通过计算网络的度中心度(degree centrality)可以了解节点与其他节点的直接连接数量;接近中心度(closeness centrality)衡量节点到网络中其他所有节点的平均距离;中介中心度(betweenness centrality)衡量节点在连接网络中其他节点对的最短路径上的出现频率。集中度高意味着节点在网络中处于重要位置,对信息的流动和控制具有较大影响力。 ### 描述知识点 **Flask框架** Flask是一个轻量级的Web应用框架,它使用Python编程语言开发。它非常适合快速开发小型Web应用,以及作为微服务架构的一部分。Flask的一个核心特点是“微”,意味着它提供了基本的Web开发功能,同时保持了框架的小巧和灵活。Flask内置了开发服务器,支持Werkzeug WSGI工具包和Jinja2模板引擎,提供了RESTful请求分发和请求钩子等功能。 **应用布局** 一个典型的Flask应用会包含以下几个关键部分: - `app/`:这是应用的核心目录,包含了路由设置、视图函数、模型和控制器等代码文件。 - `static/`:存放静态文件,比如CSS样式表、JavaScript文件和图片等,这些文件的内容不会改变。 - `templates/`:存放HTML模板文件,Flask将使用这些模板渲染最终的HTML页面。模板语言通常是Jinja2。 - `wsgi.py`:WSGI(Web Server Gateway Interface)是Python应用程序和Web服务器之间的一种标准接口。这个文件通常用于部署到生产服务器时,作为应用的入口点。 **部署到Heroku** Heroku是一个支持多种编程语言的云平台即服务(PaaS),它允许开发者轻松部署、运行和管理应用。部署Flask应用到Heroku,需要几个步骤:首先,创建一个Procfile文件,告知Heroku如何启动应用;其次,确保应用的依赖关系被正确管理,通常通过一个requirements.txt文件列出所有依赖;最后,使用Git将应用推送到Heroku提供的仓库,Heroku会自动识别Procfile并开始部署过程。 ### 标签知识点 **HTML** HTML(HyperText Markup Language,超文本标记语言)是用于创建网页和Web应用的标准标记语言。它定义了网页的结构和内容。HTML文件由一系列元素组成,这些元素通过标签(tags)来表示,如`<p>`代表段落,`<a>`代表链接,`<img>`代表图像等。HTML5是当前使用的最新版本,支持更多的特性,如离线存储、多媒体和图形等。 ### 压缩包子文件的文件名称列表知识点 **IMproblem-using-AHP-and-centralisation-of-nodes-master** 这里的文件名称“IMproblem-using-AHP-and-centralisation-of-nodes-master”表明了一个GitHub仓库的名称,其中包含了源代码以及与项目相关的所有文件。从名称中可以看出,该仓库是关于如何结合AHP和节点集中度分析来解决IM问题的Flask应用程序。文件名中的“master”表明这是仓库的主分支(现在叫做main分支),它是项目最新的、可部署的代码版本。 综合来看,本段信息为我们提供了构建和部署一个使用Flask框架、针对IM问题使用AHP和节点集中度分析的Web应用的方法和步骤。同时,介绍了应用在不同环节中所需技术和组件的详细知识点。
recommend-type

视频内容自动生成算法:突破性的8大最新进展

# 1. 视频内容自动生成算法概述 ## 算法发展背景 随着人工智能技术的迅速发展,视频内容自动生成算法已经成为媒体和娱乐行业的重要工具。这些算法能够自动编辑和合成视频内容,使内容创作者能够以较低的成本和时间生成高质量的视频。从社交媒体动态到在线教育内容,视频内容自动生成的应用场景正在不断扩大。 ## 核心技术简述 视
recommend-type

Softmax函数实际应用举例

<think>嗯,用户现在想了解Softmax函数的实际应用场景,这和我之前详细解释过的Softmax原理是直接相关的。用户特意提到要参考站内引用,看来是想看到具体案例支撑。 从用户提问方式看,ta应该已经理解了Softmax的基本数学原理(毕竟我上次用向量[2,1,0.1]的例子详细演示过计算过程),现在需要落地到实践层面。这种从理论到应用的递进很合理,可能是个正在学习机器学习的学生,或者需要解决实际问题的工程师。 我注意到用户提供的引用里有些关键线索:引用[1]提到图像分类和概率解释,引用[4]强调指数放大的特性,引用[5]则对比了Sigmoid在多标签分类的应用差异。这些正好能支撑我
recommend-type

WDI项目1:PriceIsRight游戏开发实践

### 标题解析 标题“price-is-right:WDI项目1-PriceIsRight游戏”表明这是一个名为“Price Is Right”的游戏项目,这是WDI(Web Development Immersive,全栈网页开发沉浸式课程)的第一个项目。WDI是一种常用于IT培训机构的课程名称,旨在通过实战项目来培养学员的全栈网页开发能力。 ### 描述解析 描述中提到,该游戏的目的是为了练习基本的JavaScript技能。这表明游戏被设计成一个编程练习,让开发者通过实现游戏逻辑来加深对JavaScript的理解。描述中也提到了游戏是一个支持两个玩家的版本,包含了分配得分、跟踪得分以及宣布获胜者等逻辑,这是游戏开发中常见的功能实现。 开发者还提到使用了Bootstrap框架来增加网站的可伸缩性。Bootstrap是一个流行的前端框架,它让网页设计和开发工作更加高效,通过提供预设的CSS样式和JavaScript组件,让开发者能够快速创建出响应式的网站布局。此外,开发者还使用了HTML5和CSS进行网站设计,这表明项目也涉及到了前端开发的基础技能。 ### 标签解析 标签“JavaScript”指出了该游戏中核心编程语言的使用。JavaScript是一种高级编程语言,常用于网页开发中,负责实现网页上的动态效果和交互功能。通过使用JavaScript,开发者可以在不离开浏览器的情况下实现复杂的游戏逻辑和用户界面交互。 ### 文件名称解析 压缩包子文件的文件名称列表中仅提供了一个条目:“price-is-right-master”。这里的“master”可能指明了这是项目的主分支或者主版本,通常在版本控制系统(如Git)中使用。文件名中的“price-is-right”与标题相呼应,表明该文件夹内包含的代码和资源是与“Price Is Right”游戏相关的。 ### 知识点总结 #### 1. JavaScript基础 - **变量和数据类型**:用于存储得分等信息。 - **函数和方法**:用于实现游戏逻辑,如分配得分、更新分数。 - **控制结构**:如if-else语句和循环,用于实现游戏流程控制。 - **事件处理**:监听玩家的输入(如点击按钮)和游戏状态的变化。 #### 2. Bootstrap框架 - **网格系统**:实现响应式布局,让游戏界面在不同设备上都能良好展示。 - **预设组件**:可能包括按钮、表单、警告框等,用于快速开发用户界面。 - **定制样式**:根据需要自定义组件样式来符合游戏主题。 #### 3. HTML5与CSS - **语义化标签**:使用HTML5提供的新标签来构建页面结构,如`<header>`, `<section>`, `<footer>`等。 - **CSS布局**:使用Flexbox或Grid等布局技术对页面元素进行定位和排版。 - **样式设计**:通过CSS为游戏界面增添美观的视觉效果。 #### 4. 项目结构和版本控制 - **主分支管理**:`master`分支通常保存着项目的稳定版本,用于部署生产环境。 - **代码组织**:合理的文件结构有助于维护和扩展项目。 #### 5. 前端开发最佳实践 - **分离关注点**:将样式、脚本和内容分离,确保代码清晰易维护。 - **响应式设计**:确保游戏在多种设备和屏幕尺寸上均有良好的用户体验。 - **可访问性**:考虑键盘导航、屏幕阅读器等无障碍功能,让游戏更加友好。 #### 6. 交互式游戏开发 - **游戏逻辑实现**:创建一个简单的游戏循环,管理玩家输入和得分更新。 - **状态管理**:游戏中的得分和其他游戏状态需要妥善保存和更新。 - **用户界面反馈**:提供即时的视觉和听觉反馈,增强玩家体验。 通过上述知识点的解析,可以看出“Price Is Right”游戏项目不仅仅是一个简单的编程练习,它还融合了多种前端技术,包括JavaScript、Bootstrap、HTML5和CSS,以实现一个完整的、可交互的游戏体验。此项目也反映了开发者在掌握前端开发技能的同时,了解了如何组织代码、维护项目结构和实践开发最佳实践。
recommend-type

人工智能视频编辑:如何利用技术进步提升内容创作质量

# 1. 人工智能视频编辑概述 随着人工智能技术的飞速发展,视频编辑领域正在经历一场前所未有的革命。AI的介入,不仅极大地提升了视频编辑的效率,还赋予了内容创作者全新的表达方式。本章旨在概述人工智能视频编辑的概念、发展历程和当前的应用现状,为读者提供一个全面而深入的了解。 ## 1.1 人工智能视频编辑的兴起 人工智能视频编辑是将先进的机器学习算法与传统视频处理技术相
recommend-type

反激变换器

<think>首先,用户意图是了解反激变换器的工作原理或设计方法。用户的问题是:“反激变换器工作原理及设计指南”。所以我需要基于这个意图和问题,通过调用网络搜索工具进行检索。 我的任务是: 1. 调用网络搜索工具来检索相关内容。 2. 整合检索到的内容,生成详细、清晰、实用、可操作的回答。 3. 禁止将所有引用内容集中在回答末尾;引用应该融入回答中。 4. 避免使用第一人称如“我”。 5. 避免步骤词汇如“首先”、“然后”。 6. 将答案组织为多个方法或步骤,并在每个步骤间换行。 7. 对于代码和公式,遵循特定格式: - 行内公式:$公式内容$ - 独立公式:$$公式内容$$