Skip to main content

Device & Resolution

Device & Resolution

Hosanna exposes a device abstraction that reports UI resolution and quality. Resolution info drives resource selection and can influence image URI resolution.

Platform-Neutral Device Facade

IHosannaDevice provides cross-platform access to four key areas:

export interface IHosannaDevice {
configure(): unknown;
onSystemDeviceInfoEvent(event: ISystemEvent<JsonData>): unknown;
/** Information about the device. */
deviceInfo: ISGRODeviceInfo;
/** The device registry for storing key-value pairs. */
deviceRegistry: IDeviceRegistry;
/** Information about the application running on the device. */
appInfo: ISGROAppInfo;
resolutionInfo: IResolutionInfo
}
  • deviceRegistry: Platform-neutral key-value storage for your app. Use it for tokens, flags, and lightweight settings.
  • deviceInfo: Low-level device information (UI resolution, model, etc.).
  • appInfo: Metadata about the running app/build.
  • resolutionInfo: Normalized resolution details used by Hosanna (see below).

IResolutionInfo

export interface IResolutionInfo {
suffix: string;
scale: number;
width: number;
height: number;
}
  • suffix: Resolution suffix (e.g., fhd, hd, sd).
  • scale: Pixel scale relative to FHD (1.0 for FHD; 2/3 for HD; 1/3 for SD).
  • width / height: UI resolution in pixels.

BaseHosannaDevice

BaseHosannaDevice resolves UI resolution and an overall device quality. You can override quality or supply a forced quality via the debug flag device.forcedDeviceQuality, which can be a value of DeviceQuality.Low, DeviceQuality.Medium, or DeviceQuality.High.

export class BaseHosannaDevice implements IHosannaDevice {
appInfo: ISGROAppInfo = CreateObject('roAppInfo');
deviceInfo: ISGRODeviceInfo = CreateObject('roDeviceInfo');
deviceQuality: DeviceQuality = DeviceQuality.High; // Default value, will be overridden in subclasses
@injectFlag('device.forcedDeviceQuality') forcedDeviceQuality?: DeviceQuality;

resolutionInfo: IResolutionInfo = {
suffix: 'fhd',
scale: 1.0,
width: 1920,
height: 1080,
};

@inject() deviceRegistry!: DeviceRegistry;

configure(): void {
this.resolutionInfo = this.getUIResolutionInfo();
this.deviceQuality = this.getDeviceQuality();
}
}

Resolution is derived from Roku roDeviceInfo.GetUIResolution() and adjusted for quality:

private getUIResolutionInfo(): IResolutionInfo {
const quality = this.getDeviceQuality();
const info = this.deviceInfo.GetUIResolution();
const realSuffix = info.name.toLowerCase();
const scale = realSuffix=== 'fhd' ? 1.0 : realSuffix=== 'hd' ? 2 / 3 : 1 / 3;
const suffix = quality === DeviceQuality.Low ? 'hd' : realSuffix;
return { suffix, scale, width: info.width, height: info.height };
}
Tip: Force Quality in Dev

Inject device.forcedDeviceQuality to quickly simulate low-end devices and test scaling.

@res Auto-Substitution (Roku)

On Roku, packaged resource URIs with @res auto-resolve based on manifest:

uri_resolution_autosub=@res,-sd,-hd,-fhd

Use pkg:/path/to/image@res.png and include the matching -sd, -hd, -fhd files in your package.

Remote URLs

Remote HTTP(S) URLs do not go through Roku auto-substitution. Use resolveImageUri(url) to replace @res with a concrete suffix and to normalize pkg:/ URIs on web:

export function resolveImageUri(uri: string): string {
const normalizedUri = normalizePkgUri(uri);
return normalizedUri?.replace('@res', '-fhd') ?? '';
}