loadSuspend
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
The URI representing the location of the 3D model to load. Currently supported schemes include asset:// and file://.
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
The file containing the 3D model data to load. Supported file formats are .usdz and .glb.
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
The ContentResolver for accessing the content provider.
The content Uri pointing to the 3D model data. Only content:// scheme is supported.
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
The InputStream containing the raw model data.
The ModelFormat of the source of the InputStream that should be specified explicitly.
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
suspendfunction it integrates naturally with structured concurrency: cancellation of the surrounding coroutine cancels the in-flight load, andwithTimeout/ 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_LENGTHand> 0). Streaming AFDs that have no declared length (typical for someContentProvider.openFileimplementations) 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
An AssetFileDescriptor pointing to the raw model data.
The ModelFormat of the data referenced by afd (must match actual content).
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
The name of the model in the asset bundle.
The asset bundle containing the model.