Faire vibrer l'iPhone

228

Comment configurer l'iPhone pour qu'il vibre une fois?

Par exemple, lorsqu'un joueur perd une vie ou que le jeu est terminé, l'iPhone doit vibrer.

système
la source
9
Le geste de secousse est complètement différent de la vibration. L'une est à l'initiative de l'homme, l'autre à l'initiative de l'appareil.
Eiko

Réponses:

404

À partir de " Tutoriel iPhone: meilleure façon de vérifier les capacités des appareils iOS ":

Il existe deux fonctions apparemment similaires qui prennent un paramètre kSystemSoundID_Vibrate:

1) AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
2) AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);

Les deux fonctions font vibrer l'iPhone. Mais, lorsque vous utilisez la première fonction sur des appareils qui ne prennent pas en charge les vibrations, elle émet un bip. La deuxième fonction, en revanche, ne fait rien sur les appareils non pris en charge. Donc, si vous allez faire vibrer l'appareil en continu, comme une alerte, le bon sens dit, utilisez la fonction 2.

Tout d'abord, ajoutez le framework AudioToolbox AudioToolbox.framework à votre cible dans Build Phases.

Ensuite, importez ce fichier d'en-tête:

#import <AudioToolbox/AudioServices.h>
linuxbuild
la source
3
#import <Cocoa / Cocoa.h> n'est pas requis.
Raptor
10
Existe-t-il un moyen de réduire le temps de vibration à moins de 1 seconde?
George Asda
11
Je voudrais ajouter que si la vibration est désactivée dans les paramètres d'iOS, l'utilisateur n'obtiendra pas de vibration même si vous utilisez ces commandes.
Denis Kutlubaev
7
Dans Swift: AudioServicesPlayAlertSound(UInt32(kSystemSoundID_Vibrate))(au moins à partir de la bêta 2)
Sam Soffes
1
AudioServicesPlayAlertSound (kSystemSoundID_Vibrate); Vibarate sur iPhone, mais il n'émet aucun bip sur iPad.
Mangesh
45

Swift 2.0+

AudioToolbox présente maintenant le kSystemSoundID_Vibratecomme un SystemSoundIDtype, donc le code est:

import AudioToolbox.AudioServices

AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate)

Au lieu d'avoir à passer par l'étape de casting supplémentaire

(Accessoires à @Dov)

Réponse originale (Swift 1.x)

Et voici comment vous le faites sur Swift (au cas où vous auriez rencontré le même problème que moi)

Lier contre AudioToolbox.framework(Accédez à votre projet, sélectionnez votre cible, phases de construction, Liez le binaire aux bibliothèques, ajoutez-y la bibliothèque)

Une fois cela terminé:

import AudioToolbox.AudioServices

// Use either of these
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
AudioServicesPlayAlertSound(SystemSoundID(kSystemSoundID_Vibrate))

Ce qui SystemSoundIDest ringard, c'est que c'est fondamentalement un typealias(fantaisie rapide typedef) pour un UInt32, et kSystemSoundID_Vibratec'est un habitué Int. Le compilateur vous donne une erreur pour essayer de caster de IntversUInt32 convertir , mais l'erreur se lit comme "Impossible de convertir en SystemSoundID", ce qui est déroutant. Pourquoi Apple n'a-t-il pas simplement fait d'enum Swift est au-delà de moi.

@ aponomarenko va dans les détails, ma réponse est juste pour les Swifters là-bas.

Pouvez
la source
Cela semble être corrigé dans Swift 2 / iOS 9 / Xcode 7. J'ai utilisé AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)et cela s'est bien compilé
Dov
35

Un moyen simple de le faire est avec les services audio:

#import <AudioToolbox/AudioToolbox.h> 
...    
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
fsaint
la source
3
#import <AudioToolbox / AudioToolbox.h> et vous devrez ajouter AudioToolbox.framework aux phases de construction de votre projet.
Michael Mangold
31

