Far vibrare l'iPhone


228

Come può l'iPhone essere impostato per vibrare una volta?

Ad esempio, quando un giocatore perde una vita o il gioco è finito, l'iPhone dovrebbe vibrare.


9
Agitare il gesto è completamente diverso dalla vibrazione. Uno è iniziato dall'uomo, un dispositivo è avviato.
Eiko,

Risposte:


404

Da " Tutorial per iPhone: un modo migliore per verificare le funzionalità dei dispositivi iOS ":

Esistono due funzioni apparentemente simili che accettano un parametro kSystemSoundID_Vibrate:

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

Entrambe le funzioni vibrano l'iPhone. Ma quando si utilizza la prima funzione su dispositivi che non supportano le vibrazioni, viene emesso un segnale acustico. La seconda funzione, d'altra parte, non fa nulla sui dispositivi non supportati. Quindi, se hai intenzione di far vibrare il dispositivo continuamente, come avviso, dice il buon senso, usa la funzione 2.

Innanzitutto, aggiungi il framework AudioToolbox AudioToolbox.framework al tuo target in Build Phases.

Quindi, importa questo file di intestazione:

#import <AudioToolbox/AudioServices.h>

3
#import <Cocoa / Cocoa.h> non è richiesto.
Raptor,

10
C'è un modo per ridurre il tempo di vibrazione a meno di 1 secondo?
George Asda,

11
Vorrei aggiungere che se la vibrazione è disattivata in Impostazioni di iOS, l'utente non otterrà la vibrazione anche se si utilizzano questi comandi.
Denis Kutlubaev il

7
In Swift: AudioServicesPlayAlertSound(UInt32(kSystemSoundID_Vibrate))(almeno dalla beta 2)
Sam Soffes,

1
AudioServicesPlayAlertSound (kSystemSoundID_Vibrate); Vibarate su iPhone in modo corretto ma non emette alcun segnale acustico su iPad.
Mangesh,

45

Swift 2.0+

AudioToolbox presenta ora il kSystemSoundID_Vibratecome un SystemSoundIDtipo, in modo che il codice è:

import AudioToolbox.AudioServices

AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate)

Invece di dover passare attraverso il passaggio del cast extra

(Prop a @Dov)

Risposta originale (Swift 1.x)

Ed ecco come lo fai su Swift (nel caso in cui ti sia imbattuto nello stesso problema che ho fatto io)

Collega contro AudioToolbox.framework(Vai al tuo progetto, seleziona il tuo obiettivo, costruisci fasi, Collega binario con librerie, aggiungi lì la libreria)

Una volta completato:

import AudioToolbox.AudioServices

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

La cosa di cattivo gusto è che SystemSoundIDè fondamentalmente un typealias(fantasia veloce typedef) per a UInt32, ed kSystemSoundID_Vibrateè un normale Int. Il compilatore ti dà un errore nel tentativo di eseguire il cast da IntaUInt32 , ma l'errore è "Impossibile convertire in SystemSoundID", il che è fonte di confusione. Perché la mela non l'ha fatta diventare un enum Swift è oltre me.

@ Aponomarenko va nei dettagli, la mia risposta è solo per gli Swifters.


Questo sembra essere stato risolto in Swift 2 / iOS 9 / Xcode 7. L'ho usato AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)e compilato bene
Dov

35

Un modo semplice per farlo è con i servizi audio:

#import <AudioToolbox/AudioToolbox.h> 
...    
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);

3
#import <AudioToolbox / AudioToolbox.h> e dovrai aggiungere AudioToolbox.framework alle fasi di costruzione del tuo progetto.
Michael Mangold,

31

Ho avuto grossi problemi con questo per i dispositivi che avevano la vibrazione disattivata in qualche modo, ma ne avevamo bisogno per funzionare indipendentemente, perché è fondamentale per il funzionamento della nostra applicazione e poiché è solo un numero intero per una chiamata di metodo documentata, passerà convalida. Quindi ho provato alcuni suoni che erano al di fuori di quelli ben documentati qui: TUNER88 / iOSSystemSoundsLibrary

Mi sono quindi imbattuto nel 1352, che funziona indipendentemente dall'interruttore silenzioso o dalle impostazioni sul 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);
     }
}

7
È sempre meglio usare alias nominati anziché costanti magiche, come kSystemSoundID_Vibrate invece 1352. Ti incoraggio ad aggiornare la tua risposta.
nalexn,

3
Concordo sul fatto che usare questa magia 1352 non sia l'ideale, ma non riesco a trovare nessun altro modo per forzare una vibrazione anche quando l'interruttore vibrazione è spento sul dispositivo. Questo sembra essere l'unico modo.
marcshilling,

4
Ho scritto un ciclo for con numeri interi che iniziano oltre le costanti pubblicate e ho capito quale ha causato una vibrazione
Joel Teply

2
Posso confermare che l'iPhone vibra anche se la modalità silenziosa è attivata sull'iPhone. Bella risposta!
vomako,

2
AudioServicesPlaySystemSound (1352) funziona ancora per iPhone indipendentemente dalla posizione dell'interruttore silenzioso a partire da gennaio 2016
JustAnotherCoder

26

Nota importante: avviso di futura deprecazione.

A partire da iOS 9.0 , la descrizione delle funzioni API per:

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

include la seguente nota:

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

La strada giusta da percorrere sarà usare uno di questi due:

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)
}

