English | 中文
The global entry point, responsible for engine initialization, theme registration, and custom extension registration. On Android it is accessed as a singleton; on iOS via AGenUISDK static methods; on HarmonyOS via AGenUI static methods.
| Platform | Method signature | Notes |
|---|---|---|
| Android | AGenUI.getInstance().initialize(Context applicationContext) |
Must be called before creating any SurfaceManager |
| iOS | No explicit initialization needed | Triggered automatically on first SurfaceManager creation |
| HarmonyOS | No explicit initialization needed | Triggered automatically on first SurfaceManager creation |
// Android — call in Application.onCreate()
AGenUI.getInstance().initialize(this);Sets the global day/night mode. After switching, already-rendered Surfaces automatically refresh their colors according to the registered theme tokens.
| Platform | Method signature |
|---|---|
| Android | void setDayNightMode(String mode) |
| iOS | static func setDayNightMode(_ mode: String) |
| HarmonyOS | static setDayNightMode(mode: string): void |
mode accepted values: "light" / "dark"
// Android
AGenUI.getInstance().setDayNightMode("dark");// iOS
AGenUISDK.setDayNightMode("dark")// HarmonyOS
AGenUI.setDayNightMode('dark');Registers the default theme configuration and design tokens. Should be called before creating any SurfaceManager. Both theme and designToken are JSON strings.
| Platform | Method signature |
|---|---|
| Android | void registerDefaultTheme(String theme, String designToken) throws ThemeException |
| iOS | static func registerDefaultTheme(_ theme: String, designToken: String) -> AGenUIError |
| HarmonyOS | static registerDefaultTheme(theme: string, designToken: string): boolean |
Error handling
| Platform | Error type | Notes |
|---|---|---|
| Android | ThemeException (checked exception) |
Thrown when theme JSON is malformed |
| iOS | AGenUIError (return value) |
Failure when result == false; see the message field |
| HarmonyOS | boolean (return value) |
Returns false on failure |
// Android
try {
AGenUI.getInstance().registerDefaultTheme(themeJson, designTokenJson);
} catch (ThemeException e) {
Log.e("AGenUI", "Theme error: " + e.getMessage());
}// iOS
let error = AGenUISDK.registerDefaultTheme(themeJson, designToken: designTokenJson)
if !error.result {
print("Theme error: \(error.message)")
}// HarmonyOS
const success = AGenUI.registerDefaultTheme(themeJson, designTokenJson);
if (!success) {
console.error('Theme registration failed');
}Sets path configuration for the engine.
| Platform | Method signature | Return value |
|---|---|---|
| Android | boolean setPathConfig(String configJson) |
boolean |
| iOS | static func setPathConfig(_ configJson: String) -> AGenUIError |
AGenUIError |
| HarmonyOS | static setPathConfig(configJson: string): boolean |
boolean |
configJson example: {"templateDir": "/absolute/path/to/templates"}
| Platform | Custom logger | Set min log level | Get min log level | SDK version |
|---|---|---|---|---|
| Android | void setCustomLogger(IAGenUILogger customLogger) |
void setMinLogLevel(int level) |
int getMinLogLevel() |
static String getVersion() |
| iOS | static func setCustomLogger(_ customLogger: LoggerDelegate?) |
static func setMinLogLevel(_ level: Logger.Level) |
static func getMinLogLevel() -> Logger.Level |
static func getVersion() -> String |
| HarmonyOS | static setCustomLogger(logger: IAGenUILogger): void |
static setMinLogLevel(level: number): void |
static getMinLogLevel(): number |
static getVersion(): string |
levelvalues:0=DEBUG,1=INFO,2=WARNING,3=ERROR,4=FATAL,5=PERFORMANCE.- On Android, call
setCustomLoggerbeforeinitialize()to capture all engine logs.
Each SurfaceManager instance corresponds to an independent streaming session; multiple instances may coexist.
| Platform | Constructor |
|---|---|
| Android | new SurfaceManager(Activity activity) |
| iOS | SurfaceManager() |
| HarmonyOS | new SurfaceManager(context: UIAbilityContext) |
- Android requires
AGenUI.getInstance().initialize(context)to be completed first; otherwise anIllegalStateExceptionis thrown. - iOS / HarmonyOS trigger engine initialization automatically during construction.
// Android
SurfaceManager surfaceManager = new SurfaceManager(activity);// iOS
let surfaceManager = SurfaceManager()// HarmonyOS
const surfaceManager = new SurfaceManager(context);Full call order: beginTextStream() → receiveTextChunk(chunk) × N → endTextStream()
| Platform | beginTextStream |
receiveTextChunk |
endTextStream |
|---|---|---|---|
| Android | void beginTextStream() |
void receiveTextChunk(String dataString) |
void endTextStream() |
| iOS | func beginTextStream() |
func receiveTextChunk(_ dataString: String) |
func endTextStream() |
| HarmonyOS | beginTextStream(): void |
receiveTextChunk(dataString: string): void |
endTextStream(): void |
beginTextStream()starts a new streaming session and clears the internal buffer.receiveTextChunk()supports fragmented delivery or a single complete JSON payload.endTextStream()ends the current streaming session. Call this when the SSE stream closes, the HTTP response ends, the user cancels, or a network disconnect occurs.
Re-evaluates every component's attributes and styles across all Surfaces, then emits field-level diffs to the native renderer for any value that actually changed.
Call this when host-owned external state (theme, locale, orientation, etc.) has changed and registered FunctionCalls need to be re-run.
| Platform | Method signature |
|---|---|
| Android | void invalidateFunctionCallValues() |
| iOS | func invalidateFunctionCallValues() |
| HarmonyOS | — |
Add or remove Surface lifecycle listeners. All platforms support registering multiple listeners simultaneously.
| Platform | Method signatures |
|---|---|
| Android | void addListener(ISurfaceManagerListener listener) / void removeListener(ISurfaceManagerListener listener) |
| iOS | func addListener(_ listener: SurfaceManagerListener) / func removeListener(_ listener: SurfaceManagerListener) / func removeAllListeners() |
| HarmonyOS | addListener(listener: ISurfaceManagerListener): void / removeListener(listener: ISurfaceManagerListener): void / removeAllListeners(): void |
iOS stores listeners as weak references, so there is no risk of retain cycles.
Retrieves an existing Surface instance by surfaceId.
| Platform | Method signature |
|---|---|
| Android | Surface getSurface(String surfaceId) |
| iOS | — |
| HarmonyOS | getSurface(surfaceId: string): Surface | null |
Returns the native instance id assigned by the engine on creation.
| Platform | Method signature |
|---|---|
| Android | int getInstanceId() |
| iOS | func getInstanceId() -> Int |
| HarmonyOS | getInstanceId(): number |
| Platform | Method signature | Notes |
|---|---|---|
| Android | void destroy() |
Destroys all Surfaces, removes all listeners, releases NativeEventBridge resources |
| iOS | Executed automatically on deinit |
Call removeAllListeners() to ensure no retain cycles |
| HarmonyOS | destroy(): void |
Destroys all Surfaces and releases native resources |
Android — ISurfaceManagerListener
public interface ISurfaceManagerListener {
void onCreateSurface(Surface surface);
void onDeleteSurface(Surface surface);
default void onReceiveActionEvent(String event) {}
default void onRootComponentUpdate(Surface surface, Map<String, String> props) {}
default void onError(Surface surface, int code, String message) {}
default void onBlankCheckResult(Surface surface, boolean isBlank) {}
}iOS — SurfaceManagerListener
@objc public protocol SurfaceManagerListener: AnyObject {
@objc optional func onCreateSurface(_ surface: Surface)
@objc optional func onDeleteSurface(_ surface: Surface)
@objc optional func onReceiveActionEvent(_ event: String)
@objc optional func onRootComponentUpdate(_ surface: Surface, props: [String: Any])
@objc optional func onError(_ surface: Surface?, code: Int, message: String)
@objc optional func onBlankCheckResult(_ surface: Surface, isBlank: Bool)
}HarmonyOS — ISurfaceManagerListener
export interface ISurfaceManagerListener {
onCreateSurface?: (surface: Surface) => void;
onDeleteSurface?: (surface: Surface) => void;
onReceiveActionEvent?: (event: string) => void;
onError?: (surface: Surface | null, code: number, message: string) => void;
}Android
surfaceManager.addListener(new ISurfaceManagerListener() {
@Override
public void onCreateSurface(Surface surface) {
ViewGroup container = surface.getContainer();
parentLayout.addView(container, new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.WRAP_CONTENT
));
}
@Override
public void onDeleteSurface(Surface surface) {
// Remove the corresponding view
}
});iOS
class MyViewController: UIViewController, SurfaceManagerListener {
func onCreateSurface(_ surface: Surface) {
view.addSubview(surface.view)
surface.updateSize(width: self.view.bounds.width, height: .infinity)
}
func onDeleteSurface(_ surface: Surface) {
surface.view.removeFromSuperview()
}
}
surfaceManager.addListener(self)HarmonyOS
const listener: ISurfaceManagerListener = {
onCreateSurface: (surface: Surface) => {
this.surfaceId = surface.surfaceId; // Save surfaceId for use with AGenUIContainer
},
onDeleteSurface: (surface: Surface) => {
this.surfaceId = '';
}
};
surfaceManager.addListener(listener);Surface represents a complete rendering unit. It is created by SurfaceManager via listener callbacks and should not be constructed directly.
| Property | Android | iOS | HarmonyOS |
|---|---|---|---|
| Surface ID | getSurfaceId(): String |
surfaceId: String |
surfaceId: string |
| Root container | getContainer(): ViewGroup |
view: UIView |
Rendered via AGenUIContainer; no view property |
| Animation toggle | setAnimationEnabled(boolean) / isAnimationEnabled(): boolean |
animationEnabled: Bool (default true) |
animationEnabled: boolean (default true) |
| Raw protocol content | getRawProtocolContent(): String / setRawProtocolContent(String) |
rawProtocolContent: String |
rawProtocolContent: string |
| Size update | — | updateSize(width: CGFloat, height: CGFloat) |
— |
| Blank-screen check | startBlankCheck(long delayMs, int validComponentCount) / cancelBlankCheck() |
startBlankCheck(checkDelayMs: Int, validComponentCount: Int) |
— |
HarmonyOS — rendering container
// Use in build()
AGenUIContainer({ surfaceId: this.surfaceId })
.width('100%')Registering a custom component requires: defining the component class, registering a component factory, and unregistering when no longer needed.
| Platform | Registration method |
|---|---|
| Android | AGenUI.getInstance().registerComponent(String type, IComponentFactory creator) |
| iOS | AGenUISDK.registerComponent(_ type: String, creator: (String, [String: Any]) -> Component) |
| iOS (ObjC) | AGenUISDK.registerComponentObjC(_ type: String, creator: (String, [String: Any]) -> Component) |
| iOS (ObjC + className) | AGenUISDK.registerComponentObjC(_ type: String, componentClassName: String, creator: (String, [String: Any]) -> Component) |
| HarmonyOS | AGenUI.registerComponent(type: string, creator: IComponentFactory) |
Android — IComponentFactory
public interface IComponentFactory {
A2UIComponent createComponent(Context context, String id, Map<String, Object> properties);
String getComponentType();
}iOS — factory closure
// creator closure signature: (componentId: String, properties: [String: Any]) -> Component
AGenUISDK.registerComponent("MyButton") { id, properties in
return MyButtonComponent(id: id, properties: properties)
}HarmonyOS — IComponentFactory
export type IComponentFactory = (
surfaceId: string,
nodeId: string,
componentType: string,
viewStatePtr: bigint
) => A2UIComponent;Lottie Component Example
- Android:
- Factory:
playground/android/app/src/main/java/com/amap/agenuiplayground/component/factory/LottieComponentFactory.java - Component:
playground/android/app/src/main/java/com/amap/agenuiplayground/component/impl/LottieComponent.java
- Factory:
- iOS:
playground/ios/Playground/Playground for AGenUI/CustomComponent/LottieComponent.swift - HarmonyOS:
playground/harmony/entry/src/main/ets/components/CustomLottieComponent.ets
| Platform | Method signature |
|---|---|
| Android | AGenUI.getInstance().unregisterComponent(String type) |
| iOS | AGenUISDK.unRegisterComponent(_ type: String) |
| HarmonyOS | AGenUI.unRegisterComponent(type: string) |
Custom components on Android and HarmonyOS must inherit from A2UIComponent. iOS custom components must inherit from Component.
Android — A2UIComponent
public abstract class A2UIComponent {
public A2UIComponent(String id, String componentType)
// Must be implemented by subclasses
protected abstract View onCreateView(Context context);
protected abstract void onUpdateProperties(Map<String, Object> properties);
// Helper methods
public final void triggerAction() // Trigger a component Action event
public final void syncState(String jsonData) // Sync UI state to the data model
public String getId()
public String getComponentType()
public View getView()
public Map<String, Object> getProperties()
public String getSurfaceId()
public boolean shouldAutoAddChildView() // Default true; child views are added to the container automatically
public void addChild(A2UIComponent child)
public void removeChild(A2UIComponent child)
}HarmonyOS — A2UIComponent
export abstract class A2UIComponent {
constructor(surfaceId: string, nodeId: string, componentType: string,
viewStatePtr: bigint, builder: WrappedBuilder<[CustomView]>)
// Must be implemented by subclasses
protected abstract onUpdateProperties(properties: A2UIComponentProps): void;
// Helper methods
public getProp<T>(key: string): T | undefined
public getLayoutWidth(): number
public getLayoutHeight(): number
public getSurfaceId(): string
public getNodeId(): string
public shouldAutoAddChildView(): boolean // Default false
}iOS — Component
@objc open class Component: UIView {
// Initialization
public init(componentId: String, componentType: String, properties: [String: Any] = [:])
// Core properties
public let componentId: String // Unique component identifier
public let componentType: String // Component type
public var properties: [String: Any] // Component properties
// Tree structure management
public private(set) var children: [Component] // Child components list
public weak var parent: Component? // Parent component
public weak var surface: Surface? // Owning Surface
// Lifecycle methods (subclasses can override)
open func updateProperties(_ properties: [String: Any]) // Called when properties update
// Helper methods
public final func triggerAction() // Trigger component Action event
public final func syncState(_ change: [String: Any]) // Sync UI state to data model
public func getChildrenIdsFromProperties() -> [String] // Get child component IDs from properties
public func addChild(_ child: Component) // Add child component
public func removeChild(_ child: Component) // Remove child component
public func getChild(_ id: String) -> Component? // Get specific child component
public func destroy() // Destroy component
}Custom functions allow UI components to invoke host application capabilities (e.g., navigation, data queries).
| Platform | Registration method |
|---|---|
| Android | AGenUI.getInstance().registerFunction(IFunction function) |
| iOS | AGenUISDK.registerFunction(_ function: Function) |
| HarmonyOS | AGenUI.registerFunction(func: IFunctionCall) |
Android — IFunction
public interface IFunction {
FunctionResult execute(FunctionCallContext context, String jsonString);
FunctionConfig getConfig();
}
public class FunctionCallContext {
public final int instanceId;
public final String surfaceId;
}
public class FunctionConfig {
public FunctionConfig(String name)
public String getName()
public String toJSON() // Serializes to {"name": "..."}
}
public class FunctionResult {
public static FunctionResult createSuccess(Object value)
public static FunctionResult createError(String error)
public static FunctionResult createPending(String requestId)
public JSONObject toJson()
public String toJsonString()
}iOS — Function protocol
@objc public protocol Function: AnyObject {
@objc var functionConfig: FunctionConfig { get }
@objc func execute(context: FunctionCallContext, params: String) -> FunctionResult
}
@objc public class FunctionCallContext: NSObject {
@objc public let instanceId: Int
@objc public let surfaceId: String
@objc public init(instanceId: Int, surfaceId: String)
}
@objc public class FunctionConfig: NSObject {
@objc public let name: String
@objc public init(name: String)
@objc public func toJSON() -> String
}
@objc public class FunctionResult: NSObject {
@objc public let result: Bool
@objc public let value: String
@objc public static func success(value: String) -> FunctionResult
@objc public static func failure(value: String) -> FunctionResult
}HarmonyOS — IFunctionCall
export interface FunctionCallContext {
instanceId: number;
surfaceId: string;
}
export interface IFunctionCall {
execute(context: FunctionCallContext, paramsJson: string): FunctionResult;
getConfig(): FunctionConfig;
}
export class FunctionConfig {
name: string = '';
}
export class FunctionResult {
result: boolean = false;
value: object | string | undefined = undefined;
static createSuccess(value: object): FunctionResult
static createError(error: string): FunctionResult
}Android
AGenUI.getInstance().registerFunction(new IFunction() {
@Override
public FunctionResult execute(FunctionCallContext context, String jsonString) {
return FunctionResult.createSuccess("success");
}
@Override
public FunctionConfig getConfig() {
return new FunctionConfig("openPage");
}
});iOS
class OpenPageFunction: NSObject, Function {
let functionConfig = FunctionConfig(name: "openPage")
func execute(context: FunctionCallContext, params: String) -> FunctionResult {
return FunctionResult.success(value: "{}")
}
}
AGenUISDK.registerFunction(OpenPageFunction())HarmonyOS
const openPageFunc: IFunctionCall = {
execute(context: FunctionCallContext, paramsJson: string): FunctionResult {
return FunctionResult.createSuccess({ status: 'ok' });
},
getConfig(): FunctionConfig {
return { name: 'openPage' };
}
};
AGenUI.registerFunction(openPageFunc);Toast Function Example
- Android:
playground/android/app/src/main/java/com/amap/agenuiplayground/function/ToastFunction.java - iOS:
playground/ios/Playground/Playground for AGenUI/Function/ToastFunction.swift - HarmonyOS:
playground/harmony/entry/src/main/ets/functions/ToastFunction.ets
| Platform | Method signature |
|---|---|
| Android | AGenUI.getInstance().unregisterFunction(String name) |
| iOS | AGenUISDK.unregisterFunction(_ name: String) |
| HarmonyOS | AGenUI.unregisterFunction(name: string) |
The SDK does not include built-in image loading — the host application must provide an implementation.
| Platform | Registration method |
|---|---|
| Android | AGenUI.getInstance().registerImageLoader(ImageLoader loader) |
| iOS | AGenUISDK.registerImageLoader(_ loader: ImageLoader) |
| HarmonyOS | AGenUI.registerImageLoader(loader: IImageLoader) |
Android — ImageLoader
public interface ImageLoader {
String loadImage(@NonNull String url, @Nullable Map<String, Object> options,
@NonNull ImageCallback callback);
default String loadImage(@NonNull String url, @NonNull ImageCallback callback);
void cancel(@NonNull String requestId);
default void clearCache();
}
public interface ImageCallback {
@MainThread void onSuccess(@NonNull ImageLoadResult result);
@MainThread void onFailure(@NonNull ImageLoaderError error);
}iOS — ImageLoader
@objc public protocol ImageLoader: AnyObject {
@objc func loadImage(
from url: URL,
options: [String: Any]?,
completion: @escaping (UIImage?, Bool, Error?) -> Void
) -> String
@objc func cancel(for taskId: String)
@objc func clearMemory()
@objc func clearDisk()
}HarmonyOS — IImageLoader
export interface IImageLoader {
loadImage(
url: string,
options: ImageLoadOptions | null,
onComplete: (requestId: string, result: ImageLoadResult | null, error: ImageLoaderError | null) => void
): string;
cancel(requestId: string): void;
clearCache(): void;
}Platform differences: Callback signatures differ across platforms. Android uses an
ImageCallbackinterface (called on the main thread); iOS uses(UIImage?, Bool, Error?) -> Void; HarmonyOS uses(requestId, result?, error?)with image data asPixelData(aUint8Arraybyte array).
| Platform | Image field | Cache field | Format field |
|---|---|---|---|
| Android | drawable: Drawable |
isFromCache: boolean |
format: Format (BITMAP/GIF/SVG/LOTTIE) |
| iOS | image: UIImage |
isFromCache: Bool |
— |
| HarmonyOS | image: PixelData (contains bytes/width/height) |
isFromCache: boolean |
format: ImageFormat (JPEG/PNG/WEBP/GIF) |
Android
public enum Type {
INVALID_URL, NETWORK_ERROR, INVALID_DATA, DECOMPRESSION_FAILED,
CANCELLED, PATH_RESOURCE_ERROR
}
// Factory methods
ImageLoaderError.invalidUrl(String url)
ImageLoaderError.networkError(String url, Throwable cause)
ImageLoaderError.invalidData(String url)
ImageLoaderError.cancelled()
ImageLoaderError.pathResourceError(String url)
boolean isCancelled()iOS
public enum ImageLoaderError: Error, Equatable {
case invalidURL(String)
case networkError(Error)
case invalidData
case decompressionFailed
case cancelled
var isCancelled: Bool { get }
}HarmonyOS
export enum ImageLoaderErrorType {
INVALID_URL = 'invalidURL',
NETWORK_ERROR = 'networkError',
INVALID_DATA = 'invalidData',
DECOMPRESSION_FAILED = 'decompressionFailed',
CANCELLED = 'cancelled',
}
export interface ImageLoaderError {
type: ImageLoaderErrorType;
message?: string;
isCancelled: boolean;
}The following keys may be used in the options parameter (consistent across all platforms):
| Key | Constant value | Description |
|---|---|---|
ImageLoadOptionsKey.width |
"width" |
Target width (px) |
ImageLoadOptionsKey.height |
"height" |
Target height (px) |
ImageLoadOptionsKey.componentId |
"componentId" |
ID of the component making the request |
ImageLoadOptionsKey.surfaceId |
"surfaceId" |
ID of the Surface making the request |
| Scenario | Android | iOS | HarmonyOS |
|---|---|---|---|
| Theme registration failure | ThemeException (checked exception) |
AGenUIError (return value, result == false) |
boolean (returns false) |
| Creating SurfaceManager before engine initialization | IllegalStateException |
— | — |
Engine initialize() failure |
RuntimeException |
— | — |
Android
try {
AGenUI.getInstance().registerDefaultTheme(themeJson, designToken);
} catch (ThemeException e) {
// Theme JSON parsing failed
}
try {
SurfaceManager sm = new SurfaceManager(activity);
} catch (IllegalStateException e) {
// Engine not initialized — call AGenUI.getInstance().initialize(context) first
}iOS — AGenUIError
@objc public class AGenUIError: NSObject {
@objc public let result: Bool
@objc public let message: String
@objc public init(result: Bool, message: String)
}
let error = AGenUISDK.registerDefaultTheme(theme, designToken: token)
if !error.result {
print(error.message)
}HarmonyOS
// registerDefaultTheme returns boolean
const success = AGenUI.registerDefaultTheme(themeJson, designTokenJson);
if (!success) {
console.error('Theme registration failed');
}| Feature | Android | iOS | HarmonyOS |
|---|---|---|---|
| Global entry class | AGenUI (singleton) |
AGenUISDK (static methods) |
AGenUI (static methods) |
| Engine initialization | Manual — AGenUI.getInstance().initialize(context) |
Automatic | Automatic |
| SurfaceManager constructor | new SurfaceManager(activity) |
SurfaceManager() |
new SurfaceManager(context) |
| Surface root container | surface.getContainer() → ViewGroup |
surface.view → UIView |
AGenUIContainer({ surfaceId }) → ArkUI component |
| Listener interface | ISurfaceManagerListener (abstract methods, all must be implemented) |
SurfaceManagerListener (@objc optional, all methods optional) |
ISurfaceManagerListener (all properties optional) |
onDeleteSurface parameter |
Surface surface |
Surface surface |
Surface surface |
| Function interface name | IFunction |
Function (Swift protocol) |
IFunctionCall |
| Function.execute signature | execute(FunctionCallContext, String) |
execute(context:params:) |
execute(context, paramsJson) |
| FunctionResult factory | createSuccess(Object) / createError(String) / createPending(String) |
success(value: String) / failure(value: String) |
createSuccess(object) / createError(string) |
| Image loader interface name | ImageLoader |
ImageLoader (@objc protocol) |
IImageLoader |
| Image callback | ImageCallback interface (main-thread callback) |
(UIImage?, Bool, Error?) -> Void |
(requestId, result?, error?) -> void |
| Image data type | Drawable |
UIImage |
PixelData (Uint8Array byte array) |
| Resource release | surfaceManager.destroy() |
Automatic on deinit |
surfaceManager.destroy() |
| Error handling | ThemeException / IllegalStateException |
AGenUIError (return value) |
boolean return value |
Q1: How do I get the native container for a Surface?
- Android: Call
surface.getContainer()in theonCreateSurfacecallback. It returns aFrameLayout(MATCH_PARENT × WRAP_CONTENT) that you canaddViewdirectly to your layout. - iOS: Use
surface.viewin theonCreateSurfacecallback. CalladdSubviewon the target view and set layout constraints. - HarmonyOS: Save
surface.surfaceIdin theonCreateSurfacecallback, then render withAGenUIContainer({ surfaceId: this.surfaceId })inbuild().
Q2: How do I make a Surface height auto-size to its content?
- Android: Set the
heightofsurface.getContainer()toWRAP_CONTENT(this is the default):parentLayout.addView(surface.getContainer(), new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT ));
- iOS: Do not set a fixed height constraint — the Surface will size to fit its content automatically.
- HarmonyOS:
AGenUIContainerdefaults to wrap-content height; no extra handling is needed.
Q3: How do I get a Surface's unique ID in onDeleteSurface?
All three platforms pass a Surface object to onDeleteSurface. Call surface.getSurfaceId() on Android or access surface.surfaceId on iOS / HarmonyOS to get the ID. You can also call surface.getContainer() (Android) or surface.view (iOS) directly to remove the view.
Q4: How do I switch day/night mode?
Make sure a theme configuration is registered first. After switching, already-rendered Surfaces refresh their colors automatically.
// Android
AGenUI.getInstance().registerDefaultTheme(themeJson, designTokenJson);
AGenUI.getInstance().setDayNightMode("dark");// iOS
AGenUISDK.registerDefaultTheme(themeJson, designToken: designTokenJson)
AGenUISDK.setDayNightMode("dark")// HarmonyOS
AGenUI.registerDefaultTheme(themeJson, designTokenJson);
AGenUI.setDayNightMode('dark');