¿Cómo se puede configurar el iPhone para que vibre una vez?
Por ejemplo, cuando un jugador pierde una vida o el juego termina, el iPhone debería vibrar.
¿Cómo se puede configurar el iPhone para que vibre una vez?
Por ejemplo, cuando un jugador pierde una vida o el juego termina, el iPhone debería vibrar.
Respuestas:
Desde " Tutorial de iPhone: Mejor manera de verificar las capacidades de los dispositivos iOS ":
Hay dos funciones aparentemente similares que toman un parámetro kSystemSoundID_Vibrate
:
1) AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
2) AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
Ambas funciones hacen vibrar el iPhone. Pero, cuando usa la primera función en dispositivos que no admiten vibración, reproduce un pitido. La segunda función, por otro lado, no hace nada en dispositivos no compatibles. Entonces, si va a hacer vibrar el dispositivo continuamente, como alerta, dice el sentido común, use la función 2.
Primero, agregue el marco AudioToolbox AudioToolbox.framework
a su objetivo en Build Phases.
Luego, importe este archivo de encabezado:
#import <AudioToolbox/AudioServices.h>
AudioServicesPlayAlertSound(UInt32(kSystemSoundID_Vibrate))
(al menos a partir de beta 2)
AudioToolbox presenta ahora el kSystemSoundID_Vibrate
como un SystemSoundID
tipo, por lo que el código es:
import AudioToolbox.AudioServices
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate)
En lugar de tener que pasar por el paso de lanzamiento adicional
(Apoyos para @Dov)
Y así es como lo haces en Swift (en caso de que te encuentres con el mismo problema que yo)
Enlace contra AudioToolbox.framework
(vaya a su proyecto, seleccione su objetivo, construya fases, enlace binario con bibliotecas, agregue la biblioteca allí)
Una vez que se haya completado:
import AudioToolbox.AudioServices
// Use either of these
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
AudioServicesPlayAlertSound(SystemSoundID(kSystemSoundID_Vibrate))
Lo cursi es que SystemSoundID
es básicamente un typealias
(veloz fantasía typedef
) para un UInt32
, y kSystemSoundID_Vibrate
es un habitual Int
. El compilador le da un error al intentar convertir desde Int
a UInt32
, pero el error se lee como "No se puede convertir a SystemSoundID", lo cual es confuso. ¿Por qué Apple no lo convirtió en una enumeración Swift?
@ aponomarenko entra en detalles, mi respuesta es solo para los Swifters.
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
y compilé bien
Una forma sencilla de hacerlo es con los servicios de audio:
#import <AudioToolbox/AudioToolbox.h>
...
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
Tuve un gran problema con esto para los dispositivos que tenían la vibración desactivada de alguna manera, pero necesitábamos que funcionara de todos modos, porque es fundamental para el funcionamiento de nuestra aplicación, y dado que es solo un número entero para una llamada de método documentada, pasará validación. Así que probé algunos sonidos que estaban fuera de los bien documentados aquí: TUNER88 / iOSSystemSoundsLibrary
Luego me topé con 1352, que funciona independientemente del interruptor silencioso o la configuración del dispositivo (Settings->vibrate on ring, vibrate on silent)
.
- (void)vibratePhone;
{
if([[UIDevice currentDevice].model isEqualToString:@"iPhone"])
{
AudioServicesPlaySystemSound (1352); //works ALWAYS as of this post
}
else
{
// Not an iPhone, so doesn't have vibrate
// play the less annoying tick noise or one of your own
AudioServicesPlayAlertSound (1105);
}
}
Nota importante: Alerta de desaprobación futura.
A partir de iOS 9.0 , la descripción de las funciones de API para:
AudioServicesPlaySystemSound(inSystemSoundID: SystemSoundID)
AudioServicesPlayAlertSound(inSystemSoundID: SystemSoundID)
incluye la siguiente nota:
This function will be deprecated in a future release.
Use AudioServicesPlayAlertSoundWithCompletion or
AudioServicesPlaySystemSoundWithCompletion instead.
La forma correcta de hacerlo será usar cualquiera de estos dos:
AudioServicesPlayAlertSoundWithCompletion(kSystemSoundID_Vibrate, nil)
o
AudioServicesPlayAlertSoundWithCompletion(kSystemSoundID_Vibrate) {
//your callback code when the vibration is done (it may not vibrate in iPod, but this callback will be always called)
}
Recuerda
import AVFoundation
Para un iPhone 7/7 Plus o más reciente, use estas tres API de retroalimentación háptica.
let generator = UINotificationFeedbackGenerator()
generator.notificationOccured(style: .error)
Estilos disponibles son .error
, .success
y .warning
. Cada uno tiene su propia sensación distintiva.
De los documentos :
Una
UIFeedbackGenerator
subclase concreta que crea hápticos para comunicar éxitos, fracasos y advertencias.
let generator = UIImpactFeedbackGenerator(style: .medium)
generator.impactOccured()
Estilos disponibles son .heavy
, .medium
y .light
. Estas son vibraciones simples con diversos grados de "dureza".
De los documentos :
Una
UIFeedbackGenerator
subclase concreta que crea hápticos para simular impactos físicos.
let generator = UISelectionFeedbackGenerator()
generator.selectionChanged()
Este es el menos notable de todos los hápticos, y por lo tanto, es el más adecuado para cuando los hápticos no deberían hacerse cargo de la experiencia de la aplicación.
De los documentos :
Una
UIFeedbackGenerator
subclase concreta que crea hápticos para indicar un cambio en la selección.
Hay un par de cosas que vale la pena recordar al usar estas API.
En realidad no creas el háptico. Usted solicita el sistema genere una háptica. El sistema decidirá en base a lo siguiente:
Por lo tanto, el sistema ignorará silenciosamente su solicitud de un háptico si no es posible. Si esto se debe a un dispositivo no compatible, puede intentar esto:
func haptic() {
// Get whether the device can generate haptics or not
// If feedbackSupportLevel is nil, will assign 0
let feedbackSupportLevel = UIDevice.current.value(forKey: "_feedbackSupportLevel") as? Int ?? 0
switch feedbackSupportLevel {
case 2:
// 2 means the device has a Taptic Engine
// Put Taptic Engine code here, using the APIs explained above
case 1:
// 1 means no Taptic Engine, but will support AudioToolbox
// AudioToolbox code from the myriad of other answers!
default: // 0
// No haptic support
// Do something else, like a beeping noise or LED flash instead of haptics
}
Sustituya los comentarios en las declaraciones switch
- case
, y este código de generación háptica será portátil para otros dispositivos iOS. Generará el mayor nivel de háptico posible.
prepare()
método para ponerlo en un estado de preparación. Ejemplo de uso de Game Over: es posible que sepa que el juego está a punto de finalizar, ya que el usuario tiene un HP muy bajo o un monstruo peligroso está cerca de ellos.
En este caso, preparar el Taptic Engine crearía una experiencia de mayor calidad y más receptiva.
Por ejemplo, supongamos que su aplicación utiliza un reconocedor de gestos panorámicos para cambiar la parte del mundo visible. Desea generar un háptico cuando el usuario "mira" alrededor de 360 grados. Aquí es cómo puedes usar prepare()
:
@IBAction func userChangedViewablePortionOfWorld(_ gesture: UIPanGestureRecogniser!) {
haptic = UIImpactFeedbackGenerator(style: .heavy)
switch gesture.state {
case .began:
// The user started dragging the screen.
haptic.prepare()
case .changed:
// The user trying to 'look' in another direction
// Code to change viewable portion of the virtual world
if virtualWorldViewpointDegreeMiddle = 360.0 {
haptic.impactOccured()
}
default:
break
}
import UIKit
!
haptic
dentro de este método. No estás llamando impactOccured
en la misma instancia que llamas prepare
.
En mis viajes descubrí que si intentas cualquiera de los siguientes mientras estás grabando audio, el dispositivo no vibrará incluso si está habilitado.
1) AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
2) AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
Mi método fue llamado en un momento específico en la medición de los movimientos de los dispositivos. Tuve que detener la grabación y luego reiniciarla después de que ocurriera la vibración.
Se veía así.
-(void)vibrate {
[recorder stop];
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
[recorder start];
}
recorder
es una instancia de AVRecorder.
Espero que esto ayude a otros que han tenido el mismo problema antes.
En iOS 10, y en iPhones más nuevos, también puede usar API háptica. Esta retroalimentación háptica es más suave que la API AudioToolbox.
Para su escenario GAME OVER, una retroalimentación de impacto de IU debe ser adecuada.
UIImpactFeedbackGenerator(style: .heavy).impactOccurred()
Podrías usar los otros estilos de retroalimentación háptica .
En mi caso estaba usando AVCaptureSession. AudioToolbox estaba en las fases de compilación del proyecto y se importó pero aún no funcionaba. Para que funcione, detuve la sesión antes de la vibración y continué después de eso.
#import <AudioToolbox/AudioToolbox.h>
...
@property (nonatomic) AVCaptureSession *session;
...
- (void)vibratePhone;
{
[self.session stopRunning];
NSLog(@"vibratePhone %@",@"here");
if([[UIDevice currentDevice].model isEqualToString:@"iPhone"])
{
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
}
else
{
AudioServicesPlayAlertSound (kSystemSoundID_Vibrate);
}
[self.session startRunning];
}
Puedes usar
1) AudioServicesPlayAlertSound (kSystemSoundID_Vibrate);
para iPhone y algunos iPods más nuevos.
2) AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
para iPads