WatchOS 6.0、Swift 5.0:无背景触觉

Posted

技术标签:

【中文标题】WatchOS 6.0、Swift 5.0:无背景触觉【英文标题】:WatchOS 6.0, Swift 5.0 : No Background Haptics 【发布时间】:2020-03-10 12:35:04 【问题描述】:

我正在尝试在应用处于后台时获得触觉反馈。本质上,当某个值超过阈值时,应该有触觉反馈。据我所见,我已经正确设置了所有内容;当超过阈值时我正在调用的函数我知道正在被调用,因为我可以在日志中看到它,但是没有声音或振动发生。所以我不确定我做错了什么。当应用程序显示在屏幕上而不是在后台显示时,它可以正常工作。

这是使用较旧的 Apple 示例代码(我知道折旧的项目)。我的最终目标是拥有一个棒球投球分析应用程序,其触觉是加强学习的肌肉记忆,有点像与狗一起训练的答题器。

这是引入 CoreMotion 的 MotionManager。

import Foundation
import CoreMotion
import WatchKit
import os.log

protocol MotionManagerDelegate: class 
    func didUpdateMotion(_ manager: MotionManager, gravityStr: String, rotationRateStr: String, userAccelStr: String, attitudeStr: String, rollInt: Double)


extension Date 
    var millisecondsSince1970:Int64 
        return Int64((self.timeIntervalSince1970 * 1000.0).rounded())
    


class MotionManager 
// MARK: Properties

let motionManager = CMMotionManager()
let queue = OperationQueue()
let wristLocationIsLeft = WKInterfaceDevice.current().wristLocation == .left

// MARK: Application Specific Constants

// The app is using 50hz data and the buffer is going to hold 1s worth of data.
let sampleInterval = 1.0 / 50
let rateAlongGravityBuffer = RunningBuffer(size: 50)

weak var delegate: MotionManagerDelegate?

var gravityStr = ""
var rotationRateStr = ""
var userAccelStr = ""
var attitudeStr = ""
var rollInt = 0.0

var recentDetection = false

// MARK: Initialization

init() 
    // Serial queue for sample handling and calculations.
    queue.maxConcurrentOperationCount = 1
    queue.name = "MotionManagerQueue"


// MARK: Motion Manager

func startUpdates() 
    if !motionManager.isDeviceMotionAvailable 
        print("Device Motion is not available.")
        return
    

    os_log("Start Updates");

    motionManager.deviceMotionUpdateInterval = sampleInterval
    motionManager.startDeviceMotionUpdates(to: queue)  (deviceMotion: CMDeviceMotion?, error: Error?) in
        if error != nil 
            print("Encountered error: \(error!)")
        

        if deviceMotion != nil 
            self.processDeviceMotion(deviceMotion!)
        
    


func stopUpdates() 
    if motionManager.isDeviceMotionAvailable 
        motionManager.stopDeviceMotionUpdates()
    


// MARK: Motion Processing

func processDeviceMotion(_ deviceMotion: CMDeviceMotion) 
    gravityStr = String(format: "X: %.1f Y: %.1f Z: %.1f" ,
                        deviceMotion.gravity.x,
                        deviceMotion.gravity.y,
                        deviceMotion.gravity.z)
    userAccelStr = String(format: "X: %.1f Y: %.1f Z: %.1f" ,
                       deviceMotion.userAcceleration.x,
                       deviceMotion.userAcceleration.y,
                       deviceMotion.userAcceleration.z)
    rotationRateStr = String(format: "X: %.1f Y: %.1f Z: %.1f" ,
                          deviceMotion.rotationRate.x,
                          deviceMotion.rotationRate.y,
                          deviceMotion.rotationRate.z)
    attitudeStr = String(format: "r: %.1f p: %.1f y: %.1f" ,
                             deviceMotion.attitude.roll,
                             deviceMotion.attitude.pitch,
                             deviceMotion.attitude.yaw)

    rollInt = deviceMotion.attitude.roll

    let timestamp = Date().millisecondsSince1970

    os_log("Motion: %@, %@, %@, %@, %@, %@, %@, %@, %@, %@, %@, %@, %@",
           String(timestamp),
           String(deviceMotion.gravity.x),
           String(deviceMotion.gravity.y),
           String(deviceMotion.gravity.z),
           String(deviceMotion.userAcceleration.x),
           String(deviceMotion.userAcceleration.y),
           String(deviceMotion.userAcceleration.z),
           String(deviceMotion.rotationRate.x),
           String(deviceMotion.rotationRate.y),
           String(deviceMotion.rotationRate.z),
           String(deviceMotion.attitude.roll),
           String(deviceMotion.attitude.pitch),
           String(deviceMotion.attitude.yaw))

    updateMetricsDelegate();


