176 lines
5.8 KiB
Swift
176 lines
5.8 KiB
Swift
|
|
import AudioToolbox
|
||
|
|
import CoreHaptics
|
||
|
|
import Flutter
|
||
|
|
import UIKit
|
||
|
|
|
||
|
|
public class VibrationPluginSwift: NSObject, FlutterPlugin {
|
||
|
|
#if targetEnvironment(simulator)
|
||
|
|
private let isDevice = false
|
||
|
|
#else
|
||
|
|
private let isDevice = true
|
||
|
|
#endif
|
||
|
|
|
||
|
|
private static let feedbackGenerator = UIImpactFeedbackGenerator(style: .light)
|
||
|
|
|
||
|
|
@available(iOS 13.0, *)
|
||
|
|
public static var engine: CHHapticEngine?
|
||
|
|
|
||
|
|
public static func register(with registrar: FlutterPluginRegistrar) {
|
||
|
|
let channel = FlutterMethodChannel(name: "vibration", binaryMessenger: registrar.messenger())
|
||
|
|
let instance = VibrationPluginSwift()
|
||
|
|
|
||
|
|
if #available(iOS 13.0, *) {
|
||
|
|
VibrationPluginSwift.createEngine()
|
||
|
|
}
|
||
|
|
|
||
|
|
feedbackGenerator.prepare()
|
||
|
|
|
||
|
|
registrar.addMethodCallDelegate(instance, channel: channel)
|
||
|
|
}
|
||
|
|
|
||
|
|
@available(iOS 13.0, *)
|
||
|
|
public static func createEngine() {
|
||
|
|
// Create and configure a haptic engine.
|
||
|
|
do {
|
||
|
|
VibrationPluginSwift.engine = try CHHapticEngine()
|
||
|
|
} catch {
|
||
|
|
print("Engine creation error: \(error)")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
if VibrationPluginSwift.engine == nil {
|
||
|
|
print("Failed to create engine!")
|
||
|
|
}
|
||
|
|
|
||
|
|
// The stopped handler alerts you of engine stoppage due to external causes.
|
||
|
|
VibrationPluginSwift.engine?.stoppedHandler = { reason in
|
||
|
|
print("The engine stopped for reason: \(reason.rawValue)")
|
||
|
|
}
|
||
|
|
|
||
|
|
// The reset handler provides an opportunity for your app to restart the engine in case of failure.
|
||
|
|
VibrationPluginSwift.engine?.resetHandler = {
|
||
|
|
// Try restarting the engine.
|
||
|
|
print("The engine reset --> Restarting now!")
|
||
|
|
|
||
|
|
do {
|
||
|
|
try VibrationPluginSwift.engine?.start()
|
||
|
|
} catch {
|
||
|
|
print("Failed to restart the engine: \(error)")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private func supportsHaptics() -> Bool {
|
||
|
|
if #available(iOS 13.0, *) {
|
||
|
|
return CHHapticEngine.capabilitiesForHardware().supportsHaptics
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
@available(iOS 13.0, *)
|
||
|
|
private func playPattern(myArgs: [String: Any], pattern: [Int]) -> Void {
|
||
|
|
// Get event parameters, if any
|
||
|
|
var params: [CHHapticEventParameter] = []
|
||
|
|
//var amplitudes: [Int] = []
|
||
|
|
let amplitudes = myArgs["intensities"] as! [Int]
|
||
|
|
|
||
|
|
// Create haptic events
|
||
|
|
var hapticEvents: [CHHapticEvent] = []
|
||
|
|
var i: Int = 0
|
||
|
|
var rel: Double = 0.0
|
||
|
|
|
||
|
|
while i < pattern.count {
|
||
|
|
// Get intensity parameter, if any
|
||
|
|
if (i < amplitudes.count) {
|
||
|
|
if(amplitudes[i] != 0) {
|
||
|
|
let p = CHHapticEventParameter(parameterID: .hapticIntensity, value: Float(Double(amplitudes[i]) / 255.0))
|
||
|
|
// Get wait time and duration
|
||
|
|
let duration = Double(pattern[i]) / 1000.0
|
||
|
|
// Create haptic event
|
||
|
|
let e = CHHapticEvent(
|
||
|
|
eventType: .hapticContinuous,
|
||
|
|
parameters: [p],
|
||
|
|
relativeTime: rel,
|
||
|
|
duration: duration
|
||
|
|
)
|
||
|
|
hapticEvents.append(e)
|
||
|
|
// Add duration to relative time
|
||
|
|
rel += duration
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
let waitTime = Double(pattern[i]) / 1000.0
|
||
|
|
rel += waitTime
|
||
|
|
}
|
||
|
|
}
|
||
|
|
i += 1
|
||
|
|
}
|
||
|
|
// Try to play engine
|
||
|
|
do {
|
||
|
|
if let engine = VibrationPluginSwift.engine {
|
||
|
|
let patternToPlay = try CHHapticPattern(events: hapticEvents, parameters: [])
|
||
|
|
let player = try engine.makePlayer(with: patternToPlay)
|
||
|
|
try engine.start()
|
||
|
|
try player.start(atTime: 0)
|
||
|
|
}
|
||
|
|
} catch {
|
||
|
|
print("Failed to play pattern: \(error.localizedDescription).")
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||
|
|
switch call.method {
|
||
|
|
case "hasVibrator":
|
||
|
|
result(isDevice)
|
||
|
|
case "hasAmplitudeControl":
|
||
|
|
result(isDevice)
|
||
|
|
case "hasCustomVibrationsSupport":
|
||
|
|
result(supportsHaptics())
|
||
|
|
case "vibrate":
|
||
|
|
VibrationPluginSwift.feedbackGenerator.impactOccurred()
|
||
|
|
result(isDevice)
|
||
|
|
// guard let args = call.arguments else {
|
||
|
|
// result(false)
|
||
|
|
// return
|
||
|
|
// }
|
||
|
|
//
|
||
|
|
// guard let myArgs = args as? [String: Any] else {
|
||
|
|
// AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
|
||
|
|
// result(true)
|
||
|
|
// return
|
||
|
|
// }
|
||
|
|
//
|
||
|
|
// guard let pattern = myArgs["pattern"] as? [Int] else {
|
||
|
|
// AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
|
||
|
|
// result(true)
|
||
|
|
// return
|
||
|
|
// }
|
||
|
|
//
|
||
|
|
// if pattern.count == 0 {
|
||
|
|
// AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
|
||
|
|
// result(true)
|
||
|
|
// return
|
||
|
|
// }
|
||
|
|
//
|
||
|
|
// assert(pattern.count % 2 == 0, "Pattern must have even number of elements!")
|
||
|
|
//
|
||
|
|
// if !supportsHaptics() {
|
||
|
|
// AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
|
||
|
|
// result(true)
|
||
|
|
// return
|
||
|
|
// }
|
||
|
|
//
|
||
|
|
// if #available(iOS 13.0, *) {
|
||
|
|
// playPattern(myArgs: myArgs, pattern: pattern)
|
||
|
|
// }
|
||
|
|
//
|
||
|
|
// result(isDevice)
|
||
|
|
case "cancel":
|
||
|
|
result(nil)
|
||
|
|
default:
|
||
|
|
result(FlutterMethodNotImplemented)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|