J'ai eu de gros problèmes avec cela pour les appareils dont les vibrations étaient désactivées d'une manière ou d'une autre, mais nous en avions besoin pour fonctionner malgré tout, car cela est essentiel au fonctionnement de notre application, et comme il ne s'agit que d'un entier pour un appel de méthode documenté, il passera validation. J'ai donc essayé quelques sons qui étaient en dehors de ceux bien documentés ici: TUNER88 / iOSSystemSoundsLibrary

J'ai ensuite trébuché sur 1352, qui fonctionne indépendamment du commutateur silencieux ou des paramètres de l'appareil (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
la source
7
Il est toujours préférable d'utiliser des alias nommés au lieu de constantes magiques, comme kSystemSoundID_Vibrate au lieu de 1352. Je vous encourage à mettre à jour votre réponse.
nalexn
3
Je suis d'accord pour dire que l'utilisation de cette magie 1352 n'est pas idéale, mais je ne trouve pas d'autre moyen de forcer une vibration même lorsque le commutateur de vibration est éteint sur l'appareil. Cela semble être le seul moyen.
marcshilling
4
J'ai écrit une boucle for avec des entiers commençant au-delà des constantes publiées et compris laquelle causait une vibration
Joel Teply
2
Je peux confirmer que l'iPhone vibre même si le mode silencieux est activé sur l'iPhone. Très bonne réponse!
vomako
2
AudioServicesPlaySystemSound (1352) fonctionne toujours pour les iPhones quelle que soit la position du commutateur silencieux en janvier 2016
JustAnotherCoder
26

Remarque importante: Alerte de dépréciation future.

Depuis iOS 9.0 , la description des fonctions de l' API pour:

AudioServicesPlaySystemSound(inSystemSoundID: SystemSoundID)
AudioServicesPlayAlertSound(inSystemSoundID: SystemSoundID)

comprend la note suivante:

This function will be deprecated in a future release.
Use AudioServicesPlayAlertSoundWithCompletion or  
AudioServicesPlaySystemSoundWithCompletion instead.

La bonne façon de procéder sera d'utiliser l'un de ces deux éléments:

AudioServicesPlayAlertSoundWithCompletion(kSystemSoundID_Vibrate, nil)

ou

AudioServicesPlayAlertSoundWithCompletion(kSystemSoundID_Vibrate) {
 //your callback code when the vibration is done (it may not vibrate in iPod, but this callback will be always called)
}

se souvenir de import AVFoundation

Hugo Alonso
la source
la déclaration d'importation vous manque
Juan Boero
import AudioToolbox.AudioServices
Hugo Alonso
je l'ai fait moi-même, c'est juste avec celui d'AVFoundation.
Juan Boero
Quoi qu'il en soit pour régler la durée des vibrations?
Micro
Vous allez devoir concaténer plusieurs appels, utiliser un laps de temps entre chaque nouvel appel
Hugo Alonso
7

Pour un iPhone 7/7 Plus ou plus récent, utilisez ces trois API de rétroaction Haptic.

API disponibles

Pour les notifications:

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

Sont styles disponibles .error, .successet .warning. Chacun a sa propre sensation distinctive.
De la documentation :

Une UIFeedbackGeneratorsous-classe concrète qui crée des haptiques pour communiquer les succès, les échecs et les avertissements.

Pour des vibrations simples:

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

Sont styles disponibles .heavy, .mediumet .light. Ce sont de simples vibrations avec différents degrés de "dureté".
De la documentation :

Une UIFeedbackGeneratorsous-classe concrète qui crée des haptiques pour simuler les impacts physiques

Pour quand l'utilisateur a sélectionné un élément

let generator = UISelectionFeedbackGenerator()
generator.selectionChanged()

C'est le moins perceptible de tous les haptiques, et donc le plus approprié lorsque les haptiques ne devraient pas prendre le contrôle de l'expérience de l'application.
De la documentation :

Une UIFeedbackGeneratorsous-classe concrète qui crée des haptiques pour indiquer un changement de sélection.

Remarques

Il y a quelques points à retenir lors de l'utilisation de ces API.

Pas de thé

Vous ne créez pas réellement l'haptique. Vous demandez au système de générer un haptique. Le système décidera en fonction de ce qui suit:

  • Si des haptiques sont possibles sur l'appareil (s'il dispose d'un Taptic Engine dans ce cas)
  • Si l'application peut enregistrer de l'audio (les haptiques ne se génèrent pas pendant l'enregistrement pour éviter les interférences indésirables)
  • Si les haptiques sont activés dans les paramètres système.

Par conséquent, le système ignorera silencieusement votre demande d'haptique si cela n'est pas possible. Si cela est dû à un périphérique non pris en charge, vous pouvez essayer ceci:

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
    }

Remplacer les commentaires dans le switch-case instructions , et ce code de génération haptique sera portable sur d'autres appareils iOS. Il générera le plus haut niveau d'haptique possible.

Remarque B

  • Étant donné que la génération d'haptiques est une tâche de niveau matériel , il peut y avoir une latence entre le moment où vous appelez le code de génération d'haptiques et le moment où cela se produit. Pour cette raison, les API Taptic Engine ont toutes une prepare()méthode pour la mettre en état de préparation. Utilisation de votre exemple Game Over: vous savez peut-être que le jeu est sur le point de se terminer, si l'utilisateur a des PV très bas ou qu'un monstre dangereux est près d'eux.
  • Si vous ne générez pas d'haptique en quelques secondes, le Taptic Engine retournera dans un état inactif (pour économiser la batterie)


Dans ce cas, la préparation du Taptic Engine créerait une expérience de meilleure qualité et plus réactive.

Par exemple, supposons que votre application utilise un identificateur de mouvement panoramique pour modifier la partie du monde visible. Vous souhaitez générer un haptique lorsque l'utilisateur «regarde» à 360 degrés. Voici comment vous pouvez utiliser 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
la source
N'oubliez pas de le faire import UIKit!
Benj
Vous ne voulez pas créer une nouvelle instance de l' hapticintérieur de cette méthode. Vous impactOccuredn'appelez pas sur la même instance que vous appelez prepare.
rmaddy
5

Et si vous utilisez le framework Xamarin (monotouch), appelez simplement

SystemSound.Vibrate.PlayAlertSound()
Wheelie
la source
5

Au cours de mes voyages, j'ai constaté que si vous essayez l'une des options suivantes pendant que vous enregistrez de l'audio, l'appareil ne vibrera pas même s'il est activé.

1) AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
2) AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);

