我有一个角度为2的Cordova应用程序。我创建了一个自定义插件,进入设备检索一些数据,然后将其返回到一个页面,一切正常。
但是,当此页面在应用程序打开时运行时,设备就绪事件未触发,因此数据为空(如预期),因为角度已在设备准备好之前启动。
如何通知角度2已发生设备就绪事件?通常我会创建一个主题和订阅。
我想在应用程序的入口点执行此操作,并使用emit()通知应用程序中的区域:
declare var IPFinder, Windows, device;
@Injectable()
export class DeviceService {
// contains the api's for each plugin used
device: Observable<any>;
constructor(private cordovaService: CordovaService) {
this.deviceReadyEvent();
}
// when the device is ready
deviceReadyEvent() {
this.device = this.cordovaService.deviceReady.map(() => {
console.log('DEVICE READY IN ANGULAR');
// add plugins here
let deviceAPI = {
IPFinder: IPFinder,
device: device
};
this.platformSpecific(deviceAPI);
return deviceAPI;
});
}
private platformSpecific(deviceAPI) {
if (device.platform === 'windows') {
deviceAPI['Windows'] = Windows;
}
}
}
还有更好的选择吗?我知道在Angular 1中你会对应用程序进行bootrap,但它在v2中的工作方式不同。
更新---------------------------------------------- -
我接受了n00dl3的答案,效果很好
但是用这个作为我的服务:
this.deviceService.device.subscribe((device) => {
device.IPFinder.getIP((ips) => {
// zone required to update view
this.zone.run(() => {
this.setIPAddress(ips);
});
}, (error) => {
console.log('error', error);
});
});
然后我使用:
调用它(需要在构造函数private deviceService:DeviceService&amp; zone中)public static var isOffline = UserDefaults.standard.bool(forKey: "isOffline") {
didSet {
print("Saving isOffline flag which is now \(isOffline)")
DispatchQueue.main.async {
UserDefaults.standard.set(isOffline, forKey: "isOffline")
}
}
}
答案 0 :(得分:1)
您可以创建一个服务,该服务将使用Observable处理cordova事件,并从其他服务中的Observable
映射数据。 (我通过插件为我的个人案例提供了一项服务......)
在这个示例中,我想使用cordova-plugin-device获取平台信息。您需要安装类型定义:@types/cordova-plugin-device。
<强> cordova.service.ts 强>
@Injectable()
export class CordovaService {
deviceReady: Observable<Event>;
constructor() {
this.deviceReady = Observable.fromEvent(document, "deviceready").publishReplay(1);
(this.deviceReady as ConnectableObservable<Event>).connect();
}
}
对于该特定事件,您需要publishReplay(1)
和connect()
,因为它会触发一次,一旦设备准备就绪,任何其他侦听器都会立即被调用:
deviceready事件的行为与其他事件略有不同。在deviceready事件触发后注册的任何事件处理程序都会立即调用其回调函数。
<强> device.service.ts 强>
@Injectable()
export class DeviceService{
platform:Observable<any>;
constructor(private cdv:CordovaService){
this.platform = this.cdv.deviceReady.map(()=>device.platform);
}
}
并在随机组件中:
this.deviceService.platform.subscribe(platform=>console.log(platform));
如果您执行需要回调的操作(基本上任何cordova原生动作调用),您可以使用Observable.create()
创建一个observable。文件系统API的示例:
<强> filesystem.service.ts 强>
@Injectable()
export class FileSystemService {
constructor(private cdv: CordovaService, private zone: NgZone) { }
read(file: FileEntry, mode: "text" | "arrayBuffer" | "binaryString" | "dataURL" = "text") {
return this.cdv.deviceReady.switchMap(() => Observable.create((observer) => {
let reader = new FileReader();
reader.onerror = evt => {
this.zone.run(() => observer.error(evt));
};
reader.onloadend = evt => {
this.zone.run(() => observer.next(evt));
};
switch (mode) {
case "text":
reader.readAsText(file);
break;
case "arrayBuffer":
reader.readAsArrayBuffer(file);
break;
case "binaryString":
reader.readAsBinaryString(file);
break;
case "dataURL":
reader.readAsDataURL(file);
break;
}
}));
}
}
您可能需要导入ngZone
,因为回调可能会在角度区域之外运行,从而避免一些更改检测。