AppDelegate.swift 3.37 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5 6 7
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import UIKit
import Flutter

8 9 10 11 12 13 14 15 16 17 18 19 20 21
enum ChannelName {
  static let battery = "samples.flutter.io/battery"
  static let charging = "samples.flutter.io/charging"
}

enum BatteryState {
  static let charging = "charging"
  static let discharging = "discharging"
}

enum MyFlutterErrorCode {
  static let unavailable = "UNAVAILABLE"
}

22
@UIApplicationMain
23
@objc class AppDelegate: FlutterAppDelegate, FlutterStreamHandler {
24
  private var eventSink: FlutterEventSink?
25 26 27

  override func application(
    _ application: UIApplication,
28
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
29
    GeneratedPluginRegistrant.register(with: self)
30 31 32 33
    guard let controller = window?.rootViewController as? FlutterViewController else {
      fatalError("rootViewController is not type FlutterViewController")
    }
    let batteryChannel = FlutterMethodChannel(name: ChannelName.battery,
34
                                              binaryMessenger: controller.binaryMessenger)
35
    batteryChannel.setMethodCallHandler({
36 37
      [weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in
      guard call.method == "getBatteryLevel" else {
38
        result(FlutterMethodNotImplemented)
39
        return
40
      }
41
      self?.receiveBatteryLevel(result: result)
42
    })
43

44
    let chargingChannel = FlutterEventChannel(name: ChannelName.charging,
45
                                              binaryMessenger: controller.binaryMessenger)
46 47
    chargingChannel.setStreamHandler(self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
48 49
  }

50
  private func receiveBatteryLevel(result: FlutterResult) {
51 52
    let device = UIDevice.current
    device.isBatteryMonitoringEnabled = true
53 54
    guard device.batteryState != .unknown  else {
      result(FlutterError(code: MyFlutterErrorCode.unavailable,
55 56
                          message: "Battery info unavailable",
                          details: nil))
57
      return
58
    }
59
    result(Int(device.batteryLevel * 100))
60 61 62
  }

  public func onListen(withArguments arguments: Any?,
63
                       eventSink: @escaping FlutterEventSink) -> FlutterError? {
64 65 66
    self.eventSink = eventSink
    UIDevice.current.isBatteryMonitoringEnabled = true
    sendBatteryStateEvent()
67 68
    NotificationCenter.default.addObserver(
      self,
69
      selector: #selector(AppDelegate.onBatteryStateDidChange),
70
      name: UIDevice.batteryStateDidChangeNotification,
71
      object: nil)
72
    return nil
73 74 75
  }

  @objc private func onBatteryStateDidChange(notification: NSNotification) {
76
    sendBatteryStateEvent()
77 78 79
  }

  private func sendBatteryStateEvent() {
80
    guard let eventSink = eventSink else {
81
      return
82 83
    }

84 85 86 87 88 89 90
    switch UIDevice.current.batteryState {
    case .full:
      eventSink(BatteryState.charging)
    case .charging:
      eventSink(BatteryState.charging)
    case .unplugged:
      eventSink(BatteryState.discharging)
91
    default:
92 93 94
      eventSink(FlutterError(code: MyFlutterErrorCode.unavailable,
                             message: "Charging status unavailable",
                             details: nil))
95 96 97 98
    }
  }

  public func onCancel(withArguments arguments: Any?) -> FlutterError? {
99 100 101
    NotificationCenter.default.removeObserver(self)
    eventSink = nil
    return nil
102 103
  }
}