Ma méthode a été appelée à un moment précis dans la mesure des mouvements des appareils. J'ai dû arrêter l'enregistrement, puis le redémarrer après la vibration.

Cela ressemblait à ça.

-(void)vibrate {
    [recorder stop];
    AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
    [recorder start];
}

recorder est une instance AVRecorder.

J'espère que cela aide d'autres personnes qui ont déjà eu le même problème.

Sébastien Peek
la source
4

Dans iOS 10 et sur les iPhones plus récents, vous pouvez également utiliser l'API haptique. Cette rétroaction haptique est plus douce que l'API AudioToolbox.

Pour votre scénario GAME OVER, une rétroaction d'impact sur l'interface utilisateur lourde devrait convenir.

UIImpactFeedbackGenerator(style: .heavy).impactOccurred()

Vous pouvez utiliser les autres styles de rétroaction haptique .

samwize
la source
1

Dans Swift:

import AVFoundation
...
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
Eric
la source
0

Dans mon cas, j'utilisais l'AVCaptureSession. AudioToolbox était en phase de construction du projet et il a été importé mais ne fonctionnait toujours pas. Afin de le faire fonctionner, j'ai arrêté la session avant les vibrations et j'ai continué après.

#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
la source
-5

Vous pouvez utiliser

1) AudioServicesPlayAlertSound (kSystemSoundID_Vibrate);

pour iPhone et quelques iPods plus récents.

2) AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);

pour iPad.

swathy krishnan
la source
3
Les iPod touch et iPads ne peuvent pas vibrer.
DDPWNAGE
1
sur un appareil sans vibration (comme l'iPod Touch), cela ne fera rien
Lal Krishna