如何修复创建Anchor时出现的AR_ERROR_NOT_TRACKING错误
解决AR Core创建Anchor时的
AR_ERROR_NOT_TRACKING崩溃问题 嘿,我一眼就看出问题所在了——你在onCreate方法里直接调用session.createAnchor(),这时候AR Core的相机跟踪还没准备好呢!
AR Core启动后需要先完成环境检测、初始化跟踪状态,这个过程不是瞬间完成的。在onCreate阶段,Session刚被初始化,相机还没开始正常跟踪,这时候强行创建Anchor肯定会触发AR_ERROR_NOT_TRACKING错误。
下面是具体的修复方案和修改后的代码:
核心修复思路
- 不要在Activity初始化阶段创建Anchor:
onCreate是Activity启动的早期阶段,AR SceneView还没进入渲染循环,跟踪状态根本没稳定下来。 - 监听跟踪状态,等待合适时机:通过AR SceneView的帧回调,等到相机跟踪状态变为
TrackingState.TRACKING时,再执行创建Anchor的操作。 - 确保模型渲染器加载完成:避免因为
markerRenderable还没加载好导致空指针。
修改后的完整代码
private ArFragment fragment; private Session mSession; private ModelRenderable markerRenderable; // 标记是否已创建Anchor,避免重复执行 private boolean anchorCreated = false; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (!checkIsSupportedDeviceOrFinish(this)){ return; } setContentView(R.layout.activity_navigation); fragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.sceneform_fragment); // 初始化Session if (mSession == null){ try { mSession = new Session(this); fragment.getArSceneView().setupSession(mSession); } catch (UnavailableArcoreNotInstalledException | UnavailableApkTooOldException | UnavailableSdkTooOldException | UnavailableDeviceNotCompatibleException e) { e.printStackTrace(); } } // 异步加载模型渲染器 ModelRenderable.builder() .setSource(this, Uri.parse("marker.sfb")) .build() .thenAccept(renderable -> markerRenderable = renderable) .exceptionally( throwable -> { Toast toast = Toast.makeText(this, "Unable to load marker renderable", Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); return null; }); // 设置场景更新监听器,在每帧更新时检查跟踪状态 fragment.getArSceneView().getScene().addOnUpdateListener(frameTime -> { Frame frame = fragment.getArSceneView().getArFrame(); // 跳过无效帧或模型未加载完成的情况 if (frame == null || markerRenderable == null || anchorCreated) { return; } // 检查相机当前的跟踪状态 TrackingState trackingState = frame.getCamera().getTrackingState(); if (trackingState == TrackingState.TRACKING) { // 跟踪状态稳定,创建Anchor createFixedPositionAnchor(); anchorCreated = true; } }); } private void createFixedPositionAnchor() { Session session = fragment.getArSceneView().getSession(); if (session == null) { Toast.makeText(this, "AR Session not available", Toast.LENGTH_SHORT).show(); return; } float[] position = { 0, 0, (float)-0.75}; // 距离相机75cm的位置 float[] rotation = { 0, 0, 0, 1 }; try { Anchor anchor = session.createAnchor(new Pose(position, rotation)); AnchorNode anchorNode = new AnchorNode(anchor); anchorNode.setRenderable(markerRenderable); anchorNode.setParent(fragment.getArSceneView().getScene()); } catch (NotTrackingException e) { // 保险起见捕获异常,避免崩溃 e.printStackTrace(); Toast.makeText(this, "Failed to create anchor: Camera not tracking", Toast.LENGTH_SHORT).show(); } }
关键修改点说明
- 把创建Anchor的逻辑移到了
addOnUpdateListener的帧回调中,确保只有在相机跟踪状态稳定时才执行。 - 增加了
anchorCreated布尔标记,防止每帧都尝试创建Anchor,避免重复操作。 - 在创建Anchor前先检查
markerRenderable是否加载完成,避免空指针异常。 - 捕获了
NotTrackingException,即使跟踪状态判断有误差,也不会直接崩溃应用。
额外注意事项
- AR Core的跟踪状态稳定需要几秒时间,启动后不要着急创建Anchor。
- 如果是要创建地理位置相关的Anchor,还需要确保设备位置服务开启,且AR Core版本在1.20以上(支持地理定位Anchor)。
- 所有AR相关的操作(如创建Anchor、操作Session)都必须在主线程执行,不要在子线程中调用。
内容的提问来源于stack exchange,提问作者ZQ.O
相关产品推荐
相关产品推荐

