我正在尝试在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;
}
}