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.