Skip to content

Geospatial: ARCore API Key is not inserted into Android Manifest? #420

@johannesvollmer

Description

@johannesvollmer

Observed problem: I tried using the geospatial feature, but it just immediately started in "Stopped" earth tracking mode.

Assumed cause: This problem was really hard to debug for me, because the ARCore library did not specify the cause of the problem. I tried many things to solve it, and finally it worked after I manually inserted our ARCore API Key into the android manifest file after building.

Reproduction Steps

  const tracking = await arSceneNavigator.getEarthTrackingState();
  log.info("Tracking state: " + tracking.state);
  1. Delete /android folder to remove previously generated files
  2. Run the npx expo prebuild command
  3. Run the npx expo run:android command
  4. Observe tracking mode immediately being "stopped"

After manually inserting the ARCore API Key into the generated AndroidManifest.xml, and performing the steps again, it works in our setup.

Context

  • We are using expo prebuilt workflow, regenerating the folder from scratch each time
  • Developing on Windows, running on Android
  • We are trying to load the api key using config.js, see below. The code checks for the existence of the environment variable, so this can't be the problem

app.config.ts

 { 
  "plugins": [
      [
        "@reactvision/react-viro",
        {
          googleCloudApiKey: getGeospatialARCoreApiKey(),
          geospatialAnchorProvider: "arcore",
          android: { xRMode: ["AR"] },
        }
      ]
  ]
}

export function getGeospatialARCoreApiKey() {
  return validate(process.env["GEOSPATIAL_ARCORE_KEY"], "Google Geospatial ARCore API Key");
}

function validate(value: string | undefined, name: string): string {
  if (!value || value.length === 0) {
    throw new Error(
      `Missing required environment variable: '${name}'. Add it to your .env file. Check company Bitwarden or use your own.`,
    );
  }

  return value;
}

package.json/dependencies

    "@reactvision/react-viro": "2.50.1",
    "babel-preset-expo": "~54.0.9",
    "expo": "^54.0.0",
    "expo-asset": "~12.0.12",
    "expo-build-properties": "~1.0.10",
    "react": "19.1.0",
    "react-native": "0.81.5",

Workaround

After adding the following postbuild script, it seems to work reliably: `patch-viro-missing-api-key.ts`. Click to see file contents.
// Idempotent patcher for AndroidManifest.xml:
// Inserts ARCore Api key into Android Manifest if it is missing.
/* eslint-disable no-console */

import fs from "node:fs";
import path from "node:path";
import * as env from "dotenv";

const missingManifestEntry = () =>
  `<meta-data android:name="com.google.android.ar.API_KEY" android:value="${getGeospatialARCoreApiKey()}"/>`;

function patchArcoreApiKey(src: string) {
  if (src.includes("com.google.android.ar.API_KEY")) return src;
  const insertAt = src.indexOf("<activity");
  if (insertAt < 0) return src;
  return src.slice(0, insertAt) + missingManifestEntry() + "\n    " + src.slice(insertAt);
}

(function main() {
  try {
    env.config({ override: true });
    const file = path.join(path.resolve(process.cwd()), "android", "app", "src", "main", "AndroidManifest.xml");

    const src = fs.readFileSync(file, "utf8");
    let fixedSrc: string = patchArcoreApiKey(src);

    if (src !== fixedSrc) {
      fs.writeFileSync(file, fixedSrc, "utf8");
      console.log(`Patch Missing API Keys | Patched ${file}`);
    } else {
      console.log(`Patch Missing API Keys | No changes needed for ${file}`);
    }
  } catch (e) {
    console.error("Patch Missing API Keys | Error:", e);
  }
})();

export function getGeospatialARCoreApiKey() {
  // Note: This env variable does not use the EXPO prefix, as it is only used at build time by custom scripts, never used at runtime.
  return validateEnvVar(process.env["GEOSPATIAL_ARCORE_KEY"], "Google Geospatial ARCore API Key");
}

function validateEnvVar(value: string | undefined, name: string): string {
  if (!value || value.length === 0) {
    throw new Error(
      `Missing required environment variable: '${name}'. Add it to your .env file. Check company Bitwarden or use your own.`,
    );
  }

  return value;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions