| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import UIKit |
| import Flutter |
| |
| 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" |
| } |
| |
| @UIApplicationMain |
| @objc class AppDelegate: FlutterAppDelegate, FlutterStreamHandler { |
| private var eventSink: FlutterEventSink? |
| |
| override func application( |
| _ application: UIApplication, |
| didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { |
| GeneratedPluginRegistrant.register(with: self) |
| guard let controller = window?.rootViewController as? FlutterViewController else { |
| fatalError("rootViewController is not type FlutterViewController") |
| } |
| let batteryChannel = FlutterMethodChannel(name: ChannelName.battery, |
| binaryMessenger: controller.binaryMessenger) |
| batteryChannel.setMethodCallHandler({ |
| [weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in |
| guard call.method == "getBatteryLevel" else { |
| result(FlutterMethodNotImplemented) |
| return |
| } |
| self?.receiveBatteryLevel(result: result) |
| }) |
| |
| let chargingChannel = FlutterEventChannel(name: ChannelName.charging, |
| binaryMessenger: controller.binaryMessenger) |
| chargingChannel.setStreamHandler(self) |
| return super.application(application, didFinishLaunchingWithOptions: launchOptions) |
| } |
| |
| private func receiveBatteryLevel(result: FlutterResult) { |
| let device = UIDevice.current |
| device.isBatteryMonitoringEnabled = true |
| guard device.batteryState != .unknown else { |
| result(FlutterError(code: MyFlutterErrorCode.unavailable, |
| message: "Battery info unavailable", |
| details: nil)) |
| return |
| } |
| result(Int(device.batteryLevel * 100)) |
| } |
| |
| public func onListen(withArguments arguments: Any?, |
| eventSink: @escaping FlutterEventSink) -> FlutterError? { |
| self.eventSink = eventSink |
| UIDevice.current.isBatteryMonitoringEnabled = true |
| sendBatteryStateEvent() |
| NotificationCenter.default.addObserver( |
| self, |
| selector: #selector(AppDelegate.onBatteryStateDidChange), |
| name: UIDevice.batteryStateDidChangeNotification, |
| object: nil) |
| return nil |
| } |
| |
| @objc private func onBatteryStateDidChange(notification: NSNotification) { |
| sendBatteryStateEvent() |
| } |
| |
| private func sendBatteryStateEvent() { |
| guard let eventSink = eventSink else { |
| return |
| } |
| |
| switch UIDevice.current.batteryState { |
| case .full: |
| eventSink(BatteryState.charging) |
| case .charging: |
| eventSink(BatteryState.charging) |
| case .unplugged: |
| eventSink(BatteryState.discharging) |
| default: |
| eventSink(FlutterError(code: MyFlutterErrorCode.unavailable, |
| message: "Charging status unavailable", |
| details: nil)) |
| } |
| } |
| |
| public func onCancel(withArguments arguments: Any?) -> FlutterError? { |
| NotificationCenter.default.removeObserver(self) |
| eventSink = nil |
| return nil |
| } |
| } |