diff --git a/packages/core/platforms/android/widgets-release.aar b/packages/core/platforms/android/widgets-release.aar index 6b7056f32c..97cbdd4b09 100644 Binary files a/packages/core/platforms/android/widgets-release.aar and b/packages/core/platforms/android/widgets-release.aar differ diff --git a/packages/core/utils/native-helper-for-android.ts b/packages/core/utils/native-helper-for-android.ts index 3de9ecc84c..2a873b8f16 100644 --- a/packages/core/utils/native-helper-for-android.ts +++ b/packages/core/utils/native-helper-for-android.ts @@ -450,3 +450,271 @@ export function getIgnoreEdgeToEdgeOnOlderDevices(): boolean { export function setIgnoreEdgeToEdgeOnOlderDevices(value: boolean) { org.nativescript.widgets.Utils.ignoreEdgeToEdgeOnOlderDevices = value; } + +class WidgetManager { + private _manager: org.nativescript.widgets.AppWidgetManager; + + get native() { + return this._manager; + } + + static fromNative(manager: org.nativescript.widgets.AppWidgetManager) { + const ret = new WidgetManager(); + ret._manager = manager; + return ret; + } +} + +class AndroidWidgetManager { + private _widgetManager: android.appwidget.AppWidgetManager; + + constructor(nativeManager: android.appwidget.AppWidgetManager) { + this._widgetManager = nativeManager; + } + + get native() { + return this._widgetManager; + } + + static fromNative(nativeManager: android.appwidget.AppWidgetManager) { + return new AndroidWidgetManager(nativeManager); + } +} + +interface IWidgetListener { + onEnabled?: (provider: string) => void; + onUpdate?: (event: { provider: string; appWidgetIds: number[]; manager: WidgetManager; widgetManager: AndroidWidgetManager }) => void; + onUpdateAsync?: (event: { provider: string; appWidgetIds: number[]; manager: WidgetManager; widgetManager: AndroidWidgetManager }) => void; + onDeleted?: (event: { provider: string; appWidgetIds: number[] }) => void; + onDisabled?: (provider: string) => void; +} + +export class AndroidRemoteViews { + private _remoteViews: android.widget.RemoteViews; + + constructor(remoteViews: android.widget.RemoteViews) { + this._remoteViews = remoteViews; + } + + get native() { + return this._remoteViews; + } +} + +export class RemoteViews { + protected _remoteViews: org.nativescript.widgets.RemoteViews; + + constructor(remoteViews: org.nativescript.widgets.RemoteViews) { + this._remoteViews = remoteViews; + } + + get native() { + return this._remoteViews; + } + + toAndroidRemoteViews(packageName?: string): AndroidRemoteViews { + return new AndroidRemoteViews(this._remoteViews.build(packageName ?? getApplicationContext().getPackageName())); + } +} + +export class AdapterViewFlipper extends RemoteViews { + constructor(id?: string) { + super(new org.nativescript.widgets.RemoteViews.AdapterViewFlipper(id ?? null)); + } +} + +export class Button extends RemoteViews { + constructor(id?: string) { + super(new org.nativescript.widgets.RemoteViews.Button(id ?? null)); + } +} + +export class Chronometer extends RemoteViews { + constructor(id?: string) { + super(new org.nativescript.widgets.RemoteViews.Chronometer(id ?? null)); + } +} + +export class FrameLayout extends RemoteViews { + constructor(id?: string) { + super(new org.nativescript.widgets.RemoteViews.FrameLayout(id ?? null)); + } + + get native() { + return this._remoteViews as org.nativescript.widgets.RemoteViews.FrameLayout; + } + + addView(view: RemoteViews) { + this.native.addView(view.native); + } + + removeView(view: RemoteViews) { + this.native.removeView(view.native); + } +} + +export class GridLayout extends RemoteViews { + constructor(id?: string) { + super(new org.nativescript.widgets.RemoteViews.GridLayout(id ?? null)); + } + + get native() { + return this._remoteViews as org.nativescript.widgets.RemoteViews.GridLayout; + } + + addView(view: RemoteViews) { + this.native.addView(view.native); + } + + removeView(view: RemoteViews) { + this.native.removeView(view.native); + } +} + +export class GridView extends RemoteViews { + constructor(id?: string) { + super(new org.nativescript.widgets.RemoteViews.GridView(id ?? null)); + } + + get native() { + return this._remoteViews as org.nativescript.widgets.RemoteViews.GridView; + } + + addView(view: RemoteViews) { + this.native.addView(view.native); + } + + removeView(view: RemoteViews) { + this.native.removeView(view.native); + } +} + +export class ImageButton extends RemoteViews { + constructor(id?: string) { + super(new org.nativescript.widgets.RemoteViews.ImageButton(id ?? null)); + } +} + +export class ImageView extends RemoteViews { + constructor(id?: string) { + super(new org.nativescript.widgets.RemoteViews.ImageView(id ?? null)); + } +} + +export class LinearLayout extends RemoteViews { + constructor(id?: string) { + super(new org.nativescript.widgets.RemoteViews.LinearLayout(id ?? null)); + } + + get native() { + return this._remoteViews as org.nativescript.widgets.RemoteViews.LinearLayout; + } + + addView(view: RemoteViews) { + this.native.addView(view.native); + } + + removeView(view: RemoteViews) { + this.native.removeView(view.native); + } +} + +export class ListView extends RemoteViews { + constructor(id?: string) { + super(new org.nativescript.widgets.RemoteViews.ListView(id ?? null)); + } +} + +export class ProgressBar extends RemoteViews { + constructor(id?: string) { + super(new org.nativescript.widgets.RemoteViews.ProgressBar(id ?? null)); + } +} + +export class RelativeLayout extends RemoteViews { + constructor(id?: string) { + super(new org.nativescript.widgets.RemoteViews.RelativeLayout(id ?? null)); + } + + get native() { + return this._remoteViews as org.nativescript.widgets.RemoteViews.RelativeLayout; + } + + addView(view: RemoteViews) { + this.native.addView(view.native); + } + + removeView(view: RemoteViews) { + this.native.removeView(view.native); + } +} + +export class StackView extends RemoteViews { + constructor(id?: string) { + super(new org.nativescript.widgets.RemoteViews.StackView(id ?? null)); + } + + get native() { + return this._remoteViews as org.nativescript.widgets.RemoteViews.StackView; + } + + addView(view: RemoteViews) { + this.native.addView(view.native); + } + + removeView(view: RemoteViews) { + this.native.removeView(view.native); + } +} + +export class TextView extends RemoteViews { + constructor(id?: string) { + super(new org.nativescript.widgets.RemoteViews.TextView(id ?? null)); + } +} + +export class TextClock extends RemoteViews { + constructor(id?: string) { + super(new org.nativescript.widgets.RemoteViews.TextClock(id ?? null)); + } +} + +export function registerWidgetListener(provider: string, listener: IWidgetListener) { + const opts = { + onEnabled(provider) { + if (listener.onEnabled) { + listener.onEnabled(provider); + } + }, + onUpdateAsync(context, provider, appWidgetIds, manager, widgetManager) { + if (listener.onUpdateAsync) { + listener.onUpdateAsync({ provider, appWidgetIds: dataDeserialize(appWidgetIds), manager: WidgetManager.fromNative(manager), widgetManager: AndroidWidgetManager.fromNative(widgetManager) }); + } + }, + onUpdate(context, provider, appWidgetIds, manager, widgetManager) { + if (listener.onUpdate) { + listener.onUpdate({ provider, appWidgetIds: dataDeserialize(appWidgetIds), manager: WidgetManager.fromNative(manager), widgetManager: AndroidWidgetManager.fromNative(widgetManager) }); + } + }, + onDeleted(provider, appWidgetIds) { + if (listener.onDeleted) { + listener.onDeleted({ provider, appWidgetIds: dataDeserialize(appWidgetIds) }); + } + }, + onDisabled(provider) { + if (listener.onDisabled) { + listener.onDisabled(provider); + } + }, + }; + + if (!listener.onUpdateAsync) { + delete opts.onUpdateAsync; + } + + org.nativescript.widgets.AppWidgetManager.INSTANCE.register(provider, new org.nativescript.widgets.AppWidgetManager.WidgetListener(opts)); +} + +export function unregisterWidgetListener(provider: string) { + org.nativescript.widgets.AppWidgetManager.INSTANCE.unregister(provider); +} diff --git a/packages/types-android/src/lib/android/org.nativescript.widgets.d.ts b/packages/types-android/src/lib/android/org.nativescript.widgets.d.ts index b05ab9f9f3..0f24e41c63 100644 --- a/packages/types-android/src/lib/android/org.nativescript.widgets.d.ts +++ b/packages/types-android/src/lib/android/org.nativescript.widgets.d.ts @@ -809,3 +809,733 @@ declare module org { } } } + + +declare module org { + export module nativescript { + export module widgets { + export class AppWidgetManager { + public static class: java.lang.Class; + public static INSTANCE: org.nativescript.widgets.AppWidgetManager; + public notifyEnabled$widgets_release(provider: string): void; + public notifyDeleted$widgets_release(provider: string, appWidgetIds: androidNative.Array): void; + public notifyOptionsChanged$widgets_release(context: globalAndroid.content.Context, provider: string, appWidgetId: number, newOptions: globalAndroid.os.Bundle, manager: org.nativescript.widgets.RemoteViewsManager, widgetManager: globalAndroid.appwidget.AppWidgetManager): void; + public notifyUpdateAsync$widgets_release(context: globalAndroid.content.Context, provider: string, appWidgetIds: androidNative.Array, manager: org.nativescript.widgets.RemoteViewsManager, widgetManager: globalAndroid.appwidget.AppWidgetManager): void; + public getManager(provider: string): org.nativescript.widgets.RemoteViewsManager; + public register(providerClass: string, listener: org.nativescript.widgets.AppWidgetManager.WidgetListener): void; + public unregister(providerClass: string): void; + public notifyUpdate$widgets_release(context: globalAndroid.content.Context, provider: string, appWidgetIds: androidNative.Array, manager: org.nativescript.widgets.RemoteViewsManager, widgetManager: globalAndroid.appwidget.AppWidgetManager): void; + public notifyDisabled$widgets_release(provider: string): void; + } + export module AppWidgetManager { + export class WidgetListener { + public static class: java.lang.Class; + /** + * Constructs a new instance of the org.nativescript.widgets.AppWidgetManager$WidgetListener interface with the provided implementation. An empty constructor exists calling super() when extending the interface class. + */ + public constructor(implementation: { + onEnabled?(provider: string): void; + onUpdate?(context: globalAndroid.content.Context, provider: string, appWidgetIds: androidNative.Array, manager: org.nativescript.widgets.RemoteViewsManager, widgetManager: globalAndroid.appwidget.AppWidgetManager): void; + onUpdateAsync?(context: globalAndroid.content.Context, provider: string, appWidgetIds: androidNative.Array, manager: org.nativescript.widgets.RemoteViewsManager, widgetManager: globalAndroid.appwidget.AppWidgetManager): void; + onDisabled?(provider: string): void; + onDeleted?(provider: string, appWidgetIds: androidNative.Array): void; + onOptionsChanged?(context: globalAndroid.content.Context, provider: string, appWidgetId: number, newOptions: globalAndroid.os.Bundle, manager: org.nativescript.widgets.RemoteViewsManager, widgetManager: globalAndroid.appwidget.AppWidgetManager): void; + }); + public constructor(); + public onEnabled(provider: string): void; + public onUpdate(context: globalAndroid.content.Context, provider: string, appWidgetIds: androidNative.Array, manager: org.nativescript.widgets.RemoteViewsManager, widgetManager: globalAndroid.appwidget.AppWidgetManager): void; + public onDisabled(provider: string): void; + public onDeleted(provider: string, appWidgetIds: androidNative.Array): void; + public onUpdateAsync(context: globalAndroid.content.Context, provider: string, appWidgetIds: androidNative.Array, manager: org.nativescript.widgets.RemoteViewsManager, widgetManager: globalAndroid.appwidget.AppWidgetManager): void; + public onOptionsChanged(context: globalAndroid.content.Context, provider: string, appWidgetId: number, newOptions: globalAndroid.os.Bundle, manager: org.nativescript.widgets.RemoteViewsManager, widgetManager: globalAndroid.appwidget.AppWidgetManager): void; + } + export module WidgetListener { + export class DefaultImpls { + public static class: java.lang.Class; + /** @deprecated */ + public static onOptionsChanged($this: org.nativescript.widgets.AppWidgetManager.WidgetListener, context: globalAndroid.content.Context, provider: string, appWidgetId: number, newOptions: globalAndroid.os.Bundle, manager: org.nativescript.widgets.RemoteViewsManager, widgetManager: globalAndroid.appwidget.AppWidgetManager): void; + /** @deprecated */ + public static onUpdateAsync($this: org.nativescript.widgets.AppWidgetManager.WidgetListener, context: globalAndroid.content.Context, provider: string, appWidgetIds: androidNative.Array, manager: org.nativescript.widgets.RemoteViewsManager, widgetManager: globalAndroid.appwidget.AppWidgetManager): void; + /** @deprecated */ + public static onEnabled($this: org.nativescript.widgets.AppWidgetManager.WidgetListener, provider: string): void; + /** @deprecated */ + public static onDisabled($this: org.nativescript.widgets.AppWidgetManager.WidgetListener, provider: string): void; + /** @deprecated */ + public static onUpdate($this: org.nativescript.widgets.AppWidgetManager.WidgetListener, context: globalAndroid.content.Context, provider: string, appWidgetIds: androidNative.Array, manager: org.nativescript.widgets.RemoteViewsManager, widgetManager: globalAndroid.appwidget.AppWidgetManager): void; + /** @deprecated */ + public static onDeleted($this: org.nativescript.widgets.AppWidgetManager.WidgetListener, provider: string, appWidgetIds: androidNative.Array): void; + } + } + } + } + } +} + +declare module org { + export module nativescript { + export module widgets { + export class AppWidgetProvider { + public static class: java.lang.Class; + public onDisabled(context: globalAndroid.content.Context): void; + public onEnabled($this$iv: globalAndroid.content.Context): void; + public onUpdate(request$iv: globalAndroid.content.Context, this_$iv: globalAndroid.appwidget.AppWidgetManager, context$iv: androidNative.Array): void; + public onDeleted(it: globalAndroid.content.Context, this_: androidNative.Array): void; + public onAppWidgetOptionsChanged(manager: globalAndroid.content.Context, it: globalAndroid.appwidget.AppWidgetManager, ctx: number, this_: globalAndroid.os.Bundle): void; + public constructor(); + } + export module AppWidgetProvider { + export class WidgetWorker extends org.nativescript.widgets.AppWidgetWorker { + public static class: java.lang.Class; + public constructor(context: globalAndroid.content.Context, params: androidx.work.WorkerParameters); + public doWork(): androidx.work.ListenableWorker.Result; + } + } + } + } +} + +declare module org { + export module nativescript { + export module widgets { + export abstract class AppWidgetWorker { + public static class: java.lang.Class; + public static KEY_WIDGET_IDS: string = "widget_ids"; + public static KEY_PROVIDER: string = "provider"; + public getWidgetIds(): androidNative.Array; + public static enqueue(context: globalAndroid.content.Context, workerClass: java.lang.Class, provider: string, widgetIds: androidNative.Array): void; + public updateWidget(this_: number, widgetId: globalAndroid.widget.RemoteViews): void; + public static enqueuePeriodic(context: globalAndroid.content.Context, workerClass: java.lang.Class, provider: string, widgetIds: androidNative.Array, repeatIntervalMinutes: number): void; + public updateWidgets(mgr: globalAndroid.widget.RemoteViews): void; + public getProvider(): string; + public static cancelPeriodic(context: globalAndroid.content.Context, provider: string): void; + public static buildData(provider: string, widgetIds: androidNative.Array): androidx.work.Data; + public static enqueuePeriodic(context: globalAndroid.content.Context, workerClass: java.lang.Class, provider: string, widgetIds: androidNative.Array): void; + public static cancelPeriodic(context: globalAndroid.content.Context, provider: string, uniqueWorkName: string): void; + public constructor(context: globalAndroid.content.Context, params: androidx.work.WorkerParameters); + public static enqueuePeriodic(context: globalAndroid.content.Context, workerClass: java.lang.Class, provider: string, widgetIds: androidNative.Array, repeatIntervalMinutes: number, uniqueWorkName: string): void; + public static isScheduled(context: globalAndroid.content.Context, provider: string): boolean; + } + export module AppWidgetWorker { + export class Companion { + public static class: java.lang.Class; + public enqueuePeriodic(this_: globalAndroid.content.Context, context: java.lang.Class, workerClass: string, provider: androidNative.Array, widgetIds: number, repeatIntervalMinutes: string): void; + public buildData(provider: string, widgetIds: androidNative.Array): androidx.work.Data; + public isScheduled(it: globalAndroid.content.Context, element$iv: string): boolean; + public enqueuePeriodic(context: globalAndroid.content.Context, workerClass: java.lang.Class, provider: string, widgetIds: androidNative.Array, repeatIntervalMinutes: number): void; + public cancelPeriodic(context: globalAndroid.content.Context, provider: string): void; + public cancelPeriodic(context: globalAndroid.content.Context, provider: string, uniqueWorkName: string): void; + public enqueue(now: globalAndroid.content.Context, last: java.lang.Class, request: string, this_: androidNative.Array): void; + public enqueuePeriodic(context: globalAndroid.content.Context, workerClass: java.lang.Class, provider: string, widgetIds: androidNative.Array): void; + } + } + } + } +} + +declare module org { + export module nativescript { + export module widgets { + export class RemoteViews { + public static class: java.lang.Class; + public getId(): string; + public setShort(method: string, value: number): org.nativescript.widgets.RemoteViews; + public setBoolean(method: string, value: boolean): org.nativescript.widgets.RemoteViews; + public setLong(method: string, value: number): org.nativescript.widgets.RemoteViews; + public setInt(method: string, value: number): org.nativescript.widgets.RemoteViews; + public setOnClickPendingIntent(intent: globalAndroid.app.PendingIntent): org.nativescript.widgets.RemoteViews; + public constructor(layout: org.nativescript.widgets.RemoteViews.Layout, id: string); + public getCommands(): java.util.Map; + public setBackgroundColor(value: number): org.nativescript.widgets.RemoteViews; + public setString(method: string, value: string): org.nativescript.widgets.RemoteViews; + public setFloat(method: string, value: number): org.nativescript.widgets.RemoteViews; + public setByte(method: string, value: number): org.nativescript.widgets.RemoteViews; + public setSize(width: number, widthUnit: number, height: number, heightUnit: number): org.nativescript.widgets.RemoteViews; + public findViewById(id: string): org.nativescript.widgets.RemoteViews; + public build(packageName: string): globalAndroid.widget.RemoteViews; + public getLayout(): org.nativescript.widgets.RemoteViews.Layout; + public setHeight(value: number, unit: number): org.nativescript.widgets.RemoteViews; + public resolveRemoteResources(): void; + public toLayoutId(): number; + public setVisibility(visibility: number): org.nativescript.widgets.RemoteViews; + public setWidth(value: number, unit: number): org.nativescript.widgets.RemoteViews; + } + export module RemoteViews { + export class AdapterViewFlipper extends org.nativescript.widgets.RemoteViews { + public static class: java.lang.Class; + public constructor(); + public constructor(layout: org.nativescript.widgets.RemoteViews.Layout, id: string); + public constructor(id: string); + } + export class Button extends org.nativescript.widgets.RemoteViews implements org.nativescript.widgets.RemoteViews.TextLike { + public static class: java.lang.Class; + public getCommands(): java.util.Map; + public constructor(); + public setText(value: string): org.nativescript.widgets.RemoteViews.TextLike; + public constructor(layout: org.nativescript.widgets.RemoteViews.Layout, id: string); + public constructor(id: string); + public setTextColor(value: number): org.nativescript.widgets.RemoteViews.TextLike; + } + export class Chronometer extends org.nativescript.widgets.RemoteViews { + public static class: java.lang.Class; + public constructor(); + public constructor(layout: org.nativescript.widgets.RemoteViews.Layout, id: string); + public constructor(id: string); + } + export abstract class Command { + public static class: java.lang.Class; + public applyToWithContext(rv: globalAndroid.widget.RemoteViews, targetId: number, context: globalAndroid.content.Context): void; + public applyTo(param0: globalAndroid.widget.RemoteViews, param1: number): void; + } + export module Command { + export class SetBackgroundColor extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public equals(other: any): boolean; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public hashCode(): number; + public constructor(value: number); + public component1(): number; + public copy(value: number): org.nativescript.widgets.RemoteViews.Command.SetBackgroundColor; + public toString(): string; + public getValue(): number; + } + export class SetBoolean extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public equals(other: any): boolean; + public copy(method: string, value: boolean): org.nativescript.widgets.RemoteViews.Command.SetBoolean; + public component2(): boolean; + public constructor(method: string, value: boolean); + public getValue(): boolean; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public component1(): string; + public hashCode(): number; + public getMethod(): string; + public toString(): string; + } + export class SetByte extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public component2(): number; + public equals(other: any): boolean; + public copy(method: string, value: number): org.nativescript.widgets.RemoteViews.Command.SetByte; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public component1(): string; + public hashCode(): number; + public getMethod(): string; + public constructor(method: string, value: number); + public toString(): string; + public getValue(): number; + } + export class SetFloat extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public component2(): number; + public copy(method: string, value: number): org.nativescript.widgets.RemoteViews.Command.SetFloat; + public equals(other: any): boolean; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public component1(): string; + public hashCode(): number; + public getMethod(): string; + public constructor(method: string, value: number); + public toString(): string; + public getValue(): number; + } + export class SetHeight extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public constructor(value: number, unit: number); + public component2(): number; + public equals(other: any): boolean; + public copy(value: number, unit: number): org.nativescript.widgets.RemoteViews.Command.SetHeight; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public getUnit(): number; + public hashCode(): number; + public component1(): number; + public toString(): string; + public getValue(): number; + } + export class SetHeightDimen extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public component3(): string; + public equals(other: any): boolean; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public hashCode(): number; + public toString(): string; + public constructor(value: number, resource: string, packageName: string); + public getPackageName(): string; + public component2(): string; + public copy(value: number, resource: string, packageName: string): org.nativescript.widgets.RemoteViews.Command.SetHeightDimen; + public applyToWithContext(this_: globalAndroid.widget.RemoteViews, rv: number, targetId: globalAndroid.content.Context): void; + public component1(): number; + public getResource(): string; + public getValue(): number; + } + export class SetImageBitmap extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public constructor(value: globalAndroid.graphics.Bitmap); + public equals(other: any): boolean; + public getValue(): globalAndroid.graphics.Bitmap; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public copy(value: globalAndroid.graphics.Bitmap): org.nativescript.widgets.RemoteViews.Command.SetImageBitmap; + public hashCode(): number; + public component1(): globalAndroid.graphics.Bitmap; + public toString(): string; + } + export class SetImageResource extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public equals(other: any): boolean; + public constructor(resId: number); + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public hashCode(): number; + public getResId(): number; + public component1(): number; + public copy(resId: number): org.nativescript.widgets.RemoteViews.Command.SetImageResource; + public toString(): string; + } + export class SetImageURI extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public copy(value: globalAndroid.net.Uri): org.nativescript.widgets.RemoteViews.Command.SetImageURI; + public equals(other: any): boolean; + public constructor(value: globalAndroid.net.Uri); + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public hashCode(): number; + public getValue(): globalAndroid.net.Uri; + public component1(): globalAndroid.net.Uri; + public toString(): string; + } + export class SetImageUrl extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public equals(other: any): boolean; + public copy(url: string): org.nativescript.widgets.RemoteViews.Command.SetImageUrl; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public resolve(): org.nativescript.widgets.RemoteViews.Command.SetImageBitmap; + public component1(): string; + public hashCode(): number; + public constructor(url: string); + public getUrl(): string; + public toString(): string; + } + export class SetInt extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public component2(): number; + public copy(method: string, value: number): org.nativescript.widgets.RemoteViews.Command.SetInt; + public equals(other: any): boolean; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public component1(): string; + public hashCode(): number; + public getMethod(): string; + public constructor(method: string, value: number); + public toString(): string; + public getValue(): number; + } + export class SetLong extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public component2(): number; + public equals(other: any): boolean; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public component1(): string; + public hashCode(): number; + public getMethod(): string; + public copy(method: string, value: number): org.nativescript.widgets.RemoteViews.Command.SetLong; + public constructor(method: string, value: number); + public toString(): string; + public getValue(): number; + } + export class SetOnClickPendingIntent extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public equals(other: any): boolean; + public applyToWithContext(rv: globalAndroid.widget.RemoteViews, targetId: number, context: globalAndroid.content.Context): void; + public constructor(intent: globalAndroid.app.PendingIntent); + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public hashCode(): number; + public getIntent(): globalAndroid.app.PendingIntent; + public copy(intent: globalAndroid.app.PendingIntent): org.nativescript.widgets.RemoteViews.Command.SetOnClickPendingIntent; + public toString(): string; + public component1(): globalAndroid.app.PendingIntent; + } + export class SetShort extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public component2(): number; + public equals(other: any): boolean; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public component1(): string; + public copy(method: string, value: number): org.nativescript.widgets.RemoteViews.Command.SetShort; + public hashCode(): number; + public getMethod(): string; + public constructor(method: string, value: number); + public toString(): string; + public getValue(): number; + } + export class SetSize extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public getWidthUnit(): number; + public equals(other: any): boolean; + public getHeightUnit(): number; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public hashCode(): number; + public copy(width: number, widthUnit: number, height: number, heightUnit: number): org.nativescript.widgets.RemoteViews.Command.SetSize; + public getHeight(): number; + public component4(): number; + public toString(): string; + public component2(): number; + public constructor(width: number, widthUnit: number, height: number, heightUnit: number); + public getWidth(): number; + public component1(): number; + public component3(): number; + } + export class SetSizeDimen extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public component3(): string; + public equals(other: any): boolean; + public component5(): string; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public hashCode(): number; + public copy(width: number, widthResource: string, widthPackageName: string, height: number, heightResource: string, heightPackageName: string): org.nativescript.widgets.RemoteViews.Command.SetSizeDimen; + public getHeight(): number; + public applyToWithContext(heightRes: globalAndroid.widget.RemoteViews, this_: number, rv: globalAndroid.content.Context): void; + public getWidthResource(): string; + public component4(): number; + public toString(): string; + public getHeightResource(): string; + public constructor(width: number, widthResource: string, widthPackageName: string, height: number, heightResource: string, heightPackageName: string); + public getWidth(): number; + public component2(): string; + public getWidthPackageName(): string; + public component6(): string; + public getHeightPackageName(): string; + public component1(): number; + } + export class SetString extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public equals(other: any): boolean; + public constructor(method: string, value: string); + public component2(): string; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public component1(): string; + public hashCode(): number; + public getMethod(): string; + public copy(method: string, value: string): org.nativescript.widgets.RemoteViews.Command.SetString; + public getValue(): string; + public toString(): string; + } + export class SetText extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public equals(other: any): boolean; + public copy(value: string): org.nativescript.widgets.RemoteViews.Command.SetText; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public component1(): string; + public hashCode(): number; + public constructor(value: string); + public getValue(): string; + public toString(): string; + } + export class SetTextColor extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public copy(value: number): org.nativescript.widgets.RemoteViews.Command.SetTextColor; + public equals(other: any): boolean; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public hashCode(): number; + public constructor(value: number); + public component1(): number; + public toString(): string; + public getValue(): number; + } + export class SetVisibility extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public equals(other: any): boolean; + public getVisibility(): number; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public hashCode(): number; + public constructor(visibility: number); + public component1(): number; + public copy(visibility: number): org.nativescript.widgets.RemoteViews.Command.SetVisibility; + public toString(): string; + } + export class SetWidth extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public constructor(value: number, unit: number); + public component2(): number; + public equals(other: any): boolean; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public getUnit(): number; + public copy(value: number, unit: number): org.nativescript.widgets.RemoteViews.Command.SetWidth; + public hashCode(): number; + public component1(): number; + public toString(): string; + public getValue(): number; + } + export class SetWidthDimen extends org.nativescript.widgets.RemoteViews.Command { + public static class: java.lang.Class; + public component3(): string; + public equals(other: any): boolean; + public applyTo(rv: globalAndroid.widget.RemoteViews, targetId: number): void; + public hashCode(): number; + public copy(value: number, resource: string, packageName: string): org.nativescript.widgets.RemoteViews.Command.SetWidthDimen; + public toString(): string; + public constructor(value: number, resource: string, packageName: string); + public getPackageName(): string; + public component2(): string; + public applyToWithContext(this_: globalAndroid.widget.RemoteViews, rv: number, targetId: globalAndroid.content.Context): void; + public component1(): number; + public getResource(): string; + public getValue(): number; + } + } + export class Companion { + public static class: java.lang.Class; + public generateId(): string; + } + export class FrameLayout extends org.nativescript.widgets.RemoteViews implements org.nativescript.widgets.RemoteViews.ViewGroupLike { + public static class: java.lang.Class; + public addView(this_: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public addView(child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public removeView(child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public constructor(); + public constructor(layout: org.nativescript.widgets.RemoteViews.Layout, id: string); + public removeView(it: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public constructor(id: string); + } + export class GridLayout extends org.nativescript.widgets.RemoteViews implements org.nativescript.widgets.RemoteViews.ViewGroupLike { + public static class: java.lang.Class; + public addView(this_: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public addView(child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public removeView(child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public constructor(); + public constructor(layout: org.nativescript.widgets.RemoteViews.Layout, id: string); + public removeView(it: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public constructor(id: string); + } + export class GridView extends org.nativescript.widgets.RemoteViews implements org.nativescript.widgets.RemoteViews.ViewGroupLike { + public static class: java.lang.Class; + public addView(this_: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public addView(child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public removeView(child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public constructor(); + public constructor(layout: org.nativescript.widgets.RemoteViews.Layout, id: string); + public removeView(it: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public constructor(id: string); + } + export class ImageButton extends org.nativescript.widgets.RemoteViews implements org.nativescript.widgets.RemoteViews.ImageLike { + public static class: java.lang.Class; + public getCommands(): java.util.Map; + public constructor(); + public constructor(layout: org.nativescript.widgets.RemoteViews.Layout, id: string); + public setImageUrl(url: string): org.nativescript.widgets.RemoteViews.ImageLike; + public setImageResource(value: number): org.nativescript.widgets.RemoteViews.ImageLike; + public constructor(id: string); + public setImageURI(value: globalAndroid.net.Uri): org.nativescript.widgets.RemoteViews.ImageLike; + public setImageBitmap(value: globalAndroid.graphics.Bitmap): org.nativescript.widgets.RemoteViews.ImageLike; + } + export class ImageLike { + public static class: java.lang.Class; + /** + * Constructs a new instance of the org.nativescript.widgets.RemoteViews$ImageLike interface with the provided implementation. An empty constructor exists calling super() when extending the interface class. + */ + public constructor(implementation: { + getCommands(): java.util.Map; + setImageResource(value: number): org.nativescript.widgets.RemoteViews.ImageLike; + setImageURI(value: globalAndroid.net.Uri): org.nativescript.widgets.RemoteViews.ImageLike; + setImageBitmap(value: globalAndroid.graphics.Bitmap): org.nativescript.widgets.RemoteViews.ImageLike; + setImageUrl(url: string): org.nativescript.widgets.RemoteViews.ImageLike; + access$setImageResource$jd($this: org.nativescript.widgets.RemoteViews.ImageLike, value: number): org.nativescript.widgets.RemoteViews.ImageLike; + access$setImageURI$jd($this: org.nativescript.widgets.RemoteViews.ImageLike, value: globalAndroid.net.Uri): org.nativescript.widgets.RemoteViews.ImageLike; + access$setImageBitmap$jd($this: org.nativescript.widgets.RemoteViews.ImageLike, value: globalAndroid.graphics.Bitmap): org.nativescript.widgets.RemoteViews.ImageLike; + access$setImageUrl$jd($this: org.nativescript.widgets.RemoteViews.ImageLike, url: string): org.nativescript.widgets.RemoteViews.ImageLike; + }); + public constructor(); + public getCommands(): java.util.Map; + public setImageUrl(url: string): org.nativescript.widgets.RemoteViews.ImageLike; + public setImageResource(value: number): org.nativescript.widgets.RemoteViews.ImageLike; + public setImageURI(value: globalAndroid.net.Uri): org.nativescript.widgets.RemoteViews.ImageLike; + public setImageBitmap(value: globalAndroid.graphics.Bitmap): org.nativescript.widgets.RemoteViews.ImageLike; + } + export module ImageLike { + export class DefaultImpls { + public static class: java.lang.Class; + /** @deprecated */ + public static setImageBitmap($this: org.nativescript.widgets.RemoteViews.ImageLike, value: globalAndroid.graphics.Bitmap): org.nativescript.widgets.RemoteViews.ImageLike; + /** @deprecated */ + public static setImageUrl($this: org.nativescript.widgets.RemoteViews.ImageLike, url: string): org.nativescript.widgets.RemoteViews.ImageLike; + /** @deprecated */ + public static setImageResource($this: org.nativescript.widgets.RemoteViews.ImageLike, value: number): org.nativescript.widgets.RemoteViews.ImageLike; + /** @deprecated */ + public static setImageURI($this: org.nativescript.widgets.RemoteViews.ImageLike, value: globalAndroid.net.Uri): org.nativescript.widgets.RemoteViews.ImageLike; + } + } + export class ImageView extends org.nativescript.widgets.RemoteViews implements org.nativescript.widgets.RemoteViews.ImageLike { + public static class: java.lang.Class; + public getCommands(): java.util.Map; + public constructor(); + public constructor(layout: org.nativescript.widgets.RemoteViews.Layout, id: string); + public setImageUrl(url: string): org.nativescript.widgets.RemoteViews.ImageLike; + public setImageResource(value: number): org.nativescript.widgets.RemoteViews.ImageLike; + public constructor(id: string); + public setImageURI(value: globalAndroid.net.Uri): org.nativescript.widgets.RemoteViews.ImageLike; + public setImageBitmap(value: globalAndroid.graphics.Bitmap): org.nativescript.widgets.RemoteViews.ImageLike; + } + export class Layout { + public static class: java.lang.Class; + public static AdapterViewFlipper: org.nativescript.widgets.RemoteViews.Layout; + public static Button: org.nativescript.widgets.RemoteViews.Layout; + public static Chronometer: org.nativescript.widgets.RemoteViews.Layout; + public static FrameLayout: org.nativescript.widgets.RemoteViews.Layout; + public static GridLayout: org.nativescript.widgets.RemoteViews.Layout; + public static GridView: org.nativescript.widgets.RemoteViews.Layout; + public static ImageButton: org.nativescript.widgets.RemoteViews.Layout; + public static ImageView: org.nativescript.widgets.RemoteViews.Layout; + public static LinearLayout: org.nativescript.widgets.RemoteViews.Layout; + public static ListView: org.nativescript.widgets.RemoteViews.Layout; + public static ProgressBar: org.nativescript.widgets.RemoteViews.Layout; + public static RelativeLayout: org.nativescript.widgets.RemoteViews.Layout; + public static StackView: org.nativescript.widgets.RemoteViews.Layout; + public static TextView: org.nativescript.widgets.RemoteViews.Layout; + public static ViewFlipper: org.nativescript.widgets.RemoteViews.Layout; + public static TextClock: org.nativescript.widgets.RemoteViews.Layout; + public static getEntries(): any; + public static valueOf(value: string): org.nativescript.widgets.RemoteViews.Layout; + public static values(): androidNative.Array; + } + export class LinearLayout extends org.nativescript.widgets.RemoteViews implements org.nativescript.widgets.RemoteViews.ViewGroupLike { + public static class: java.lang.Class; + public addView(this_: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public addView(child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public removeView(child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public constructor(); + public constructor(layout: org.nativescript.widgets.RemoteViews.Layout, id: string); + public removeView(it: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public constructor(id: string); + } + export class ListView extends org.nativescript.widgets.RemoteViews { + public static class: java.lang.Class; + public constructor(); + public constructor(layout: org.nativescript.widgets.RemoteViews.Layout, id: string); + public constructor(id: string); + } + export class ProgressBar extends org.nativescript.widgets.RemoteViews { + public static class: java.lang.Class; + public constructor(); + public constructor(layout: org.nativescript.widgets.RemoteViews.Layout, id: string); + public constructor(id: string); + } + export class RelativeLayout extends org.nativescript.widgets.RemoteViews implements org.nativescript.widgets.RemoteViews.ViewGroupLike { + public static class: java.lang.Class; + public addView(this_: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public addView(child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public removeView(child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public constructor(); + public constructor(layout: org.nativescript.widgets.RemoteViews.Layout, id: string); + public removeView(it: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public constructor(id: string); + } + export class StackView extends org.nativescript.widgets.RemoteViews implements org.nativescript.widgets.RemoteViews.ViewGroupLike { + public static class: java.lang.Class; + public addView(this_: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public addView(child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public removeView(child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public constructor(); + public constructor(layout: org.nativescript.widgets.RemoteViews.Layout, id: string); + public removeView(it: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public constructor(id: string); + } + export class TextClock extends org.nativescript.widgets.RemoteViews implements org.nativescript.widgets.RemoteViews.TextLike { + public static class: java.lang.Class; + public getCommands(): java.util.Map; + public constructor(); + public setText(value: string): org.nativescript.widgets.RemoteViews.TextLike; + public constructor(layout: org.nativescript.widgets.RemoteViews.Layout, id: string); + public constructor(id: string); + public setTextColor(value: number): org.nativescript.widgets.RemoteViews.TextLike; + } + export class TextLike { + public static class: java.lang.Class; + /** + * Constructs a new instance of the org.nativescript.widgets.RemoteViews$TextLike interface with the provided implementation. An empty constructor exists calling super() when extending the interface class. + */ + public constructor(implementation: { + getCommands(): java.util.Map; + setText(value: string): org.nativescript.widgets.RemoteViews.TextLike; + setTextColor(value: number): org.nativescript.widgets.RemoteViews.TextLike; + access$setText$jd($this: org.nativescript.widgets.RemoteViews.TextLike, value: string): org.nativescript.widgets.RemoteViews.TextLike; + access$setTextColor$jd($this: org.nativescript.widgets.RemoteViews.TextLike, value: number): org.nativescript.widgets.RemoteViews.TextLike; + }); + public constructor(); + public getCommands(): java.util.Map; + public setText(value: string): org.nativescript.widgets.RemoteViews.TextLike; + public setTextColor(value: number): org.nativescript.widgets.RemoteViews.TextLike; + } + export module TextLike { + export class DefaultImpls { + public static class: java.lang.Class; + /** @deprecated */ + public static setText($this: org.nativescript.widgets.RemoteViews.TextLike, value: string): org.nativescript.widgets.RemoteViews.TextLike; + /** @deprecated */ + public static setTextColor($this: org.nativescript.widgets.RemoteViews.TextLike, value: number): org.nativescript.widgets.RemoteViews.TextLike; + } + } + export class TextView extends org.nativescript.widgets.RemoteViews implements org.nativescript.widgets.RemoteViews.TextLike { + public static class: java.lang.Class; + public getCommands(): java.util.Map; + public constructor(); + public setText(value: string): org.nativescript.widgets.RemoteViews.TextLike; + public constructor(layout: org.nativescript.widgets.RemoteViews.Layout, id: string); + public constructor(id: string); + public setTextColor(value: number): org.nativescript.widgets.RemoteViews.TextLike; + } + export class ViewFlipper extends org.nativescript.widgets.RemoteViews implements org.nativescript.widgets.RemoteViews.ViewGroupLike { + public static class: java.lang.Class; + public addView(this_: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public addView(child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public removeView(child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public constructor(); + public constructor(layout: org.nativescript.widgets.RemoteViews.Layout, id: string); + public removeView(it: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public constructor(id: string); + } + export class ViewGroupLike { + public static class: java.lang.Class; + /** + * Constructs a new instance of the org.nativescript.widgets.RemoteViews$ViewGroupLike interface with the provided implementation. An empty constructor exists calling super() when extending the interface class. + */ + public constructor(implementation: { + addView(this_: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + removeView(it: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + access$addView$jd($this: org.nativescript.widgets.RemoteViews.ViewGroupLike, child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + access$removeView$jd($this: org.nativescript.widgets.RemoteViews.ViewGroupLike, child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + }); + public constructor(); + public addView(this_: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + public removeView(it: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + } + export module ViewGroupLike { + export class DefaultImpls { + public static class: java.lang.Class; + /** @deprecated */ + public static addView($this: org.nativescript.widgets.RemoteViews.ViewGroupLike, child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + /** @deprecated */ + public static removeView($this: org.nativescript.widgets.RemoteViews.ViewGroupLike, child: org.nativescript.widgets.RemoteViews): org.nativescript.widgets.RemoteViews.ViewGroupLike; + } + } + export class WhenMappings { + public static class: java.lang.Class; + } + } + } + } +} + +declare module org { + export module nativescript { + export module widgets { + export class RemoteViewsManager { + public static class: java.lang.Class; + public reparent(oldParentId: string, newParentId: string): void; + public build(it: string): globalAndroid.widget.RemoteViews; + public build(this_: string, rootId: string): globalAndroid.widget.RemoteViews; + public findViewById(found: string, childId: string): org.nativescript.widgets.RemoteViews; + public resolveRemoteResources(): void; + public remove(parentId: string): void; + public add(it: org.nativescript.widgets.RemoteViews, id: string): void; + public getById(id: string): org.nativescript.widgets.RemoteViews; + public getChildren(it: string): java.util.List; + public constructor(); + public getParent(it: string): org.nativescript.widgets.RemoteViews; + } + } + } +} \ No newline at end of file diff --git a/packages/ui-mobile-base/android/build.gradle b/packages/ui-mobile-base/android/build.gradle index 6051f05dfc..0b80384bfc 100644 --- a/packages/ui-mobile-base/android/build.gradle +++ b/packages/ui-mobile-base/android/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:8.11.1' - classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.21' + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:2.2.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/packages/ui-mobile-base/android/widgetdemo/build.gradle.kts b/packages/ui-mobile-base/android/widgetdemo/build.gradle.kts index fe6375bd2d..7cc5352faa 100644 --- a/packages/ui-mobile-base/android/widgetdemo/build.gradle.kts +++ b/packages/ui-mobile-base/android/widgetdemo/build.gradle.kts @@ -27,11 +27,11 @@ android { } } compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } kotlinOptions { - jvmTarget = "11" + jvmTarget = "17" } } @@ -42,8 +42,9 @@ dependencies { implementation("com.google.android.material:material:1.12.0") implementation("androidx.activity:activity:1.10.1") implementation("androidx.constraintlayout:constraintlayout:2.2.1") - implementation(project(":widgets")) - testImplementation("junit:junit:4.13.2") + implementation(project(":widgets")) + implementation("androidx.work:work-runtime:2.10.0") + testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.2.1") androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1") } diff --git a/packages/ui-mobile-base/android/widgetdemo/src/main/AndroidManifest.xml b/packages/ui-mobile-base/android/widgetdemo/src/main/AndroidManifest.xml index fd9c3be6e8..44cca1a7f8 100644 --- a/packages/ui-mobile-base/android/widgetdemo/src/main/AndroidManifest.xml +++ b/packages/ui-mobile-base/android/widgetdemo/src/main/AndroidManifest.xml @@ -1,24 +1,37 @@ - - - - + + - - - - + + + + + + + + + + + + + + + + diff --git a/packages/ui-mobile-base/android/widgetdemo/src/main/java/org/nativescript/widgetsdemo/DemoWidgetProvider.kt b/packages/ui-mobile-base/android/widgetdemo/src/main/java/org/nativescript/widgetsdemo/DemoWidgetProvider.kt new file mode 100644 index 0000000000..fbb3cf90ea --- /dev/null +++ b/packages/ui-mobile-base/android/widgetdemo/src/main/java/org/nativescript/widgetsdemo/DemoWidgetProvider.kt @@ -0,0 +1,7 @@ +package org.nativescript.widgetsdemo + +import org.nativescript.widgets.AppWidgetProvider + +class DemoWidgetProvider : AppWidgetProvider() { + override val interval = 900000L +} diff --git a/packages/ui-mobile-base/android/widgetdemo/src/main/java/org/nativescript/widgetsdemo/MainActivity.kt b/packages/ui-mobile-base/android/widgetdemo/src/main/java/org/nativescript/widgetsdemo/MainActivity.kt index aa4c6ea0b1..3e408971b5 100644 --- a/packages/ui-mobile-base/android/widgetdemo/src/main/java/org/nativescript/widgetsdemo/MainActivity.kt +++ b/packages/ui-mobile-base/android/widgetdemo/src/main/java/org/nativescript/widgetsdemo/MainActivity.kt @@ -1,6 +1,9 @@ package org.nativescript.widgetsdemo import android.app.Dialog +import android.app.PendingIntent +import android.content.Context +import android.content.Intent import android.graphics.Color import android.os.Bundle import android.util.Log @@ -13,13 +16,16 @@ import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar import androidx.core.graphics.drawable.toDrawable import androidx.core.view.postDelayed -import androidx.core.widget.NestedScrollView import androidx.fragment.app.DialogFragment +import androidx.work.WorkerParameters +import org.nativescript.widgets.AppWidgetManager +import org.nativescript.widgets.AppWidgetWorker import org.nativescript.widgets.CommonLayoutParams import org.nativescript.widgets.ContentLayout import org.nativescript.widgets.GridLayout import org.nativescript.widgets.GridUnitType import org.nativescript.widgets.LayoutBase +import org.nativescript.widgets.RemoteViewsManager import org.nativescript.widgets.StackLayout import org.nativescript.widgets.Utils @@ -256,8 +262,12 @@ class MainActivity : AppCompatActivity() { page.overflowEdge = mode statusLabel.text = "Mode: $name" page.postDelayed(100) { - paddingLabel.text = "paddingBottom: ${page.paddingBottom} (edge=${page.edgeInsets.bottom}, ime=${page.imeInsets.bottom})" - Log.d(TAG, "Cycle -> $name: paddingBottom=${page.paddingBottom}, edge=${page.edgeInsets.bottom}, ime=${page.imeInsets.bottom}") + paddingLabel.text = + "paddingBottom: ${page.paddingBottom} (edge=${page.edgeInsets.bottom}, ime=${page.imeInsets.bottom})" + Log.d( + TAG, + "Cycle -> $name: paddingBottom=${page.paddingBottom}, edge=${page.edgeInsets.bottom}, ime=${page.imeInsets.bottom}" + ) } } @@ -282,9 +292,89 @@ class MainActivity : AppCompatActivity() { } } + class Worker(context: Context, params: WorkerParameters) : AppWidgetWorker(context, params) { + override fun doWork(): Result { + val widget = org.nativescript.widgets.RemoteViews.LinearLayout() + val btn = org.nativescript.widgets.RemoteViews.Button("button") + widget.addView(btn) + widget.setBackgroundColor(Color.RED) + val img = org.nativescript.widgets.RemoteViews.ImageView() + widget.addView(img) + img.setImageUrl("https://picsum.photos/seed/${System.currentTimeMillis()}/200/300") + + for (id in widgetIds) { + (widget.findViewById("button") as? org.nativescript.widgets.RemoteViews.Button)?.let { + btn.setText("Nice View Widget $id") + } + val updated = widget.build(applicationContext.packageName) + updateWidget(id, updated) + + widget.resolveRemoteResources() + updateWidget(id, widget.build(applicationContext.packageName)) + } + return Result.success() + } + } + + override fun onNewIntent(intent: Intent) { + super.onNewIntent(intent) + Log.d("com.test", "intent $intent") + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + AppWidgetManager.register( + "org.nativescript.widgetsdemo.DemoWidgetProvider", + object : AppWidgetManager.WidgetListener { + override fun onUpdateAsync( + context: Context, + provider: String, + appWidgetIds: IntArray, + manager: RemoteViewsManager, + widgetManager: android.appwidget.AppWidgetManager? + ) { + // AppWidgetWorker.enqueue(context, provider, appWidgetIds) + + val widget = org.nativescript.widgets.RemoteViews.LinearLayout() + val btn = org.nativescript.widgets.RemoteViews.Button("button") + btn.setSize( + 40f, + TypedValue.COMPLEX_UNIT_DIP, + 40f, + TypedValue.COMPLEX_UNIT_DIP, + ) + widget.addView(btn) + widget.setBackgroundColor(Color.RED) + val img = org.nativescript.widgets.RemoteViews.ImageView() +// img.setImageResource( +// R.drawable.ic_launcher_background +// ) + widget.addView(img) + for (id in appWidgetIds) { + (widget.findViewById("button") as? org.nativescript.widgets.RemoteViews.Button)?.let { + btn.setText("Nice View Widget $id") + val intent = PendingIntent.getActivity( + context, + 0, + Intent(applicationContext, MainActivity::class.java), + PendingIntent.FLAG_IMMUTABLE + ) + btn.setOnClickPendingIntent( + intent + ) + } + val updated = widget.build(applicationContext.packageName) + widgetManager?.updateAppWidget(id, updated) + + img.setImageUrl("https://picsum.photos/seed/${System.currentTimeMillis()}_$id/200/300") + + widget.resolveRemoteResources() + widgetManager?.updateAppWidget(id, widget.build(applicationContext.packageName)) + } + } + }) + Utils.enableEdgeToEdge(this) val frame = ContentLayout(this) diff --git a/packages/ui-mobile-base/android/widgetdemo/src/main/res/values/strings.xml b/packages/ui-mobile-base/android/widgetdemo/src/main/res/values/strings.xml index 7917a8704b..7244facc89 100644 --- a/packages/ui-mobile-base/android/widgetdemo/src/main/res/values/strings.xml +++ b/packages/ui-mobile-base/android/widgetdemo/src/main/res/values/strings.xml @@ -6,4 +6,5 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur euismod dictu Pellentesque blandit congue mattis. Proin eget nibh id nisl pellentesque elementum. Vestibulum neque arcu, luctus vitae pretium sed, venenatis quis odio. Quisque varius ligula id quam ullamcorper, ut gravida magna aliquam. Proin sit amet nibh tempus, aliquam justo ut, accumsan nibh. Curabitur non neque dui. Phasellus ac semper nunc. Aenean placerat lacinia suscipit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + NativeScript Widget Demo diff --git a/packages/ui-mobile-base/android/widgetdemo/src/main/res/xml/demo_widget_info.xml b/packages/ui-mobile-base/android/widgetdemo/src/main/res/xml/demo_widget_info.xml new file mode 100644 index 0000000000..3c5d61f210 --- /dev/null +++ b/packages/ui-mobile-base/android/widgetdemo/src/main/res/xml/demo_widget_info.xml @@ -0,0 +1,10 @@ + + diff --git a/packages/ui-mobile-base/android/widgets/build.gradle b/packages/ui-mobile-base/android/widgets/build.gradle index b942f0634f..d278229ca9 100644 --- a/packages/ui-mobile-base/android/widgets/build.gradle +++ b/packages/ui-mobile-base/android/widgets/build.gradle @@ -3,6 +3,7 @@ def isWinOs = System.properties['os.name'].toLowerCase().contains('windows') apply plugin: 'com.android.library' +apply plugin: 'org.jetbrains.kotlin.android' def computeCompileSdkVersion() { if (project.hasProperty("compileSdk")) { @@ -43,9 +44,17 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + kotlinOptions { + jvmTarget = '17' + } } dependencies { + implementation 'androidx.core:core-ktx:1.17.0' def androidXViewPagerVersion = "1.1.0" if (project.hasProperty("androidXViewPager")) { androidXViewPagerVersion = androidXViewPager @@ -108,6 +117,12 @@ dependencies { implementation "androidx.documentfile:documentfile:$androidXDocumentFileVersion" implementation "androidx.activity:activity:$androidXActivityVersion" implementation "androidx.core:core:$androidXCoreVersion" + + def androidXWorkVersion = "2.10.0" + if (project.hasProperty("androidXWork")) { + androidXWorkVersion = androidXWork + } + implementation("androidx.work:work-runtime:$androidXWorkVersion") } tasks.register('cleanBuildDir', Delete) { diff --git a/packages/ui-mobile-base/android/widgets/src/main/kotlin/AppWidgetManager.kt b/packages/ui-mobile-base/android/widgets/src/main/kotlin/AppWidgetManager.kt new file mode 100644 index 0000000000..d977fbd8f9 --- /dev/null +++ b/packages/ui-mobile-base/android/widgets/src/main/kotlin/AppWidgetManager.kt @@ -0,0 +1,109 @@ +package org.nativescript.widgets + +import android.content.Context +import android.os.Bundle +import java.util.concurrent.ConcurrentHashMap + +object AppWidgetManager { + + interface WidgetListener { + fun onEnabled(provider: String) {} + + fun onUpdate( + context: Context, + provider: String, + appWidgetIds: IntArray, + manager: RemoteViewsManager, + widgetManager: android.appwidget.AppWidgetManager? + ) { + } + + + fun onUpdateAsync( + context: Context, + provider: String, + appWidgetIds: IntArray, + manager: RemoteViewsManager, + widgetManager: android.appwidget.AppWidgetManager? + ) { + } + + fun onDisabled(provider: String) {} + fun onDeleted(provider: String, appWidgetIds: IntArray) {} + fun onOptionsChanged( + context: Context, + provider: String, + appWidgetId: Int, + newOptions: Bundle, + manager: RemoteViewsManager, + widgetManager: android.appwidget.AppWidgetManager? + ) { + } + } + + private val listeners = ConcurrentHashMap() + private val managers = ConcurrentHashMap() + + fun register(providerClass: String, listener: WidgetListener) { + listeners[providerClass] = listener + } + + fun unregister(providerClass: String) { + listeners.remove(providerClass) + managers.remove(providerClass) + } + + fun getManager(providerClass: String): RemoteViewsManager { + return managers.getOrPut(providerClass) { RemoteViewsManager() } + } + + internal fun notifyUpdate( + context: Context, + provider: String, + appWidgetIds: IntArray, + manager: RemoteViewsManager, + widgetManager: android.appwidget.AppWidgetManager? + ) { + listeners[provider]?.onUpdate(context, provider, appWidgetIds, manager, widgetManager) + } + + internal fun notifyUpdateAsync( + context: Context, + provider: String, + appWidgetIds: IntArray, + manager: RemoteViewsManager, + widgetManager: android.appwidget.AppWidgetManager? + ) { + listeners[provider]?.onUpdateAsync(context, provider, appWidgetIds, manager, widgetManager) + } + + internal fun notifyEnabled(provider: String) { + listeners[provider]?.onEnabled(provider) + } + + internal fun notifyDisabled(provider: String) { + listeners[provider]?.onDisabled(provider) + } + + internal fun notifyDeleted(provider: String, appWidgetIds: IntArray) { + listeners[provider]?.onDeleted(provider, appWidgetIds) + } + + internal fun notifyOptionsChanged( + context: Context, + provider: String, + appWidgetId: Int, + newOptions: Bundle, + manager: RemoteViewsManager, + widgetManager: android.appwidget.AppWidgetManager?, + ) { + listeners[provider]?.onOptionsChanged( + context, + provider, + appWidgetId, + newOptions, + manager, + widgetManager + ) + } +} diff --git a/packages/ui-mobile-base/android/widgets/src/main/kotlin/AppWidgetProvider.kt b/packages/ui-mobile-base/android/widgets/src/main/kotlin/AppWidgetProvider.kt new file mode 100644 index 0000000000..5d049ce6ff --- /dev/null +++ b/packages/ui-mobile-base/android/widgets/src/main/kotlin/AppWidgetProvider.kt @@ -0,0 +1,105 @@ +package org.nativescript.widgets + +import android.content.ComponentName +import android.content.Context +import android.os.Bundle +import androidx.work.WorkerParameters + +open class AppWidgetProvider : android.appwidget.AppWidgetProvider() { + private val providerName = this::class.java.name + open val interval = 900000L + + internal class WidgetWorker( + context: Context, + params: WorkerParameters + ) : AppWidgetWorker(context, params) { + override fun doWork(): Result { + val appWidgetManager = android.appwidget.AppWidgetManager.getInstance(applicationContext) + val component = ComponentName( + applicationContext, this.provider + ) + val ids = appWidgetManager.getAppWidgetIds(component) + if (ids.isEmpty()) { + cancelPeriodic( + applicationContext, + this.provider + ) + return Result.success() + } + + val manager = AppWidgetManager.getManager(this.provider) + AppWidgetManager.notifyUpdateAsync( + applicationContext, + this.provider, + ids, + manager, + appWidgetManager + ) + + return Result.success() + } + } + + override fun onEnabled(context: Context) { + super.onEnabled(context) + AppWidgetManager.notifyEnabled(providerName) + AppWidgetWorker.enqueuePeriodic(context, providerName, intArrayOf(), interval) + } + + override fun onUpdate( + context: Context?, + appWidgetManager: android.appwidget.AppWidgetManager?, + appWidgetIds: IntArray? + ) { + val context = context ?: return + val ids = appWidgetIds ?: return + val manager = AppWidgetManager.getManager(providerName) + AppWidgetManager.notifyUpdate( + context, + providerName, + ids, + manager, + appWidgetManager + ) + AppWidgetWorker.enqueueImmediate( + context, providerName, ids + ) + } + + override fun onDeleted(context: Context?, appWidgetIds: IntArray?) { + super.onDeleted(context, appWidgetIds) + appWidgetIds?.let { + AppWidgetManager.notifyDeleted(providerName, it) + } + } + + override fun onDisabled(context: Context) { + super.onDisabled(context) + AppWidgetManager.notifyDisabled(providerName) + AppWidgetWorker.cancelPeriodic( + context, providerName + ) + } + + + override fun onAppWidgetOptionsChanged( + context: Context?, + appWidgetManager: android.appwidget.AppWidgetManager?, + appWidgetId: Int, + newOptions: Bundle? + ) { + super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions) + val ctx = context ?: return + newOptions?.let { + val manager = AppWidgetManager.getManager(providerName) + AppWidgetManager.notifyOptionsChanged( + ctx, + providerName, + appWidgetId, + it, + manager, + appWidgetManager + ) + } + } +} diff --git a/packages/ui-mobile-base/android/widgets/src/main/kotlin/AppWidgetWorker.kt b/packages/ui-mobile-base/android/widgets/src/main/kotlin/AppWidgetWorker.kt new file mode 100644 index 0000000000..633f2df954 --- /dev/null +++ b/packages/ui-mobile-base/android/widgets/src/main/kotlin/AppWidgetWorker.kt @@ -0,0 +1,161 @@ +package org.nativescript.widgets + +import android.content.Context +import android.os.SystemClock +import androidx.work.Data +import androidx.work.ExistingPeriodicWorkPolicy +import androidx.work.ExistingWorkPolicy +import androidx.work.OneTimeWorkRequest +import androidx.work.PeriodicWorkRequest +import androidx.work.WorkInfo +import androidx.work.WorkManager +import androidx.work.Worker +import androidx.work.WorkerParameters +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.TimeUnit + +abstract class AppWidgetWorker( + context: Context, + params: WorkerParameters +) : Worker(context, params) { + + val widgetIds: IntArray + get() = inputData.getIntArray(KEY_WIDGET_IDS) ?: intArrayOf() + + val provider: String + get() = inputData.getString(KEY_PROVIDER) ?: "" + + companion object { + const val KEY_WIDGET_IDS = "widget_ids" + const val KEY_PROVIDER = "provider" + + private val lastEnqueuedAt = ConcurrentHashMap() + private const val MIN_INTERVAL_MS = 3000L + + @JvmStatic + fun buildData(provider: String, widgetIds: IntArray): Data { + return Data.Builder() + .putString(KEY_PROVIDER, provider) + .putIntArray(KEY_WIDGET_IDS, widgetIds) + .build() + } + + @JvmStatic + fun enqueue( + context: Context, + workerClass: Class, + provider: String, + widgetIds: IntArray + ) { + val workName = "widget_update_${provider}_once" + val now = SystemClock.elapsedRealtime() + val last = lastEnqueuedAt[workName] + if (last != null && now - last < MIN_INTERVAL_MS) return + lastEnqueuedAt[workName] = now + + val request = OneTimeWorkRequest.Builder(workerClass) + .setInputData(buildData(provider, widgetIds)) + .build() + WorkManager.getInstance(context) + .enqueueUniqueWork( + workName, + ExistingWorkPolicy.REPLACE, + request + ) + } + + inline fun enqueue( + context: Context, + provider: String, + widgetIds: IntArray + ) = enqueue(context, T::class.java, provider, widgetIds) + + @JvmStatic + @JvmOverloads + fun enqueuePeriodic( + context: Context, + workerClass: Class, + provider: String, + widgetIds: IntArray, + repeatIntervalMilliSeconds: Long = 900000, // 15 mins min time allowed + uniqueWorkName: String = "widget_update_$provider" + ) { + val request = PeriodicWorkRequest.Builder( + workerClass, + repeatIntervalMilliSeconds, TimeUnit.MILLISECONDS + ) + .setInputData(buildData(provider, widgetIds)) + .build() + WorkManager.getInstance(context) + .enqueueUniquePeriodicWork( + uniqueWorkName, + ExistingPeriodicWorkPolicy.UPDATE, + request + ) + } + + inline fun enqueuePeriodic( + context: Context, + provider: String, + widgetIds: IntArray, + repeatIntervalMilliSeconds: Long = 900000, + uniqueWorkName: String = "widget_update_$provider" + ) = enqueuePeriodic( + context, + T::class.java, + provider, + widgetIds, + repeatIntervalMilliSeconds, + uniqueWorkName + ) + + @JvmStatic + @JvmOverloads + fun cancelPeriodic( + context: Context, + provider: String, + uniqueWorkName: String = "widget_update_$provider" + ) { + WorkManager.getInstance(context).cancelUniqueWork(uniqueWorkName) + } + + + @JvmStatic + inline fun enqueueImmediate( + context: Context, + provider: String, + widgetIds: IntArray, + ) { + val request = OneTimeWorkRequest.Builder(T::class.java) + .setInputData(buildData(provider, widgetIds)) + .build() + WorkManager.getInstance(context).enqueueUniqueWork( + "widget_${provider}_immediate", + ExistingWorkPolicy.KEEP, + request + ) + } + + @JvmStatic + fun isScheduled(context: Context, provider: String): Boolean { + val statuses = WorkManager.getInstance(context) + .getWorkInfosForUniqueWork("widget_update_$provider") + .get() + return statuses.any { it.state == WorkInfo.State.ENQUEUED || it.state == WorkInfo.State.RUNNING } + } + } + + fun updateWidgets(rv: android.widget.RemoteViews?) { + rv ?: return + val mgr = android.appwidget.AppWidgetManager.getInstance(applicationContext) + for (id in widgetIds) { + mgr.updateAppWidget(id, rv) + } + } + + fun updateWidget(widgetId: Int, rv: android.widget.RemoteViews?) { + rv ?: return + val mgr = android.appwidget.AppWidgetManager.getInstance(applicationContext) + mgr.updateAppWidget(widgetId, rv) + } +} diff --git a/packages/ui-mobile-base/android/widgets/src/main/kotlin/RemoteViews.kt b/packages/ui-mobile-base/android/widgets/src/main/kotlin/RemoteViews.kt new file mode 100644 index 0000000000..23a185ece1 --- /dev/null +++ b/packages/ui-mobile-base/android/widgets/src/main/kotlin/RemoteViews.kt @@ -0,0 +1,489 @@ +package org.nativescript.widgets + +import android.annotation.SuppressLint +import android.app.PendingIntent +import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.net.Uri +import android.os.Build +import java.net.URL +import java.util.concurrent.atomic.AtomicLong + +open class RemoteViews(val layout: Layout, val id: String = generateId()) { + + companion object { + private val counter = AtomicLong(0) + fun generateId(): String = "ns_rv_${counter.incrementAndGet()}" + } + + internal val commands = mutableMapOf() + internal var stableId: Int? = null + internal var manager: RemoteViewsManager? = null + + sealed class Command { + abstract fun applyTo(rv: android.widget.RemoteViews, targetId: Int) + + open fun applyToWithContext(rv: android.widget.RemoteViews, targetId: Int, context: Context) {} + + data class SetText(val value: String) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + rv.setTextViewText(targetId, value) + } + } + + data class SetTextColor(val value: Int) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + rv.setTextColor(targetId, value) + } + } + + data class SetImageResource(val resId: Int) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + rv.setImageViewResource(targetId, resId) + } + } + + data class SetVisibility(val visibility: Int) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + rv.setViewVisibility(targetId, visibility) + } + } + + data class SetByte(val method: String, val value: Byte) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + rv.setByte(targetId, method, value) + } + } + + data class SetShort(val method: String, val value: Short) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + rv.setShort(targetId, method, value) + } + } + + data class SetInt(val method: String, val value: Int) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + rv.setInt(targetId, method, value) + } + } + + data class SetLong(val method: String, val value: Long) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + rv.setLong(targetId, method, value) + } + } + + data class SetFloat(val method: String, val value: Float) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + rv.setFloat(targetId, method, value) + } + } + + data class SetBoolean(val method: String, val value: Boolean) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + rv.setBoolean(targetId, method, value) + } + } + + data class SetString(val method: String, val value: String) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + rv.setString(targetId, method, value) + } + } + + data class SetBackgroundColor(val value: Int) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + rv.setInt(targetId, "setBackgroundColor", value) + } + } + + + data class SetImageURI(val value: Uri?) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + rv.setImageViewUri(targetId, value) + } + } + + data class SetImageBitmap(val value: Bitmap) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + rv.setImageViewBitmap(targetId, value) + } + } + + data class SetImageUrl(val url: String) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + // no-op: must be resolved via resolveRemoteResources() before build + } + + fun resolve(): SetImageBitmap? { + return try { + val bitmap = URL(url).openStream().use { BitmapFactory.decodeStream(it) } + bitmap?.let { SetImageBitmap(it) } + } catch (e: Exception) { + null + } + } + } + + data class SetOnClickPendingIntent(val intent: PendingIntent) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + rv.setOnClickPendingIntent( + targetId, intent + ) + } + + override fun applyToWithContext( + rv: android.widget.RemoteViews, + targetId: Int, + context: Context + ) { + } + } + + data class SetWidth(val value: Float, val unit: Int) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + rv.setViewLayoutWidth(targetId, value, unit) + } + } + } + + data class SetHeight(val value: Float, val unit: Int) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + rv.setViewLayoutHeight(targetId, value, unit) + } + } + } + + data class SetSize( + val width: Float, + val widthUnit: Int, + val height: Float, + val heightUnit: Int + ) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + rv.setViewLayoutWidth(targetId, width, widthUnit) + rv.setViewLayoutHeight(targetId, height, heightUnit) + } + } + } + + data class SetWidthDimen(val value: Float, val resource: String, val packageName: String?) : + Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) {} + + @SuppressLint("DiscouragedApi") + override fun applyToWithContext( + rv: android.widget.RemoteViews, + targetId: Int, + context: Context + ) { + val res = context.resources.getIdentifier( + resource, "dimen", packageName ?: context.packageName + ) + if (res > 0) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + rv.setViewLayoutWidthDimen( + targetId, + res + ) + } + } + } + } + + data class SetHeightDimen(val value: Float, val resource: String, val packageName: String?) : + Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) {} + + @SuppressLint("DiscouragedApi") + override fun applyToWithContext( + rv: android.widget.RemoteViews, + targetId: Int, + context: Context + ) { + val res = context.resources.getIdentifier( + resource, "dimen", packageName ?: context.packageName + ) + if (res > 0) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + rv.setViewLayoutHeightDimen( + targetId, + res + ) + } + } + } + } + + data class SetSizeDimen( + val width: Float, + val widthResource: String, + val widthPackageName: String?, + val height: Float, + val heightResource: String, + val heightPackageName: String? + ) : Command() { + override fun applyTo(rv: android.widget.RemoteViews, targetId: Int) {} + + @SuppressLint("DiscouragedApi") + override fun applyToWithContext( + rv: android.widget.RemoteViews, + targetId: Int, + context: Context + ) { + val widthRes = context.resources.getIdentifier( + widthResource, "dimen", widthPackageName ?: context.packageName + ) + if (widthRes > 0) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + rv.setViewLayoutWidthDimen( + targetId, + widthRes + ) + } + } + + + val heightRes = context.resources.getIdentifier( + heightResource, "dimen", heightPackageName ?: context.packageName + ) + if (heightRes > 0) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + rv.setViewLayoutHeightDimen( + targetId, + heightRes + ) + } + } + } + } + } + + fun resolveRemoteResources() { + ensureManager() + manager?.resolveRemoteResources() + } + + fun build(packageName: String): android.widget.RemoteViews? { + ensureManager() + return manager?.build(id, packageName) + } + + private fun ensureManager() { + if (manager == null) { + val mgr = RemoteViewsManager() + mgr.add(this) + } + } + + internal fun buildSelf(packageName: String): android.widget.RemoteViews { + stableId = R.id.ns_remote_view_root + val rv = android.widget.RemoteViews(packageName, toLayoutId()) + commands.values.forEach { cmd -> cmd.applyTo(rv, stableId!!) } + return rv + } + + enum class Layout { + AdapterViewFlipper, + Button, + Chronometer, + FrameLayout, + GridLayout, + GridView, + ImageButton, + ImageView, + LinearLayout, + ListView, + ProgressBar, + RelativeLayout, + StackView, + TextView, + ViewFlipper, + TextClock + } + + fun setBackgroundColor(value: Int): RemoteViews { + commands["setBackgroundColor"] = Command.SetBackgroundColor(value) + return this + } + + fun setVisibility(visibility: Int): RemoteViews { + commands["setVisibility"] = Command.SetVisibility(visibility) + return this + } + + fun setString(method: String, value: String): RemoteViews { + commands["setString:$method"] = Command.SetString(method, value) + return this + } + + fun setByte(method: String, value: Byte): RemoteViews { + commands["setByte:$method"] = Command.SetByte(method, value) + return this + } + + fun setInt(method: String, value: Int): RemoteViews { + commands["setInt:$method"] = Command.SetInt(method, value) + return this + } + + fun setShort(method: String, value: Short): RemoteViews { + commands["setShort:$method"] = Command.SetShort(method, value) + return this + } + + fun setLong(method: String, value: Long): RemoteViews { + commands["setLong:$method"] = Command.SetLong(method, value) + return this + } + + fun setFloat(method: String, value: Float): RemoteViews { + commands["setFloat:$method"] = Command.SetFloat(method, value) + return this + } + + fun setBoolean(method: String, value: Boolean): RemoteViews { + commands["setBoolean:$method"] = Command.SetBoolean(method, value) + return this + } + + fun setWidth(value: Float, unit: Int): RemoteViews { + commands["setWidth"] = Command.SetWidth(value, unit) + return this + } + + fun setHeight(value: Float, unit: Int): RemoteViews { + commands["setHeight"] = Command.SetHeight(value, unit) + return this + } + + fun setSize(width: Float, widthUnit: Int, height: Float, heightUnit: Int): RemoteViews { + commands["setSize"] = Command.SetSize(width, widthUnit, height, heightUnit) + return this + } + + fun setOnClickPendingIntent(intent: PendingIntent): RemoteViews { + commands["setOnClickPendingIntent"] = Command.SetOnClickPendingIntent(intent) + return this + } + + fun toLayoutId(): Int { + return when (layout) { + Layout.AdapterViewFlipper -> R.layout.ns_remote_views_adapter_view_flipper + Layout.Button -> R.layout.ns_remote_views_button + Layout.Chronometer -> R.layout.ns_remote_views_chronometer + Layout.FrameLayout -> R.layout.ns_remote_views_frame_layout + Layout.GridLayout -> R.layout.ns_remote_views_grid_layout + Layout.GridView -> R.layout.ns_remote_views_grid_view + Layout.ImageButton -> R.layout.ns_remote_views_image_button + Layout.ImageView -> R.layout.ns_remote_views_image_view + Layout.LinearLayout -> R.layout.ns_remote_views_linear_layout + Layout.ListView -> R.layout.ns_remote_views_list_view + Layout.ProgressBar -> R.layout.ns_remote_views_progress_bar + Layout.RelativeLayout -> R.layout.ns_remote_views_relative_layout + Layout.StackView -> R.layout.ns_remote_views_stack_view + Layout.TextView -> R.layout.ns_remote_views_text_view + Layout.ViewFlipper -> R.layout.ns_remote_views_view_flipper + Layout.TextClock -> R.layout.ns_remote_views_text_clock + } + } + + fun findViewById(id: String): RemoteViews? { + return manager?.findViewById(this.id, id) + } + + fun getCommands(): MutableMap { + return commands + } + + class AdapterViewFlipper(id: String = generateId()) : RemoteViews(Layout.AdapterViewFlipper, id) + + class Button(id: String = generateId()) : RemoteViews(Layout.Button, id), TextLike + + class Chronometer(id: String = generateId()) : RemoteViews(Layout.Chronometer, id) + + class FrameLayout(id: String = generateId()) : RemoteViews(Layout.FrameLayout, id), ViewGroupLike + + class GridLayout(id: String = generateId()) : RemoteViews(Layout.GridLayout, id), ViewGroupLike + + class GridView(id: String = generateId()) : RemoteViews(Layout.GridView, id), ViewGroupLike + + class ImageButton(id: String = generateId()) : RemoteViews(Layout.ImageButton, id), ImageLike + + class ImageView(id: String = generateId()) : RemoteViews(Layout.ImageView, id), ImageLike + + class LinearLayout(id: String = generateId()) : RemoteViews(Layout.LinearLayout, id), + ViewGroupLike + + class ListView(id: String = generateId()) : RemoteViews(Layout.ListView, id) + + class ProgressBar(id: String = generateId()) : RemoteViews(Layout.ProgressBar, id) + + class RelativeLayout(id: String = generateId()) : RemoteViews(Layout.RelativeLayout, id), + ViewGroupLike + + class StackView(id: String = generateId()) : RemoteViews(Layout.StackView, id), ViewGroupLike + + class TextView(id: String = generateId()) : RemoteViews(Layout.TextView, id), TextLike + + class ViewFlipper(id: String = generateId()) : RemoteViews(Layout.ViewFlipper, id), ViewGroupLike + + class TextClock(id: String = generateId()) : RemoteViews(Layout.TextClock, id), TextLike + + interface TextLike { + fun getCommands(): MutableMap + + fun setText(value: String): TextLike { + getCommands()["setText"] = Command.SetText(value) + return this + } + + fun setTextColor(value: Int): TextLike { + getCommands()["setTextColor"] = Command.SetTextColor(value) + return this + } + } + + interface ViewGroupLike { + fun addView(child: RemoteViews): ViewGroupLike { + val self = this as RemoteViews + self.ensureManager() + self.manager?.add(child, self.id) + return this + } + + fun removeView(child: RemoteViews): ViewGroupLike { + val self = this as RemoteViews + child.id.let { self.manager?.remove(it) } + return this + } + } + + interface ImageLike { + fun getCommands(): MutableMap + + fun setImageResource(value: Int): ImageLike { + getCommands()["setImageResource"] = Command.SetImageResource(value) + return this + } + + fun setImageURI(value: Uri?): ImageLike { + getCommands()["setImageURI"] = Command.SetImageURI(value) + return this + } + + fun setImageBitmap(value: Bitmap): ImageLike { + getCommands()["setImageBitmap"] = Command.SetImageBitmap(value) + return this + } + + fun setImageUrl(url: String): ImageLike { + getCommands()["setImageUrl"] = Command.SetImageUrl(url) + return this + } + } +} diff --git a/packages/ui-mobile-base/android/widgets/src/main/kotlin/RemoteViewsManager.kt b/packages/ui-mobile-base/android/widgets/src/main/kotlin/RemoteViewsManager.kt new file mode 100644 index 0000000000..72d2f61dac --- /dev/null +++ b/packages/ui-mobile-base/android/widgets/src/main/kotlin/RemoteViewsManager.kt @@ -0,0 +1,108 @@ +package org.nativescript.widgets + +class RemoteViewsManager { + private val nodes = mutableMapOf() + private val parents = mutableMapOf() + private val children = mutableMapOf>() + + fun add(node: RemoteViews, parentId: String? = null) { + val id = node.id + node.manager = this + nodes[id] = node + parents[id] = parentId + children[id] = mutableListOf() + + // register as child of parent + parentId?.let { children[it]?.add(id) } + } + + fun remove(id: String) { + // detach from parent + parents[id]?.let { parentId -> + children[parentId]?.remove(id) + } + // reparent children to null or could reparent to grandparent + children[id]?.forEach { childId -> + parents[childId] = null + } + nodes[id]?.manager = null + nodes.remove(id) + parents.remove(id) + children.remove(id) + } + + fun reparent(id: String, newParentId: String?) { + // detach from old parent + parents[id]?.let { oldParentId -> + children[oldParentId]?.remove(id) + } + // attach to new parent + parents[id] = newParentId + newParentId?.let { children[it]?.add(id) } + } + + fun getById(id: String): RemoteViews? = nodes[id] + + fun findViewById(parentId: String, targetId: String): RemoteViews? { + if (parentId == targetId) return nodes[parentId] + children[parentId]?.forEach { childId -> + if (childId == targetId) return nodes[childId] + val found = findViewById(childId, targetId) + if (found != null) return found + } + return null + } + + fun getChildren(id: String): List { + return children[id]?.mapNotNull { nodes[it] } ?: emptyList() + } + + fun getParent(id: String): RemoteViews? { + return parents[id]?.let { nodes[it] } + } + + fun resolveRemoteResources() { + for (node in nodes.values) { + val iterator = node.commands.entries.iterator() + val resolved = mutableMapOf() + while (iterator.hasNext()) { + val entry = iterator.next() + val cmd = entry.value + if (cmd is RemoteViews.Command.SetImageUrl) { + val bitmap = cmd.resolve() + if (bitmap != null) { + resolved[entry.key] = bitmap + } else { + iterator.remove() + } + } + } + node.commands.putAll(resolved) + } + } + + fun build(packageName: String): android.widget.RemoteViews? { + val rootId = parents.entries.firstOrNull { it.value == null }?.key ?: return null + val root = nodes[rootId] ?: return null + return buildNode(rootId, packageName, root) + } + + fun build(rootId: String, packageName: String): android.widget.RemoteViews? { + val root = nodes[rootId] ?: return null + return buildNode(rootId, packageName, root) + } + + private fun buildNode( + id: String, + packageName: String, + node: RemoteViews + ): android.widget.RemoteViews { + val rv = node.buildSelf(packageName) + children[id]?.forEach { childId -> + val childNode = nodes[childId] ?: return@forEach + val childRv = buildNode(childId, packageName, childNode) + rv.addView(node.stableId!!, childRv) + } + return rv + } +} diff --git a/packages/ui-mobile-base/android/widgets/src/main/res/layout/ns_remote_views_adapter_view_flipper.xml b/packages/ui-mobile-base/android/widgets/src/main/res/layout/ns_remote_views_adapter_view_flipper.xml new file mode 100644 index 0000000000..933343d1ae --- /dev/null +++ b/packages/ui-mobile-base/android/widgets/src/main/res/layout/ns_remote_views_adapter_view_flipper.xml @@ -0,0 +1,8 @@ + + + + diff --git a/packages/ui-mobile-base/android/widgets/src/main/res/layout/ns_remote_views_button.xml b/packages/ui-mobile-base/android/widgets/src/main/res/layout/ns_remote_views_button.xml new file mode 100644 index 0000000000..a5142adfa8 --- /dev/null +++ b/packages/ui-mobile-base/android/widgets/src/main/res/layout/ns_remote_views_button.xml @@ -0,0 +1,5 @@ + +