// MARK: Data and Delegate Management

func updateMetricsDelegate() 
    delegate?.didUpdateMotion(self,gravityStr:gravityStr, rotationRateStr: rotationRateStr, userAccelStr: userAccelStr, attitudeStr: attitudeStr, rollInt: rollInt)


这是我的 WorkOutMangager,用于控制锻炼会话。我正在调用的函数在最后。它正在从 MotionManagerDelagate 中提取值。

import Foundation
import HealthKit
import WatchKit
import os.log

protocol WorkoutManagerDelegate: class 
    func didUpdateMotion(_ manager: WorkoutManager, gravityStr: String, rotationRateStr: String, userAccelStr: String, attitudeStr: String)


class WorkoutManager: MotionManagerDelegate 
    // MARK: Properties
    let motionManager = MotionManager()
    let healthStore = HKHealthStore()

var rollInt = 0.0

weak var delegate: WorkoutManagerDelegate?
var session: HKWorkoutSession?

// MARK: Initialization

init() 
    motionManager.delegate = self


// MARK: WorkoutManager

func startWorkout() 
    // If we have already started the workout, then do nothing.
    if (session != nil) 
        return
    

    // Configure the workout session.
    let workoutConfiguration = HKWorkoutConfiguration()
    workoutConfiguration.activityType = .tennis
    workoutConfiguration.locationType = .outdoor

    do 
        session = try HKWorkoutSession(configuration: workoutConfiguration)
     catch 
        fatalError("Unable to create the workout session!")
    

    // Start the workout session andKAKAHA.watchWatch.watchkitapp device motion updates.
    healthStore.start(session!)
    motionManager.startUpdates()

    if(rollInt < -0.9)
        WKInterfaceDevice.current().play(.failure)
        os_log("ALERT!!!")
    


func stopWorkout() 
    // If we have already stopped the workout, then do nothing.
    if (session == nil) 
        return
    

    // Stop the device motion updates and workout session.
    motionManager.stopUpdates()
    healthStore.end(session!)

    // Clear the workout session.
    session = nil


// MARK: MotionManagerDelegate

func didUpdateMotion(_ manager: MotionManager, gravityStr: String, rotationRateStr: String, userAccelStr: String, attitudeStr: String, rollInt: Double) 

    delegate?.didUpdateMotion(self, gravityStr: gravityStr, rotationRateStr: rotationRateStr, userAccelStr: userAccelStr, attitudeStr: attitudeStr)

    self.rollInt = rollInt
    rollAlert()


@objc fileprivate func rollAlert()
    if (rollInt < -0.9) 
        WKInterfaceDevice.current().play(.failure)
        os_log("TOO CLOSE TO FACE!!!")
    
   

【问题讨论】:

此外,无论多长时间后,应用“唤醒”时都会播放触觉。 【参考方案1】:

我觉得自己很愚蠢。我没有选择“音频”作为背景模式。

【讨论】:

以上是关于WatchOS 6.0、Swift 5.0:无背景触觉的主要内容,如果未能解决你的问题,请参考以下文章

Objective C iOS 项目 + Swift 2 WatchOS 项目和 Cocoapods

没有这样的模块错误“NotificationCenter”WatchOS,Swift

转动手腕时流暂停 - watchOS / Swift

iOS,swift:无延迟播放背景音乐和音效

如何将 watchOS Swift 目标添加到用 Objective-C 编写的 iOS 应用程序中

带背景图像按钮的圆形边框swift