角2和科尔多瓦设备就绪

时间:2017-06-02 07:39:05

标签: angular cordova

我有一个角度为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")
                }

        }
    }

1 个答案:

答案 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,因为回调可能会在角度区域之外运行,从而避免一些更改检测。