Sprawianie, że iPhone wibruje


228

Jak iPhone może raz ustawić wibrację?

Na przykład, gdy gracz traci życie lub gra się kończy, iPhone powinien wibrować.


9
Gest wstrząsania jest zupełnie inny niż wibracja. Jeden jest inicjowany przez człowieka, jeden inicjowany przez urządzenie.
Eiko

Odpowiedzi:


404

Z „ Samouczka iPhone'a: ​​lepszy sposób na sprawdzenie możliwości urządzeń iOS ”:

Istnieją dwie pozornie podobne funkcje, które przyjmują parametr kSystemSoundID_Vibrate:

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

Obie funkcje wibrują iPhone'a. Ale kiedy używasz pierwszej funkcji na urządzeniach, które nie obsługują wibracji, odtwarza dźwięk. Z drugiej strony druga funkcja nie działa na nieobsługiwanych urządzeniach. Jeśli więc zamierzasz ciągle wibrować urządzeniem, jako ostrzeżenie, zdrowy rozsądek mówi, użyj funkcji 2.

Najpierw dodaj strukturę AudioToolbox AudioToolbox.frameworkdo celu w Fazach kompilacji.

Następnie zaimportuj ten plik nagłówka:

#import <AudioToolbox/AudioServices.h>

3
#import <Cocoa / Cocoa.h> nie jest wymagany.
Raptor

10
Czy istnieje sposób na skrócenie czasu wibracji do mniej niż 1 sekundy?
George Asda,

11
Chciałbym dodać, że jeśli wibracja jest wyłączona w Ustawieniach iOS, użytkownik nie dostanie wibracji, nawet jeśli użyjesz tych poleceń.
Denis Kutlubaev

7
W Swift: AudioServicesPlayAlertSound(UInt32(kSystemSoundID_Vibrate))(przynajmniej od wersji beta 2)
Sam Soffes

1
AudioServicesPlayAlertSound (kSystemSoundID_Vibrate); Poprawnie wibruj na iPhonie, ale na iPadzie nie słychać żadnego dźwięku.
Mangesh

45

Swift 2.0+

AudioToolbox przedstawia teraz kSystemSoundID_Vibratejako SystemSoundIDtyp, więc kod jest następujący:

import AudioToolbox.AudioServices

AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate)

Zamiast przechodzić przez dodatkowy etap rzucania

(Rekwizyty do @Dov)

Oryginalna odpowiedź (Swift 1.x)

Oto, jak to robisz na Swift (na wypadek, gdybyś miał takie same kłopoty jak ja)

Połącz z AudioToolbox.framework(Przejdź do projektu, wybierz cel, buduj fazy, Połącz pliki binarne z bibliotekami, dodaj tam bibliotekę)

Po zakończeniu:

import AudioToolbox.AudioServices

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

Tandetne jest to, że SystemSoundIDjest to po prostu typealias(fantazyjne szybkie typedef) dla UInt32, i kSystemSoundID_Vibratejest regularne Int. Kompilator daje błąd dla próby z obsadą Intdo UInt32, ale błąd brzmi „nie można przekonwertować do SystemSoundID”, co jest mylące. Dlaczego jabłko po prostu nie sprawiło, że szybki enum jest poza mną.

@ aponomarenko zajmuje się szczegółami, moja odpowiedź dotyczy tylko Swifterów.


Wydaje się, że zostało to naprawione w Swift 2 / iOS 9 / Xcode 7. Użyłem AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)i skompilowałem się dobrze
Dow

35

Prostym sposobem jest skorzystanie z usług audio:

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

3
#import <AudioToolbox / AudioToolbox.h> i musisz dodać AudioToolbox.framework do faz kompilacji projektu.
Michael Mangold

31

Miałem z tym duży problem w przypadku urządzeń, które w jakiś sposób wyłączały wibracje, ale potrzebowaliśmy, aby działała niezależnie, ponieważ ma to kluczowe znaczenie dla funkcjonowania naszej aplikacji, a ponieważ jest to tylko liczba całkowita w udokumentowanym wywołaniu metody, przejdzie uprawomocnienie. Więc wypróbowałem kilka dźwięków, które były poza dobrze udokumentowanymi tutaj: TUNER88 / iOSSystemSoundsLibrary

