@nativescript/core
Version:
A JavaScript library providing an easy to use api for interacting with iOS and Android platform APIs.
175 lines • 6.21 kB
JavaScript
import { CoreTypes } from '../core-types';
import { CALLBACKS } from '../ui/frame/frame-constants';
import { NativeWindow } from './native-window-common';
/**
* Android implementation of NativeWindow.
* Wraps an AppCompatActivity.
*/
export class AndroidNativeWindow extends NativeWindow {
constructor(activity, id, isPrimary = false, role = 'application') {
super(id, isPrimary, role);
this._activity = new WeakRef(activity);
}
/**
* @internal – bind a recreated activity to this window session after a detach.
*/
_reattach(activity) {
this._activity = new WeakRef(activity);
this._setState('attached');
}
/**
* @internal – observe the activity's own configuration.
*
* Registered on the activity rather than the application context: in multi-window
* and multi-display setups each activity gets its own configuration, and only these
* callbacks report the one this window actually renders with.
*/
_registerConfigurationCallbacks() {
const activity = this.activity;
if (!activity || this._componentCallbacks) {
return;
}
const callbacks = new android.content.ComponentCallbacks2({
onLowMemory() {
// Handled application-wide.
},
onTrimMemory(level) {
// Handled application-wide.
},
onConfigurationChanged: (newConfiguration) => {
this._setOrientation(this._getOrientationValue(newConfiguration));
this._setSystemAppearance(this._getSystemAppearanceValue(newConfiguration));
this._setLayoutDirection(this._getLayoutDirectionValue(newConfiguration));
},
});
activity.registerComponentCallbacks(callbacks);
this._componentCallbacks = callbacks;
this._componentCallbacksActivity = new WeakRef(activity);
}
/**
* @internal – drop the configuration callbacks, so a recreated activity does not
* leave the previous one registered.
*/
_unregisterConfigurationCallbacks() {
const callbacks = this._componentCallbacks;
if (!callbacks) {
return;
}
this._componentCallbacks = null;
this._componentCallbacksActivity?.deref()?.unregisterComponentCallbacks(callbacks);
this._componentCallbacksActivity = null;
}
_detach() {
this._unregisterConfigurationCallbacks();
super._detach();
}
/**
* The wrapped Android Activity (may be GC'd).
*/
get activity() {
return this._activity?.deref();
}
get android() {
const activity = this.activity;
if (!activity) {
return undefined;
}
return { activity };
}
/**
* Platform-specific: apply the view as root content of this Activity.
*/
_setNativeContent(view) {
const activity = this.activity;
if (!activity) {
throw new Error('NativeWindow: Activity is no longer available.');
}
const callbacks = activity[CALLBACKS];
if (!callbacks) {
throw new Error('NativeWindow: Cannot find activity callbacks.');
}
callbacks.resetActivityContent(activity, view);
}
/**
* Close this window by finishing the activity.
*/
close() {
if (this.isPrimary) {
console.log('NativeWindow: Cannot close the primary window.');
return;
}
const activity = this.activity;
if (activity) {
activity.finish();
}
}
// --- Platform getters ---
_getOrientation() {
const activity = this.activity;
if (!activity) {
return 'unknown';
}
const configuration = activity.getResources().getConfiguration();
return this._getOrientationValue(configuration);
}
_getSystemAppearance() {
const activity = this.activity;
if (!activity) {
return null;
}
const configuration = activity.getResources().getConfiguration();
return this._getSystemAppearanceValue(configuration);
}
_getLayoutDirection() {
const activity = this.activity;
if (!activity) {
return null;
}
const configuration = activity.getResources().getConfiguration();
return this._getLayoutDirectionValue(configuration);
}
// --- Value converters ---
_getOrientationValue(configuration) {
switch (configuration.orientation) {
case android.content.res.Configuration.ORIENTATION_LANDSCAPE:
return 'landscape';
case android.content.res.Configuration.ORIENTATION_PORTRAIT:
return 'portrait';
default:
return 'unknown';
}
}
_getSystemAppearanceValue(configuration) {
const mode = configuration.uiMode & android.content.res.Configuration.UI_MODE_NIGHT_MASK;
switch (mode) {
case android.content.res.Configuration.UI_MODE_NIGHT_YES:
return 'dark';
case android.content.res.Configuration.UI_MODE_NIGHT_NO:
case android.content.res.Configuration.UI_MODE_NIGHT_UNDEFINED:
default:
return 'light';
}
}
_getLayoutDirectionValue(configuration) {
switch (configuration.getLayoutDirection()) {
case android.view.View.LAYOUT_DIRECTION_RTL:
return CoreTypes.LayoutDirection.rtl;
case android.view.View.LAYOUT_DIRECTION_LTR:
default:
return CoreTypes.LayoutDirection.ltr;
}
}
_onDestroy() {
this._unregisterConfigurationCallbacks();
super._onDestroy();
this._activity = null;
}
/**
* Mints a window identity. Android has no stable activity id, so the value is kept
* in the activity saved state to survive recreation (rotation, theme change).
*/
static newWindowId() {
return `window-${java.util.UUID.randomUUID().toString()}`;
}
}
//# sourceMappingURL=native-window.android.js.map