Hacer que el iPhone vibre

228

¿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.

sistema
fuente
99
El gesto de agitar es completamente diferente a la vibración. Uno es iniciado por humanos, otro iniciado por dispositivo.
Eiko

Respuestas:

404

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.frameworka su objetivo en Build Phases.

Luego, importe este archivo de encabezado:

#import <AudioToolbox/AudioServices.h>
linuxbuild
fuente
3
#import <Cocoa / Cocoa.h> no es obligatorio.
Raptor
10
¿Hay alguna manera de reducir el tiempo de vibración a menos de 1 segundo?
George Asda
11
Me gustaría agregar que si la vibración está desactivada en la configuración de iOS, el usuario no obtendrá vibración incluso si usa estos comandos.
Denis Kutlubaev
77
En Swift: AudioServicesPlayAlertSound(UInt32(kSystemSoundID_Vibrate))(al menos a partir de beta 2)
Sam Soffes
1
AudioServicesPlayAlertSound (kSystemSoundID_Vibrate); Vibarate en iPhone proerly pero no emite ningún pitido en iPad.
Mangesh
45

Swift 2.0+

AudioToolbox presenta ahora el kSystemSoundID_Vibratecomo un SystemSoundIDtipo, 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)

Respuesta original (Swift 1.x)

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 SystemSoundIDes básicamente un typealias(veloz fantasía typedef) para un UInt32, y kSystemSoundID_Vibratees un habitual Int. El compilador le da un error al intentar convertir desde Inta 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.

Poder
fuente
Esto parece estar solucionado en Swift 2 / iOS 9 / Xcode 7. Usé AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)y compilé bien
Dov
35

Una forma sencilla de hacerlo es con los servicios de audio:

#import <AudioToolbox/AudioToolbox.h> 
...    
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
fsaint
fuente
3
#import <AudioToolbox / AudioToolbox.h> y deberá agregar AudioToolbox.framework a las Fases de compilación de su proyecto.
Michael Mangold
31

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);
     }
}
Joel Teply
fuente
77
Siempre es mejor usar alias con nombre en lugar de constantes mágicas, como kSystemSoundID_Vibrate en lugar de 1352. Le recomiendo que actualice su respuesta.
nalexn
3
Estoy de acuerdo en que usar esta magia 1352 no es ideal, pero no puedo encontrar otra forma de forzar una vibración incluso cuando el interruptor de vibración está apagado en el dispositivo. Esta parece ser la única manera.
marcshilling
44
Escribí un bucle for con números enteros comenzando por las constantes publicadas y descubrí cuál causó una vibración
Joel Teply,
2
Puedo confirmar que el iPhone vibra incluso si el modo silencioso está activado en el iPhone. ¡Gran respuesta!
vomako
2
AudioServicesPlaySystemSound (1352) todavía funciona para iPhones independientemente de la posición del interruptor silencioso a partir de enero de 2016
JustAnotherCoder
26

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

Hugo Alonso
fuente
te falta la declaración de importación
Juan Boero
importar AudioToolbox.AudioServices
Hugo Alonso
Lo hice yo mismo, es solo con la Fundación AV.
Juan Boero
De todos modos para establecer la duración de la vibración?
Micro
Tendrá que concatenar varias llamadas, usar un lapso de tiempo entre cada nueva llamada
Hugo Alonso
7

Para un iPhone 7/7 Plus o más reciente, use estas tres API de retroalimentación háptica.

API disponibles

Para notificaciones:

let generator = UINotificationFeedbackGenerator()
generator.notificationOccured(style: .error)

Estilos disponibles son .error, .successy .warning. Cada uno tiene su propia sensación distintiva.
De los documentos :

Una UIFeedbackGeneratorsubclase concreta que crea hápticos para comunicar éxitos, fracasos y advertencias.

Para vibraciones simples:

let generator = UIImpactFeedbackGenerator(style: .medium)
generator.impactOccured()

Estilos disponibles son .heavy, .mediumy .light. Estas son vibraciones simples con diversos grados de "dureza".
De los documentos :

Una UIFeedbackGeneratorsubclase concreta que crea hápticos para simular impactos físicos.

Para cuando el usuario seleccionó un elemento

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 UIFeedbackGeneratorsubclase concreta que crea hápticos para indicar un cambio en la selección.

Notas

Hay un par de cosas que vale la pena recordar al usar estas API.

No hay té

En realidad no creas el háptico. Usted solicita el sistema genere una háptica. El sistema decidirá en base a lo siguiente:

  • Si los dispositivos táctiles son posibles en el dispositivo (si tiene un motor táctico en este caso)
  • Si la aplicación puede grabar audio (los hápticos no se generan durante la grabación para evitar interferencias no deseadas)
  • Si los hápticos están habilitados en la Configuración del sistema.

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.

Nota B

  • Debido al hecho de que generar hápticos es una tarea de nivel de hardware , puede haber una latencia entre cuando llama al código de generación háptica y cuándo sucede realmente. Por esta razón, las API de Taptic Engine tienen un 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.
  • Si no genera un háptico en unos pocos segundos, el Taptic Engine volverá a estar inactivo (para ahorrar batería)


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

} 
Benj
fuente
¡Solo recuerda import UIKit!
Benj
No desea crear una nueva instancia de hapticdentro de este método. No estás llamando impactOccureden la misma instancia que llamas prepare.
rmaddy
5

Y si está utilizando el marco Xamarin (monotouch), simplemente llame

SystemSound.Vibrate.PlayAlertSound()
Wheelie
fuente
5

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.

Sebastien Peek
fuente
4

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 .

samwize
fuente
1

En Swift:

import AVFoundation
...
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
Eric
fuente
0

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];
}
Caner Çakmak
fuente
-5

Puedes usar

1) AudioServicesPlayAlertSound (kSystemSoundID_Vibrate);

para iPhone y algunos iPods más nuevos.

2) AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);

para iPads

krishnan swathy
fuente
3
iPod touch y iPad no pueden vibrar.
DDPWNAGE
1
en un dispositivo sin capacidad de vibración (como iPod Touch) esto no hará nada
Lal Krishna