loadSuspend

@JvmStatic
suspend fun loadSuspend(uriString: String): Entity

Asynchronously loads a 3D model from the specified URI string and returns its root entity.

For content:// scheme, use Entity.loadSuspend(contentResolver: ContentResolver, uri: Uri) instead.

This suspend function dispatches the native load operation on Dispatchers.Main.

Return

The loaded root entity, which is attached to the scene. If any error occurs during the loading process, an ResourceLoadingException will be thrown.

Parameters

uriString

The URI representing the location of the 3D model to load. Currently supported schemes include asset:// and file://.


@JvmStatic
suspend fun loadSuspend(file: File): Entity

Asynchronously loads a 3D model from a file and returns its root entity.

This suspend function delegates to loadSuspend with a file:// URI.

Return

The loaded root entity, which is attached to the scene. If any error occurs during the loading process, an ResourceLoadingException will be thrown.

Parameters

file

The file containing the 3D model data to load. Supported file formats are .usdz and .glb.


@JvmStatic
suspend fun loadSuspend(contentResolver: ContentResolver, uri: Uri): Entity

Asynchronously loads a 3D model from a content provider URI and returns its root entity.

For asset:// or file:// scheme, use Entity.load(uriString: String) instead.

This suspend function dispatches the native load operation on Dispatchers.Main.

Memory and concurrency notes

  • This API loads through the in-memory path. The full content URI data is read before the asynchronous load starts and may be temporarily retained in memory until the loading job completes.

  • Loading multiple large content URI models in parallel can significantly increase peak memory usage and may cause an OutOfMemoryError.

  • For remote models, large models, or list/grid experiences that load multiple models, prefer copying the data to an app cache file first, then call loadSuspend with a file:// URI or loadSuspend with a File. For pages that may start many large loads at once, consider limiting concurrent model loading to fit the device memory budget.

Return

The loaded root entity, which is attached to the scene. If any error occurs during the loading process, an ResourceLoadingException will be thrown.

Parameters

contentResolver

The ContentResolver for accessing the content provider.

uri

The content Uri pointing to the 3D model data. Only content:// scheme is supported.


@JvmStatic
suspend fun loadSuspend(inputStream: InputStream, format: ModelFormat): Entity

Asynchronously loads a 3D model from an InputStream and returns its root entity.

This suspend function dispatches the native load operation on Dispatchers.Main.

Memory and concurrency notes

  • This API loads through the in-memory path. The full stream is read before the asynchronous load starts and may be temporarily retained in memory until the loading job completes.

  • Loading multiple large streams in parallel can significantly increase peak memory usage and may cause an OutOfMemoryError.

  • For remote models, large models, or list/grid experiences that load multiple models, prefer downloading or copying the data to an app cache file first, then call loadSuspend with a file:// URI or loadSuspend with a File. For pages that may start many large loads at once, consider limiting concurrent model loading to fit the device memory budget.

Return

The loaded root entity, which is attached to the scene. If any error occurs during the loading process, an ResourceLoadingException will be thrown.

Parameters

inputStream

The InputStream containing the raw model data.

format

The ModelFormat of the source of the InputStream that should be specified explicitly.


@JvmStatic
suspend fun loadSuspend(afd: AssetFileDescriptor, format: ModelFormat): Entity

Asynchronously loads a 3D model from an AssetFileDescriptor and returns its root entity.

Compared with loadSuspend from an InputStream, this overload reads the model data directly from the asset's file descriptor and avoids buffering the entire file in JVM memory.

When to use this overload

Prefer this API when:

  • The model is large (typically tens / hundreds of MB), where a byte[]-based load would risk an OutOfMemoryError or visible GC jank.

  • You are loading Gaussian Splatting scenes (.ply / .spz), large .usdz, or any asset packaged uncompressed in the APK.

  • The model already lives behind an AssetFileDescriptor coming from AssetManager.openFd(...), ContentResolver.openAssetFileDescriptor(...), DocumentFile, Storage Access Framework, or other APIs that return AFDs natively.

Advantages over the byte-array / InputStream APIs

  • Near-zero JVM heap footprint during loading — the bytes never travel through a ByteArray.

  • Lower CPU and GC pressure: no full read-then-copy step before handing data to the engine.

  • Faster time-to-first-frame for large assets, since the engine consumes data on demand.

  • Plays well with cross-process / cross-app resource handoff (content://, SAF, third-party file pickers).

  • As a suspend function it integrates naturally with structured concurrency: cancellation of the surrounding coroutine cancels the in-flight load, and withTimeout / parent-job semantics work as expected.

Supported Formats

  • All ModelFormat variants supported by the engine (USD / GLTF / OBJ / STL / PLY / SPZ).

  • The format argument MUST match the actual content of the descriptor; the SDK cannot infer the format from an AFD (there is no filename to look at).

Required AAB / APK Configuration

The asset behind the descriptor must be stored uncompressed inside the APK. For sources like AssetManager.openFd(path), that means the file extension must be present in the application's android.androidResources.noCompress list. Typical entries when working with this API are .ply, .spz and .usdz. Without this configuration, opening the descriptor itself will fail with a FileNotFoundException from the framework — before this method even runs.

AssetFileDescriptor Requirements

  • The descriptor must report a known, positive length (i.e. afd.declaredLength != AssetFileDescriptor.UNKNOWN_LENGTH and > 0). Streaming AFDs that have no declared length (typical for some ContentProvider.openFile implementations) are not supported here — fall back to loadSuspend with an InputStream, or copy the data to an app cache file first and use loadSuspend with a File.

  • Do not share the same descriptor across concurrent load calls.

Usage

val entity = context.assets.openFd("models/scene.spz").use { afd ->
Entity.loadSuspend(afd, ModelFormat.SPZ)
}

Cancellation example:

val job = lifecycleScope.launch {
val entity = context.assets.openFd("models/scene.spz").use { afd ->
Entity.loadSuspend(afd, ModelFormat.SPZ)
}
// ... attach entity to scene ...
}
// Cancelling the job aborts the in-flight load.
job.cancel()

Resource Management

  • The caller opens and closes the AssetFileDescriptor. Using .use { } as shown above is recommended.

  • It is safe to close the descriptor as soon as this method returns control to the caller; the loaded entity does not depend on the descriptor staying open.

Performance Notes

  • Avoiding the JVM-heap copy only optimizes the loading phase. After loading completes, the runtime cost (GPU / CPU / VRAM) of the resulting entity is the same as for any other load API.

  • Texture limits still apply: a single texture (including its mipmaps) cannot exceed 256 MB. Pre-compress textures (ASTC / ETC2) when possible.

  • For pages that may start many large loads at once, consider limiting concurrent model loading to fit the device memory budget.

  • When opening cross-app content:// URIs, be prepared to handle SecurityException / unknown-length AFDs at the call site.

Return

The root entity of the loaded scene, attached to the scene graph. If any error occurs during the loading process, a ResourceLoadingException will be thrown. IO failures while reading the descriptor are propagated to the caller as java.io.IOException (not wrapped).

Parameters

afd

An AssetFileDescriptor pointing to the raw model data.

format

The ModelFormat of the data referenced by afd (must match actual content).


@JvmStatic
suspend fun loadSuspend(modelName: String, bundle: AssetBundle): Entity

Asynchronously loads an entity from the specified model name in the AssetBundle, and the root node will be returned as an entity.

This suspend function dispatches the native load operation on Dispatchers.Main.

Return

The loaded root entity, which is attached to the scene. If any error occurs during the loading process, an ResourceLoadingException will be thrown.

Parameters

modelName

The name of the model in the asset bundle.

bundle

The asset bundle containing the model.