mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
feat(android): support independent broadcast listeners (#10936)
This commit is contained in:
@@ -40,9 +40,11 @@ import {
|
||||
isA11yEnabled,
|
||||
setA11yEnabled,
|
||||
} from '../accessibility/accessibility-common';
|
||||
import { androidGetForegroundActivity, androidGetStartActivity, androidPendingReceiverRegistrations, androidRegisterBroadcastReceiver, androidRegisteredReceivers, androidSetForegroundActivity, androidSetStartActivity, androidUnregisterBroadcastReceiver, applyContentDescription } from './helpers';
|
||||
import { androidGetForegroundActivity, androidGetStartActivity, androidSetForegroundActivity, androidSetStartActivity, applyContentDescription } from './helpers';
|
||||
import { getImageFetcher, getNativeApp, getRootView, initImageCache, setA11yUpdatePropertiesCallback, setApplicationPropertiesCallback, setAppMainEntry, setNativeApp, setRootView, setToggleApplicationEventListenersCallback } from './helpers-common';
|
||||
import { getNativeScriptGlobals } from '../globals/global-utils';
|
||||
import type { AndroidApplication as IAndroidApplication } from './application';
|
||||
import lazy from '../utils/lazy';
|
||||
|
||||
declare class NativeScriptLifecycleCallbacks extends android.app.Application.ActivityLifecycleCallbacks {}
|
||||
|
||||
@@ -276,7 +278,36 @@ function initNativeScriptComponentCallbacks() {
|
||||
return NativeScriptComponentCallbacks_;
|
||||
}
|
||||
|
||||
export class AndroidApplication extends ApplicationCommon {
|
||||
interface RegisteredReceiverInfo {
|
||||
receiver: android.content.BroadcastReceiver;
|
||||
intent: string;
|
||||
callback: (context: android.content.Context, intent: android.content.Intent) => void;
|
||||
id: number;
|
||||
flags: number;
|
||||
}
|
||||
|
||||
const BroadcastReceiver = lazy(() => {
|
||||
@NativeClass
|
||||
class BroadcastReceiverImpl extends android.content.BroadcastReceiver {
|
||||
private _onReceiveCallback: (context: android.content.Context, intent: android.content.Intent) => void;
|
||||
|
||||
constructor(onReceiveCallback: (context: android.content.Context, intent: android.content.Intent) => void) {
|
||||
super();
|
||||
this._onReceiveCallback = onReceiveCallback;
|
||||
|
||||
return global.__native(this);
|
||||
}
|
||||
|
||||
public onReceive(context: android.content.Context, intent: android.content.Intent) {
|
||||
if (this._onReceiveCallback) {
|
||||
this._onReceiveCallback(context, intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
return BroadcastReceiverImpl;
|
||||
});
|
||||
|
||||
export class AndroidApplication extends ApplicationCommon implements IAndroidApplication {
|
||||
static readonly activityCreatedEvent = 'activityCreated';
|
||||
static readonly activityDestroyedEvent = 'activityDestroyed';
|
||||
static readonly activityStartedEvent = 'activityStarted';
|
||||
@@ -332,10 +363,13 @@ export class AndroidApplication extends ApplicationCommon {
|
||||
|
||||
this._registerPendingReceivers();
|
||||
}
|
||||
|
||||
private _registeredReceivers: Record<string, RegisteredReceiverInfo[]> = {};
|
||||
private _registeredReceiversById: Record<number, RegisteredReceiverInfo> = {};
|
||||
private _nextReceiverId: number = 1;
|
||||
private _pendingReceiverRegistrations: Omit<RegisteredReceiverInfo, 'receiver'>[] = [];
|
||||
private _registerPendingReceivers() {
|
||||
androidPendingReceiverRegistrations.forEach((func) => func(this.context));
|
||||
androidPendingReceiverRegistrations.length = 0;
|
||||
this._pendingReceiverRegistrations.forEach((info) => this._registerReceiver(this.context, info.intent, info.callback, info.flags, info.id));
|
||||
this._pendingReceiverRegistrations.length = 0;
|
||||
}
|
||||
|
||||
onConfigurationChanged(configuration: android.content.res.Configuration): void {
|
||||
@@ -414,18 +448,69 @@ export class AndroidApplication extends ApplicationCommon {
|
||||
// RECEIVER_EXPORTED (2)
|
||||
// RECEIVER_NOT_EXPORTED (4)
|
||||
// RECEIVER_VISIBLE_TO_INSTANT_APPS (1)
|
||||
public registerBroadcastReceiver(intentFilter: string, onReceiveCallback: (context: android.content.Context, intent: android.content.Intent) => void, flags = 2): void {
|
||||
androidRegisterBroadcastReceiver(intentFilter, onReceiveCallback, flags);
|
||||
public registerBroadcastReceiver(intentFilter: string, onReceiveCallback: (context: android.content.Context, intent: android.content.Intent) => void, flags = 2): () => void {
|
||||
const receiverId = this._nextReceiverId++;
|
||||
if (this.context) {
|
||||
this._registerReceiver(this.context, intentFilter, onReceiveCallback, flags, receiverId);
|
||||
} else {
|
||||
this._pendingReceiverRegistrations.push({
|
||||
intent: intentFilter,
|
||||
callback: onReceiveCallback,
|
||||
id: receiverId,
|
||||
flags,
|
||||
});
|
||||
}
|
||||
let removed = false;
|
||||
return () => {
|
||||
if (removed) {
|
||||
return;
|
||||
}
|
||||
removed = true;
|
||||
if (this._registeredReceiversById[receiverId]) {
|
||||
const receiverInfo = this._registeredReceiversById[receiverId];
|
||||
this.context.unregisterReceiver(receiverInfo.receiver);
|
||||
this._registeredReceivers[receiverInfo.intent] = this._registeredReceivers[receiverInfo.intent]?.filter((ri) => ri.id !== receiverId);
|
||||
delete this._registeredReceiversById[receiverId];
|
||||
} else {
|
||||
this._pendingReceiverRegistrations = this._pendingReceiverRegistrations.filter((ri) => ri.id !== receiverId);
|
||||
}
|
||||
};
|
||||
}
|
||||
private _registerReceiver(context: android.content.Context, intentFilter: string, onReceiveCallback: (context: android.content.Context, intent: android.content.Intent) => void, flags: number, id: number): android.content.BroadcastReceiver {
|
||||
const receiver: android.content.BroadcastReceiver = new (BroadcastReceiver())(onReceiveCallback);
|
||||
if (SDK_VERSION >= 26) {
|
||||
context.registerReceiver(receiver, new android.content.IntentFilter(intentFilter), flags);
|
||||
} else {
|
||||
context.registerReceiver(receiver, new android.content.IntentFilter(intentFilter));
|
||||
}
|
||||
const receiverInfo: RegisteredReceiverInfo = { receiver, intent: intentFilter, callback: onReceiveCallback, id: typeof id === 'number' ? id : this._nextReceiverId++, flags };
|
||||
this._registeredReceivers[intentFilter] ??= [];
|
||||
this._registeredReceivers[intentFilter].push(receiverInfo);
|
||||
this._registeredReceiversById[receiverInfo.id] = receiverInfo;
|
||||
return receiver;
|
||||
}
|
||||
|
||||
public unregisterBroadcastReceiver(intentFilter: string): void {
|
||||
androidUnregisterBroadcastReceiver(intentFilter);
|
||||
const receivers = this._registeredReceivers[intentFilter];
|
||||
if (receivers) {
|
||||
receivers.forEach((receiver) => {
|
||||
this.context.unregisterReceiver(receiver.receiver);
|
||||
});
|
||||
this._registeredReceivers[intentFilter] = [];
|
||||
}
|
||||
}
|
||||
|
||||
public getRegisteredBroadcastReceiver(intentFilter: string): android.content.BroadcastReceiver | undefined {
|
||||
return androidRegisteredReceivers[intentFilter];
|
||||
return this._registeredReceivers[intentFilter]?.[0].receiver;
|
||||
}
|
||||
|
||||
public getRegisteredBroadcastReceivers(intentFilter: string): android.content.BroadcastReceiver[] {
|
||||
const receiversInfo = this._registeredReceivers[intentFilter];
|
||||
if (receiversInfo) {
|
||||
return receiversInfo.map((info) => info.receiver);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
getRootView(): View {
|
||||
const activity = this.foregroundActivity || this.startActivity;
|
||||
if (!activity) {
|
||||
|
||||
Reference in New Issue
Block a user