ricordati di import AVFoundation


ti manca la dichiarazione di importazione
Juan Boero,

import AudioToolbox.AudioServices
Hugo Alonso

l'ho fatto da solo, è solo con quello AVFoundation.
Juan Boero,

In ogni caso per impostare la durata della vibrazione?
Micro

Dovrai concatenare diverse chiamate, utilizzare un intervallo di tempo tra una nuova chiamata
altra

7

Per un iPhone 7/7 Plus o più recente, usa queste tre API di feedback Haptic.

API disponibili

Per le notifiche:

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

Stili disponibili sono .error, .successe .warning. Ognuno ha il suo aspetto distintivo.
Dai documenti :

Una UIFeedbackGeneratorsottoclasse concreta che crea tattiche per comunicare successi, fallimenti e avvertimenti.

Per vibrazioni semplici:

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

Stili disponibili sono .heavy, .mediume .light. Queste sono vibrazioni semplici con vari gradi di "durezza".
Dai documenti :

Una UIFeedbackGeneratorsottoclasse concreta che crea tattili per simulare gli impatti fisici

Per quando l'utente ha selezionato un elemento

let generator = UISelectionFeedbackGenerator()
generator.selectionChanged()

Questo è il meno evidente di tutti gli aspetti tattili, e quindi è il più adatto per quando i soggetti tattili non dovrebbero assumere l'esperienza dell'app.
Dai documenti :

Una UIFeedbackGeneratorsottoclasse concreta che crea tattili per indicare un cambiamento nella selezione.

Appunti

Ci sono un paio di cose che vale la pena ricordare quando si utilizzano queste API.

Nota A

In realtà non si crea l'ottico. Si richiede al sistema di generare un aptico. Il sistema deciderà in base a quanto segue:

  • Se sul dispositivo sono possibili effetti tattili (se in questo caso ha un Taptic Engine)
  • Se l'app può registrare l'audio (non si generano aptici durante la registrazione per evitare interferenze indesiderate)
  • Se gli aptici sono abilitati nelle Impostazioni di sistema.

Pertanto, il sistema ignorerà silenziosamente la tua richiesta di aptico se non è possibile. Se ciò è dovuto a un dispositivo non supportato, puoi provare questo:

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
    }

Sostituisci i commenti nel switch-case dichiarazioni e questo codice di generazione aptico sarà portatile per altri dispositivi iOS. Genererà il più alto livello possibile di aptico.

Nota B

  • A causa del fatto che la generazione di aptici è un'attività di livello hardware , potrebbe esserci latenza tra quando si chiama il codice di generazione aptica e quando effettivamente accade. Per questo motivo, le API di Taptic Engine hanno tutte un prepare()metodo per metterlo in stato di prontezza. Usando il tuo Game Over esempio: potresti sapere che il gioco sta per finire, se l'utente ha HP molto bassi o un mostro pericoloso è vicino a lui.
  • Se non si genera un aptico entro pochi secondi, Taptic Engine tornerà in uno stato di inattività (per risparmiare la batteria)


In questo caso, la preparazione del Taptic Engine creerebbe un'esperienza di qualità superiore e più reattiva.

Ad esempio, supponiamo che la tua app utilizzi un riconoscimento dei gesti di panoramica per cambiare la parte del mondo visibile. Volete generare un aptico quando l'utente "guarda" a 360 gradi. Ecco come è possibile utilizzare 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

} 

Ricordati di farlo import UIKit!
Benj,

Non vuoi creare una nuova istanza hapticall'interno di questo metodo. Non stai chiamando impactOccuredla stessa istanza che chiami prepare.
rmaddy

5

E se stai usando il framework Xamarin (monotouch), chiama semplicemente

SystemSound.Vibrate.PlayAlertSound()

5

Nei miei viaggi ho scoperto che se provi una delle seguenti operazioni mentre stai registrando l'audio, il dispositivo non vibrerà anche se è abilitato.

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

Il mio metodo è stato chiamato in un momento specifico nella misurazione dei movimenti dei dispositivi. Ho dovuto interrompere la registrazione e quindi riavviarlo dopo che si era verificata la vibrazione.

Sembrava così.

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

recorder è un'istanza di AVRecorder.

Spero che questo aiuti gli altri che hanno avuto lo stesso problema prima.


4

In iOS 10 e su iPhone più recenti, puoi anche utilizzare l'API aptica. Questo feedback tattile è più morbido dell'API AudioToolbox.

Per il tuo scenario GAME OVER, dovrebbe essere adatto un forte feedback sull'impatto dell'interfaccia utente.

UIImpactFeedbackGenerator(style: .heavy).impactOccurred()

È possibile utilizzare gli altri stili di feedback tattili .


1

In Swift:

import AVFoundation
...
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))

0

Nel mio caso stavo usando AVCaptureSession. AudioToolbox era in fase di costruzione del progetto ed è stato importato ma non ha ancora funzionato. Per farlo funzionare ho interrotto la sessione prima delle vibrazioni e ho continuato dopo.

#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];
}

-5

Puoi usare

1) AudioServicesPlayAlertSound (kSystemSoundID_Vibrate);

per iPhone e alcuni iPod più recenti.

2) AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);

per iPad.


3
iPod touch e iPad non possono vibrare.
DDPWNAGE,

1
su un dispositivo senza capacità di vibrazione (come iPod Touch) questo non farà nulla
Lal Krishna,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.