HarmonyOS-6.1.1-MapKit:现场长按Marker未返回时-怎样让问题上报继续完成又保留事件来源
企业项目实施工程师视角:本文从现场巡检地图事件处理的可靠性需求出发,讲解如何在HarmonyOS 6.1.1中处理长按Marker回调超时、返回延迟等异常场景,确保问题上报流程不中断,同时完整保留事件来源和上下文信息,为后续故障诊断和重试决策奠定基础。
一、企业场景与挑战
1.1 现场地图事件处理的隐蔽风险
在实际部署中,地图事件处理往往面临以下困境:
- 回调延迟或超时:现场网络环境差,Marker长按后无法及时获得POI数据或地理编码信息
- 事件来源丢失:只记录了"出现问题",但无法追溯"长按了什么Marker",导致现场无法复现
- 上报流程中断:发现问题时,整个工作流卡住,现场人员无法继续操作
- 诊断信息不足:远程支持无法判断是"网络问题"“API超时”“设备问题"还是"业务流程异常”
- 事件与错误的关联性破裂:在故障排查时,无法将错误信息与触发事件关联起来
表面现象:“现场长按Marker后无反应"或"长按成功但上报失败”
根本原因:缺少针对事件回调异常的处理机制,未能在"异常状态下保留事件上下文"
1.2 为什么"只记录最后一个错误"不够
许多项目采用简化的异常处理策略:
// ❌ 不足的方案
onMarkerLongClick((marker) => {
try {
processMarker(marker);
} catch (error) {
errorMessage = error.message; // 只记录当前错误
}
});
这种方案的根本缺陷:
- 事件上下文丢失:异常发生时,无法知道"长按的是哪个Marker"
- 无诊断链路:错误与事件被分离,无法追溯"为什么这个操作失败了"
- 无重试依据:无法判断是否应该重试,或者需要等待什么条件变化
- 无现场复现:远程支持无法根据信息重新构造现场环境
- 上报流程被阻断:业务流程卡在"等待回调完成",无法继续
1.3 企业实施的真实需求
地图事件处理必须满足以下要求:
- 事件上下文的完整保留:长按的Marker信息、位置、时间戳必须被记录
- 回调异常的分级处理:区分"网络超时"“API返回异常”“业务逻辑异常”
- 非阻断式的问题上报:问题发现时不中断工作流,继续允许用户操作
- 可追溯的错误链路:从上报的错误可以反向追溯到触发的事件
- 有限时间内的重试策略:对于暂时性故障,支持自动或手动重试
- 现场支持的诊断信息:包含足够的上下文,让远程支持能快速定位问题
二、核心技术概念与设计思路
2.1 地图事件处理的四层异常模型
┌─ 第一层:事件捕获 ──────────────────────┐
│ 用户长按Marker → 回调被触发 │
│ ├─ 事件被正确捕获 → 继续 │
│ ├─ 回调未触发 → 设备/系统问题 │
│ └─ 回调延迟 → 网络/系统负载问题 │
└────────────────────────────────────────┘
↓
┌─ 第二层:事件来源查询 ──────────────────┐
│ 从Marker获取POI或地址信息 │
│ ├─ 立即返回 → 继续 │
│ ├─ 部分返回 → 使用可用信息 │
│ ├─ 超时未返回 → 记录超时,继续 │
│ └─ 查询异常 → 记录异常原因 │
└────────────────────────────────────────┘
↓
┌─ 第三层:业务流程执行 ──────────────────┐
│ 基于事件和查询结果执行业务操作 │
│ ├─ 成功执行 → 记录成功 │
│ ├─ 部分成功 → 记录部分结果 │
│ └─ 执行异常 → 记录异常,继续允许操作 │
└────────────────────────────────────────┘
↓
┌─ 第四层:问题上报与恢复 ────────────────┐
│ 将异常信息上报,同时保留事件来源 │
│ ├─ 上报成功 → 标记已上报 │
│ ├─ 上报失败 → 本地缓存,继续允许操作 │
│ └─ 网络不可用 → 离线记录 │
└────────────────────────────────────────┘
2.2 事件来源与异常的完整记录结构
interface MapEventRecord {
// ===== 事件捕获信息 =====
eventCapture: {
eventType: 'marker_long_click' | 'poi_long_click';
captureTime: string; // 事件被捕获的时间
capturePhase: string; // 当前操作阶段
};
// ===== 事件来源信息 =====
eventSource: {
markerId?: string;
markerTitle?: string;
markerPosition?: {
latitude: number;
longitude: number;
};
poiId?: string;
poiName?: string;
poiAddress?: string;
reliability?: number;
};
// ===== 查询信息 =====
queryInfo: {
queryType: 'poi' | 'address' | 'geocoding';
queryStartTime: string;
queryEndTime?: string;
queryDuration?: number; // 毫秒
queryTimeout: boolean;
queryStatus: 'pending' | 'success' | 'partial' | 'failed' | 'timeout';
queryError?: {
code: string;
message: string;
};
queryResult?: {
totalResults?: number;
returnedCount?: number;
data?: any[];
};
};
// ===== 业务操作信息 =====
operationInfo: {
operationType: string;
operationStartTime: string;
operationEndTime?: string;
operationStatus: 'pending' | 'success' | 'partial' | 'failed';
operationError?: {
code: string;
message: string;
context: string;
};
};
// ===== 上报信息 =====
reportInfo: {
needsReport: boolean;
reportReason?: string;
reportStartTime?: string;
reportEndTime?: string;
reportStatus: 'pending' | 'success' | 'failed' | 'cached';
reportError?: {
code: string;
message: string;
};
};
// ===== 总体诊断 =====
diagnosis: {
isAbnormal: boolean;
abnormalityLevel: 'info' | 'warning' | 'error' | 'critical';
rootCauseGuess: string;
recommendedAction: string;
userFacingMessage: string;
};
}
2.3 异常处理的决策树
enum EventAbnormalityLevel {
// ===== 信息级(可恢复) =====
INFO_QUERY_SLOW = 'query_slow', // 查询慢但成功
INFO_PARTIAL_DATA = 'partial_data', // 只有部分数据
// ===== 警告级(需关注) =====
WARNING_QUERY_TIMEOUT = 'query_timeout', // 查询超时
WARNING_NETWORK_SLOW = 'network_slow', // 网络慢
// ===== 错误级(需上报) =====
ERROR_QUERY_FAILED = 'query_failed', // 查询失败
ERROR_OPERATION_FAILED = 'operation_failed', // 业务操作失败
ERROR_REPORT_FAILED = 'report_failed', // 上报失败
// ===== 严重级(需立即处理) =====
CRITICAL_SESSION_LOST = 'session_lost', // 地图会话丢失
CRITICAL_NETWORK_DOWN = 'network_down' // 网络不可用
}
// 决策:根据异常级别,决定是否中断工作流
function shouldBlockUserOperation(level: EventAbnormalityLevel): boolean {
switch (level) {
// 不应阻断:用户可以继续操作
case EventAbnormalityLevel.INFO_QUERY_SLOW:
case EventAbnormalityLevel.INFO_PARTIAL_DATA:
case EventAbnormalityLevel.WARNING_QUERY_TIMEOUT:
case EventAbnormalityLevel.WARNING_NETWORK_SLOW:
case EventAbnormalityLevel.ERROR_QUERY_FAILED:
case EventAbnormalityLevel.ERROR_OPERATION_FAILED:
return false; // ✅ 允许继续操作
// 应阻断:无法继续安全工作
case EventAbnormalityLevel.ERROR_REPORT_FAILED:
return false; // 上报失败也不阻断,本地记录
case EventAbnormalityLevel.CRITICAL_SESSION_LOST:
case EventAbnormalityLevel.CRITICAL_NETWORK_DOWN:
return true; // ❌ 阻断用户操作,直到恢复
default:
return false;
}
}
三、完整的事件处理与异常恢复实现
3.1 事件捕获与来源保留
private markerLongClickCount: number = 0;
private lastMarkerClickInfo: {
marker: map.Marker;
captureTime: string;
position: { latitude: number; longitude: number };
title: string;
} | undefined;
private onMarkerLongClick = (marker: map.Marker): void => {
// ===== 第一步:捕获事件 =====
this.markerLongClickCount += 1;
const captureTime = timestamp();
const position = marker.getPosition();
const title = marker.getTitle();
// 第一步.1:保留事件来源(后续诊断需要)
this.lastMarkerClickInfo = {
marker,
captureTime,
position,
title
};
// 第一步.2:更新UI显示当前事件
this.evidenceState = {
query: this.evidenceState.query,
resultName: this.evidenceState.resultName,
reliability: this.evidenceState.reliability,
markerLongClickCount: this.markerLongClickCount,
poiLongClickCount: this.evidenceState.poiLongClickCount,
lastEvent: `Marker 长按:${title} @ ${position.latitude},${position.longitude}`
};
this.lastTriggerTime = captureTime;
this.operationSequence += 1;
this.lastOperationId = `MAP-${this.operationSequence}`;
// ===== 第二步:发起异步查询,但不阻断用户操作 =====
this.processMarkerClickAsync(marker, captureTime);
};
private async processMarkerClickAsync(
marker: map.Marker,
captureTime: string
): Promise<void> {
const queryStartTime = timestamp();
const position = marker.getPosition();
try {
// 第二步.1:从Marker获取额外信息(可能超时)
// 注意:这里实际的MapKit API可能不提供这样的方法,
// 这里演示的是"如果有这样的查询"的处理方式
const markerInfoPromise = this.queryMarkerInfo(marker);
const queryTimeout = new Promise((_, reject) =>
setTimeout(() => reject(new Error('query_timeout')), 5000)
);
let markerInfo: any = null;
try {
// 使用Promise.race实现超时控制
markerInfo = await Promise.race([markerInfoPromise, queryTimeout]);
} catch (queryError) {
// 查询超时或异常,但不中断流程
const isTimeout = queryError instanceof Error && queryError.message === 'query_timeout';
this.recordQueryAbnormality({
eventSource: { markerId: marker.getTitle(), position },
queryStatus: isTimeout ? 'timeout' : 'failed',
queryError: queryError as Error,
captureTime,
queryStartTime
});
// 继续允许用户操作
return;
}
// 第二步.2:查询成功,处理结果
this.handleMarkerClickSuccess(marker, markerInfo, captureTime, queryStartTime);
} catch (error) {
// 上层异常,记录但不中断
this.recordOperationAbnormality({
eventSource: { markerId: marker.getTitle(), position },
operationType: 'marker_click_processing',
operationError: error as Error,
captureTime,
queryStartTime
});
}
}
private async queryMarkerInfo(marker: map.Marker): Promise<any> {
// 这是一个模拟的查询方法
// 实际项目中可能需要调用后端API获取Marker关联的业务数据
return new Promise((resolve) => {
setTimeout(() => {
resolve({
markerId: marker.getTitle(),
data: 'marker_info_from_backend'
});
}, 1000);
});
}
private handleMarkerClickSuccess(
marker: map.Marker,
markerInfo: any,
captureTime: string,
queryStartTime: string
): void {
const queryDuration = this.calculateDuration(queryStartTime);
// 记录成功的查询
this.recordQuerySuccess({
eventSource: {
markerId: marker.getTitle(),
markerTitle: marker.getTitle(),
markerPosition: marker.getPosition()
},
queryStatus: 'success',
queryDuration,
queryResult: markerInfo,
captureTime,
queryStartTime
});
}
3.2 异常的分级记录与非阻断上报
interface AbnormalityRecord {
recordId: string;
abnormalityLevel: string;
abnormalityType: string;
eventSource: any;
captureTime: string;
error: {
message: string;
code?: string;
stack?: string;
};
userFacingMessage: string;
recommendedAction: string;
reportingStatus: 'pending' | 'success' | 'failed' | 'cached';
retryCount: number;
}
private abnormalityBuffer: AbnormalityRecord[] = [];
private recordQueryAbnormality(params: {
eventSource: any;
queryStatus: string;
queryError: Error;
captureTime: string;
queryStartTime: string;
}): void {
const queryDuration = this.calculateDuration(params.queryStartTime);
const isTimeout = params.queryStatus === 'timeout';
// ===== 第一步:判断异常级别 =====
let abnormalityLevel = 'warning';
let userMessage = '';
let recommendedAction = '';
if (isTimeout) {
abnormalityLevel = 'warning';
userMessage = `查询 Marker 信息超时(${queryDuration}ms)`;
recommendedAction = '现场人员可以继续操作,系统会自动重试';
} else {
abnormalityLevel = 'error';
userMessage = `查询 Marker 信息失败:${params.queryError.message}`;
recommendedAction = '请检查网络连接,或稍后重试';
}
// ===== 第二步:创建异常记录 =====
const record: AbnormalityRecord = {
recordId: `ABN-${Date.now()}-${Math.random().toString(36).slice(2)}`,
abnormalityLevel,
abnormalityType: isTimeout ? 'query_timeout' : 'query_failed',
eventSource: params.eventSource,
captureTime: params.captureTime,
error: {
message: params.queryError.message,
code: (params.queryError as any).code,
stack: (params.queryError as any).stack
},
userFacingMessage: userMessage,
recommendedAction,
reportingStatus: 'pending',
retryCount: 0
};
// ===== 第三步:加入缓冲区 =====
this.abnormalityBuffer.push(record);
// ===== 第四步:立即尝试上报,但不阻断 =====
this.reportAbnormalityAsync(record);
}
private async reportAbnormalityAsync(record: AbnormalityRecord): Promise<void> {
try {
// 尝试上报到后端
// const response = await reportService.reportMapEventAbnormality(record);
// 这里模拟上报
await this.simulateReportToBackend(record);
record.reportingStatus = 'success';
} catch (reportError) {
// 上报失败,本地缓存
record.reportingStatus = 'cached';
// 记录上报失败,但不影响用户操作
console.warn(`异常上报失败,已本地缓存:${record.recordId}`);
}
}
private async simulateReportToBackend(record: AbnormalityRecord): Promise<void> {
return new Promise((resolve, reject) => {
setTimeout(() => {
// 模拟网络请求
if (Math.random() > 0.3) {
resolve();
} else {
reject(new Error('network_error'));
}
}, 2000);
});
}
private recordOperationAbnormality(params: {
eventSource: any;
operationType: string;
operationError: Error;
captureTime: string;
queryStartTime: string;
}): void {
const record: AbnormalityRecord = {
recordId: `ABN-${Date.now()}-${Math.random().toString(36).slice(2)}`,
abnormalityLevel: 'error',
abnormalityType: 'operation_failed',
eventSource: params.eventSource,
captureTime: params.captureTime,
error: {
message: params.operationError.message,
code: (params.operationError as any).code
},
userFacingMessage: `操作异常:${params.operationError.message}`,
recommendedAction: '请稍后重试,或联系技术支持',
reportingStatus: 'pending',
retryCount: 0
};
this.abnormalityBuffer.push(record);
this.reportAbnormalityAsync(record);
}
private recordQuerySuccess(params: {
eventSource: any;
queryStatus: string;
queryDuration: number;
queryResult: any;
captureTime: string;
queryStartTime: string;
}): void {
// 如果查询耗时较长,记录为信息级异常
if (params.queryDuration > 3000) {
const record: AbnormalityRecord = {
recordId: `ABN-${Date.now()}-${Math.random().toString(36).slice(2)}`,
abnormalityLevel: 'info',
abnormalityType: 'query_slow',
eventSource: params.eventSource,
captureTime: params.captureTime,
error: {
message: `查询耗时过长:${params.queryDuration}ms`
},
userFacingMessage: `Marker 信息查询较慢(${params.queryDuration}ms)`,
recommendedAction: '可能的原因:网络延迟或后端服务负载高',
reportingStatus: 'pending',
retryCount: 0
};
this.abnormalityBuffer.push(record);
// 信息级异常可以异步上报,不影响正常流程
this.reportAbnormalityAsync(record);
}
}
private calculateDuration(startTimeStr: string): number {
const startTime = new Date(startTimeStr).getTime();
const endTime = new Date().getTime();
return Math.max(0, endTime - startTime);
}
3.3 POI长按事件的异常处理
private poiLongClickCount: number = 0;
private lastPoiClickInfo: {
poi: mapCommon.Poi;
captureTime: string;
position: { latitude: number; longitude: number };
} | undefined;
private onPoiLongClick = (poi: mapCommon.Poi): void => {
// ===== 事件捕获 =====
this.poiLongClickCount += 1;
const captureTime = timestamp();
// 保留POI信息
this.lastPoiClickInfo = {
poi,
captureTime,
position: poi.position
};
// ===== 更新UI =====
this.evidenceState = {
query: this.evidenceState.query,
resultName: this.evidenceState.resultName,
reliability: this.evidenceState.reliability,
markerLongClickCount: this.evidenceState.markerLongClickCount,
poiLongClickCount: this.poiLongClickCount,
lastEvent: `POI 长按:${poi.name} (${poi.id}) @ ${poi.position.latitude},${poi.position.longitude}`
};
this.lastTriggerTime = captureTime;
this.operationSequence += 1;
this.lastOperationId = `MAP-${this.operationSequence}`;
// ===== 异步处理,不阻断 =====
this.processPoiClickAsync(poi, captureTime);
};
private async processPoiClickAsync(
poi: mapCommon.Poi,
captureTime: string
): Promise<void> {
const queryStartTime = timestamp();
try {
// 基于POI的业务逻辑处理
// 例如:保存到任务、触发业务流程等
// 模拟异步操作
await this.processPOIOperation(poi);
this.recordQuerySuccess({
eventSource: {
poiId: poi.id,
poiName: poi.name,
poiAddress: poi.address || '无地址',
poiPosition: poi.position
},
queryStatus: 'success',
queryDuration: this.calculateDuration(queryStartTime),
queryResult: poi,
captureTime,
queryStartTime
});
} catch (error) {
this.recordOperationAbnormality({
eventSource: {
poiId: poi.id,
poiName: poi.name,
poiPosition: poi.position
},
operationType: 'poi_click_processing',
operationError: error as Error,
captureTime,
queryStartTime
});
}
}
private async processPOIOperation(poi: mapCommon.Poi): Promise<void> {
// 模拟POI处理逻辑
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 500);
});
}
四、异常诊断与远程支持指南
4.1 异常缓冲区的管理与重试
private async flushAbnormalityBuffer(): Promise<void> {
// 定期尝试重新上报本地缓存的异常
const cachedRecords = this.abnormalityBuffer.filter(
r => r.reportingStatus === 'cached'
);
for (const record of cachedRecords) {
try {
record.retryCount += 1;
await this.reportAbnormalityAsync(record);
} catch (error) {
// 仍然失败,继续缓存
console.warn(
`异常重新上报失败(第 ${record.retryCount} 次尝试):${record.recordId}`
);
}
}
}
private setupAbnormalityBufferFlusher(): void {
// 每30秒尝试一次重新上报
setInterval(() => {
this.flushAbnormalityBuffer();
}, 30000);
}
4.2 异常诊断报告的生成
interface DiagnosticReport {
reportGeneratedAt: string;
totalEventsProcessed: number;
abnormalityCount: {
info: number;
warning: number;
error: number;
critical: number;
};
lastMarkerClickInfo?: {
title: string;
position: string;
captureTime: string;
};
lastPoiClickInfo?: {
name: string;
position: string;
captureTime: string;
};
recentAbnormalities: AbnormalityRecord[];
cachedReports: AbnormalityRecord[];
}
private generateDiagnosticReport(): DiagnosticReport {
const abnormalityCount = {
info: 0,
warning: 0,
error: 0,
critical: 0
};
for (const record of this.abnormalityBuffer) {
if (abnormalityCount.hasOwnProperty(record.abnormalityLevel)) {
abnormalityCount[record.abnormalityLevel as keyof typeof abnormalityCount]++;
}
}
return {
reportGeneratedAt: timestamp(),
totalEventsProcessed: this.markerLongClickCount + this.poiLongClickCount,
abnormalityCount,
lastMarkerClickInfo: this.lastMarkerClickInfo ? {
title: this.lastMarkerClickInfo.title,
position: `${this.lastMarkerClickInfo.position.latitude},${this.lastMarkerClickInfo.position.longitude}`,
captureTime: this.lastMarkerClickInfo.captureTime
} : undefined,
lastPoiClickInfo: this.lastPoiClickInfo ? {
name: this.lastPoiClickInfo.poi.name,
position: `${this.lastPoiClickInfo.poi.position.latitude},${this.lastPoiClickInfo.poi.position.longitude}`,
captureTime: this.lastPoiClickInfo.captureTime
} : undefined,
recentAbnormalities: this.abnormalityBuffer.slice(-10), // 最近10条
cachedReports: this.abnormalityBuffer.filter(
r => r.reportingStatus === 'cached'
)
};
}
4.3 基于诊断报告的快速定位
| 异常类型 | 可能原因 | 诊断指标 | 建议处理 |
|---|---|---|---|
| query_timeout | 网络延迟或后端慢 | 查询耗时 > 5000ms | 检查网络,或反馈后端优化 |
| query_failed | API异常或后端错误 | 查询异常率 > 10% | 检查API返回状态,查看后端日志 |
| operation_failed | 业务逻辑异常 | 操作失败率增高 | 查看操作日志,分析业务流程 |
| report_failed | 上报失败(上报接口异常) | 缓存中有待上报记录 | 检查后端上报接口可用性 |
| network_down | 网络完全不可用 | 所有上报均失败 | 检查网络连接,或让用户离线工作 |
五、实施验收与测试清单
5.1 事件处理异常的验收标准
-
事件来源保留:
- Marker长按时保留Marker信息
- POI长按时保留POI信息
- 查询失败时仍保留事件源
-
异常分级:
- 区分信息级、警告级、错误级、严重级
- 每个等级有明确的处理策略
-
非阻断上报:
- 异常发生不中断用户操作
- 用户可继续长按其他地点
- UI能清晰展示异常状态
-
缓冲与重试:
- 上报失败时本地缓存
- 定期重试上报失败的异常
- 支持手动刷新重试
-
诊断报告:
- 能生成完整的诊断报告
- 包含事件统计、异常统计、最近异常
- 支持导出报告
5.2 远程验收的检查项
- 在网络延迟高的环境测试(模拟3G)
- 在网络断开场景测试(飞行模式)
- 在高频事件场景测试(快速连续长按)
- 验证缓存异常的定期重试
- 验证诊断报告的准确性
六、常见问题与应急处理
Q1: 异常上报失败太频繁,会不会影响用户体验?
A: 不会。因为:
- 上报是异步进行的,不阻断主流程
- 上报失败不中断用户操作
- 异常记录本地缓存,后续自动重试
- UI只显示关键异常信息,避免信息过载
建议:在现场验收时,观察异常缓冲区的增长速度。如果缓存异常数量持续增长超过100条,可能需要检查上报服务可用性。
Q2: 为什么长按Marker没有立即显示结果?
A: 可能的原因:
- Marker信息查询超时(异步进行,预期延迟3-5秒)
- 后端服务响应缓慢
- 网络连接差
建议:查看异常记录中的query_slow或query_timeout,判断是网络问题还是服务问题。
Q3: 现场工作人员报告某个Marker无法长按,如何诊断?
A: 按以下步骤诊断:
- 检查异常缓冲区是否有该Marker相关的记录
- 如果有超时记录,检查网络状况
- 如果有查询失败记录,检查后端API
- 如果没有任何异常记录,可能是Marker本身问题
建议:让现场人员在诊断报告中记录"无法长按的Marker位置",远程支持可以通过位置反查到Marker信息。
Q4: 离线工作时无法上报异常,会怎样?
A:
- 异常记录本地保存
- 当网络恢复时自动重试上报
- 用户可以手动触发重试
建议:设计离线工作的完整流程,包括"离线模式下哪些功能可用""何时重新上线"等。
总结
HarmonyOS 6.1.1 中的地图事件异常处理需要遵循以下核心原则:
- 事件来源的完整保留:长按Marker/POI时保留所有上下文信息
- 异常的分级处理:区分不同等级异常,采取不同策略
- 非阻断式的问题上报:异常发生不中断用户工作流
- 本地缓冲与重试:上报失败时本地缓存,自动重试
- 诊断信息的充分性:提供足够信息让远程支持快速定位
- 用户体验的连贯性:异常处理透明,用户感受到的是"功能仍在工作"
通过这套体系,企业可以:
- 在现场异常时继续工作,不被卡住
- 后续通过异常记录追溯问题原因
- 为远程支持提供完整的诊断信息
- 实现"网络不好也能工作"的目标
验证状态:✅ 本文对应的代码已集成到项目,所有事件处理、异常分级、缓冲管理的核心逻辑均在 MapSearchLongClickPage.ets 中完整实现,包括Marker长按、POI长按、事件计数、实时状态显示等。
后续复拍建议:计划在后续版本中支持事件查询结果的本地缓存、事件回放等高级功能。
必要条件|模拟器与真机准备对照
| 条件 | API 24 模拟器 | HarmonyOS 6.1.1 真机 |
|---|---|---|
| SDK/API与构建工具 | 使用 API 24 镜像验证构建和基础页面 | 使用兼容 API 24 的签名包安装 |
| Kit引入 | 先确认编译期 Kit 类型可用 | 再确认设备运行时模块实际可用 |
| 模块/页面配置 | 页面路由和 Stage 启动可验证 | 页面路由、签名和设备安装状态均需验证 |
| 权限 | 可演练授权弹窗和拒绝分支 | 需重新授权并确认系统设置中的真实状态 |
| 系统能力/硬件 | 只能代表模拟器提供的能力 | Camera、麦克风、地图、视觉识别等以真机能力为准 |
SDK/API 对照完成后插入 DevEco Studio API 24 与构建配置截图:

授权对照完成后插入真实设备权限截图:
版本和能力对照完成后插入设备/模拟器信息截图:

更多推荐


所有评论(0)