无法成功托管云锚点并无法从 google 云锚点 api 检索云锚点 ID

Unable to host cloud anchors successfully and retrieve cloud anchor id from google cloud anchor api

我正在尝试在 google arcore cloud api 上托管云锚点。我在我的清单中包含了 api 键。我还可以看到 android 设备在我想要托管锚点时发出的请求,并且还有从 api 发回的响应,如下图所示。

但是,云锚点状态永远不会更改为 SUCCESS,并且我永远不会从 google 收到云锚点 ID,即使我已经设置了更新侦听器来执行此操作,如下所示。通过调试程序,我可以看到 AppAnchorState 从未从 NONE 更改,但我还没有设法收集任何其他信息。

我同时使用 sceneform 和 arcore 1.7.0。下面是我用来尝试托管我的锚点并从 api 获取云锚点 ID 的代码。

任何帮助将不胜感激,因为在此阶段我已经为这个问题苦苦挣扎了几个小时。

public class ArActivity extends AppCompatActivity {

    private enum AppAnchorState {
        NONE,
        HOSTING,
        HOSTED,
        RESOLVING,
        RESOLVED
    }

    private AppAnchorState appAnchorState = AppAnchorState.NONE;

    private static final String TAG = ArActivity.class.getSimpleName();
    private static final double MIN_OPENGL_VERSION = 3.0;
    private static final String GLTF_ASSET = "https://github.com/KhronosGroup/glTF-Sample-Models/raw/master/2.0/Duck/glTF/Duck.gltf";

    private ArFragment arFragment;
    private ModelRenderable renderable;
    private SnackbarHelper snackbarHelper;
    private Anchor cloudAnchor;

    @Override
    @SuppressWarnings({"AndroidApiChecker", "FutureReturnValueIgnored"})
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (!checkIsSupportedDeviceOrFinish(this)) {
            return;
        }

        snackbarHelper = new SnackbarHelper();

        setContentView(R.layout.activity_ux);
        arFragment = (CustomArFragment) getSupportFragmentManager().findFragmentById(R.id.sceneform_fragment);
        arFragment.getArSceneView().getScene().addOnUpdateListener(this::onUpdateFrame);

        ModelRenderable.builder()
                .setSource(this, RenderableSource.builder().setSource(
                        this,
                        Uri.parse(GLTF_ASSET),
                        RenderableSource.SourceType.GLTF2)
                        .build())
                .setRegistryId(GLTF_ASSET)
                .build()
                .thenAccept(renderable -> this.renderable = renderable)
                .exceptionally(
                        throwable -> {
                            Toast toast =
                                    Toast.makeText(this, "Unable to load renderable " +
                                            GLTF_ASSET, Toast.LENGTH_LONG);
                            toast.setGravity(Gravity.CENTER, 0, 0);
                            toast.show();
                            return null;
                        });

        Button clearButton = findViewById(R.id.clear_button);
        clearButton.setOnClickListener(view -> setCloudAnchor(null));

        Button hostButton = findViewById(R.id.host_button);
        hostButton.setOnClickListener(view -> hostModel());

        arFragment.setOnTapArPlaneListener(
            (HitResult hitResult, Plane plane, MotionEvent motionEvent) -> {
                if (renderable == null) {
                    return;
                }

                // Create the Anchor.
                Anchor anchor = hitResult.createAnchor();
                setCloudAnchor(anchor);

                AnchorNode anchorNode = new AnchorNode(cloudAnchor);
                TransformableNode node = new TransformableNode(arFragment.getTransformationSystem());
                node.setRenderable(renderable);
                node.setParent(anchorNode);
                arFragment.getArSceneView().getScene().addChild(anchorNode);
                node.select();
            });
    }

    private void hostModel() {
        if (cloudAnchor != null) {
            arFragment.getArSceneView().getSession().hostCloudAnchor(cloudAnchor);
            appAnchorState = AppAnchorState.HOSTING;
            snackbarHelper.showMessage(this, "Now hosting anchor...");
        } else {
            snackbarHelper.showMessage(this, "No anchor to host, Please create an anchor...");
        }
    }

    private void setCloudAnchor (Anchor newAnchor){
        if (cloudAnchor != null){
            cloudAnchor.detach();
        }

        cloudAnchor = newAnchor;
        appAnchorState = AppAnchorState.NONE;
        snackbarHelper.hide(this);
    }

    private void onUpdateFrame(FrameTime frameTime){
        checkUpdatedAnchor();
    }

    private synchronized void checkUpdatedAnchor(){
        if (appAnchorState != AppAnchorState.HOSTING){
            return;
        }
        Anchor.CloudAnchorState cloudState = cloudAnchor.getCloudAnchorState();
        if (appAnchorState == AppAnchorState.HOSTING) {
            if (cloudState.isError()) {
                snackbarHelper.showMessageWithDismiss(this, "Error hosting anchor.. "
                        + cloudState);
                appAnchorState = AppAnchorState.NONE;
            } else if (cloudState == Anchor.CloudAnchorState.SUCCESS) {
                snackbarHelper.showMessageWithDismiss(this, "Anchor hosted with id "
                        + cloudAnchor.getCloudAnchorId());
                appAnchorState = AppAnchorState.HOSTED;
            }
        }
    }

    public static boolean checkIsSupportedDeviceOrFinish(final Activity activity) {
        String openGlVersionString =
                ((ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE))
                        .getDeviceConfigurationInfo()
                        .getGlEsVersion();
        if (Double.parseDouble(openGlVersionString) < MIN_OPENGL_VERSION) {
            Log.e(TAG, "Sceneform requires OpenGL ES 3.0 later");
            Toast.makeText(activity, "Sceneform requires OpenGL ES 3.0 or later", Toast.LENGTH_LONG)
                    .show();
            activity.finish();
            return false;
        }
        return true;
    }
}
public class CustomArFragment extends ArFragment {

    @Override
    protected Config getSessionConfiguration(Session session) {
        Config config = super.getSessionConfiguration(session);
        config.setCloudAnchorMode(Config.CloudAnchorMode.ENABLED);
        return config;
    }

}

所以我想通了我的问题是什么。我没有设置云锚来监听服务器的变化。这就是为什么我可以在 google api 上看到 activity 但设备上什么也没有发生。

我所要做的就是更改这段代码:

private void hostModel() {
        if (cloudAnchor != null) {
            arFragment.getArSceneView().getSession().hostCloudAnchor(cloudAnchor);
            appAnchorState = AppAnchorState.HOSTING;
            snackbarHelper.showMessage(this, "Now hosting anchor...");
        } else {
            snackbarHelper.showMessage(this, "No anchor to host, Please create an anchor...");
        }
    }

并设置 cloudAnchor 以侦听更改:

private void hostModel() {
        if (cloudAnchor != null) {
            cloudAnchor = arFragment.getArSceneView().getSession().hostCloudAnchor(cloudAnchor);
            appAnchorState = AppAnchorState.HOSTING;
            snackbarHelper.showMessage(this, "Now hosting anchor...");
        } else {
            snackbarHelper.showMessage(this, "No anchor to host, Please create an anchor...");
        }
    }