Natknąłem się na 1352, który działa niezależnie od cichego przełącznika lub ustawień urządzenia (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
Zawsze lepiej jest używać nazwanych aliasów zamiast stałych magicznych, takich jak kSystemSoundID_Vibrate zamiast 1352. Zachęcam do zaktualizowania odpowiedzi.
nalexn

3
Zgodziłbym się, że użycie tej magii 1352 nie jest idealne, ale nie mogę znaleźć innego sposobu wymuszenia wibracji, nawet gdy przełącznik wibracji jest wyłączony na urządzeniu. To chyba jedyny sposób.
marcshilling

4
Napisałem pętlę for z liczbami całkowitymi zaczynającymi się od opublikowanych stałych i zorientowałem się, która z nich spowodowała wibrację
Joel Teply

2
Mogę potwierdzić, że iPhone wibruje, nawet jeśli tryb cichy jest włączony w telefonie iPhone. Świetna odpowiedź!
vomako

2
AudioServicesPlaySystemSound (1352) nadal działa dla iPhone'ów niezależnie od pozycji cichego przełączania na styczeń 2016 r.
JustAnotherCoder

26

Ważna uwaga: Alert o przyszłej rezygnacji.

Począwszy od iOS 9.0 , opis funkcji API dla:

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

zawiera następującą notatkę:

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

Właściwą drogą będzie użycie jednego z tych dwóch:

AudioServicesPlayAlertSoundWithCompletion(kSystemSoundID_Vibrate, nil)

lub

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

Pamiętaj by import AVFoundation


brakuje wyciągu z importu
Juan Boero,

import AudioToolbox.AudioServices
Hugo Alonso

Zrobiłem to sam, tylko z AVFoundation.
Juan Boero,

W każdym razie, aby ustawić czas trwania wibracji?
Micro

Będziesz musiał połączyć kilka połączeń, użyć odstępu czasu między każdym nowym połączeniem
Hugo Alonso,

7

W przypadku telefonu iPhone 7/7 Plus lub nowszego użyj tych trzech interfejsów API interfejsu Haptic Feedback.

Dostępne interfejsy API

W przypadku powiadomień:

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

Dostępne style .error, .successi .warning. Każdy ma swój charakterystyczny charakter.
Z dokumentów :

Konkretna UIFeedbackGeneratorpodklasa, która tworzy dotykową komunikację o sukcesach, niepowodzeniach i ostrzeżeniach.

Dla prostych wibracji:

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

Dostępne style .heavy, .mediumi .light. Są to proste wibracje o różnym stopniu „twardości”.
Z dokumentów :

Konkretna UIFeedbackGeneratorpodklasa, która tworzy dotykową symulację uderzeń fizycznych

Gdy użytkownik wybrał element

let generator = UISelectionFeedbackGenerator()
generator.selectionChanged()

Jest to najmniej zauważalny ze wszystkich haptików, dlatego jest najbardziej odpowiedni, gdy haptics nie powinien przejmować funkcji aplikacji.
Z dokumentów :

Konkretna UIFeedbackGeneratorpodklasa, która tworzy dotykowe wskazujące zmianę wyboru.

Notatki

Podczas korzystania z tych interfejsów API warto pamiętać o kilku sprawach.

Nie herbata

W rzeczywistości nie tworzysz dotyku. Państwo zażądać system wygenerować dotykowych. System podejmie decyzję w oparciu o poniższe:

  • Jeśli na urządzeniu możliwe są dotykowe elementy (w tym przypadku ma silnik Taptic Engine)
  • Określa, czy aplikacja może nagrywać dźwięk (dotykowe nie generują się podczas nagrywania, aby zapobiec niepożądanym zakłóceniom)
  • Określa, czy w ustawieniach systemu włączono dotykowe.

Dlatego system po cichu zignoruje twoją prośbę o dotyk, jeśli nie jest to możliwe. Jeśli wynika to z nieobsługiwanego urządzenia, możesz spróbować:

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
    }

Zastąp komentarze w instrukcjach switch- case, a ten haptyczny kod generowania będzie przenośny na inne urządzenia z systemem iOS. Wygeneruje najwyższy możliwy poziom dotyku.

Uwaga B

  • Z uwagi na fakt, że generowanie haptiki jest zadaniem na poziomie sprzętowym , może wystąpić opóźnienie między wywołaniem kodu generowania haptic a momentem, w którym to się dzieje. Z tego powodu interfejsy API silnika Taptic Engine mają prepare()metodę ustawiania go w stan gotowości. Korzystanie z gry Przykład: Możesz wiedzieć, że gra wkrótce się zakończy, ponieważ użytkownik ma bardzo niski poziom zdrowia lub znajduje się w pobliżu niebezpieczny potwór.
  • Jeśli nie wygenerujesz haptiku w ciągu kilku sekund, silnik Taptic wróci do stanu bezczynności (w celu oszczędzania baterii)


W takim przypadku przygotowanie silnika Taptic Engine zapewniłoby lepszą jakość i czułość.

Załóżmy na przykład, że Twoja aplikacja używa rozpoznawania gestów panoramy w celu zmiany widocznej części świata. Chcesz, aby haptik generował się, gdy użytkownik „patrzy” na 360 stopni. Oto jak możesz użyć 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

} 

Pamiętaj tylko, aby import UIKit!
Benj

Nie chcesz tworzyć nowego wystąpienia haptictej metody. Nie dzwonisz impactOccuredw tej samej instancji, do której dzwonisz prepare.
rmaddy


5

Podczas moich podróży odkryłem, że jeśli spróbujesz wykonać jedną z poniższych czynności podczas nagrywania dźwięku, urządzenie nie będzie wibrować, nawet jeśli jest włączone.

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

Moja metoda została wywołana w określonym czasie przy pomiarze ruchów urządzeń. Musiałem zatrzymać nagrywanie, a następnie uruchomić je ponownie po wystąpieniu wibracji.

Tak to wyglądało.

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

recorder jest instancją AVRecorder.

Mam nadzieję, że pomoże to innym, którzy mieli wcześniej ten sam problem.


4

W iOS 10 i nowszych iPhone'ach możesz także używać haptic API. Ta dotykowa informacja zwrotna jest bardziej miękka niż API AudioToolbox.

W przypadku scenariusza GAME OVER odpowiednie informacje zwrotne dotyczące interfejsu użytkownika powinny być odpowiednie.

UIImpactFeedbackGenerator(style: .heavy).impactOccurred()

Możesz użyć innych stylów dotykowych .


1

W Swift:

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

0

W moim przypadku korzystałem z AVCaptureSession. AudioToolbox był w fazie kompilacji projektu i został zaimportowany, ale nadal nie działał. Aby to zadziałało, zatrzymałem sesję przed wibracjami i kontynuowałem po niej.

#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

Możesz użyć

1) AudioServicesPlayAlertSound (kSystemSoundID_Vibrate);

na iPhone'a i kilka nowszych iPodów.

2) AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);

na iPady.


3
iPod touch i iPad nie mogą wibrować.
DDPWNAGE,

1
na urządzeniu bez funkcji wibracji (jak iPod Touch) to nic nie da
Lal Krishna
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.