Respostas:
Do " Tutorial do iPhone: melhor maneira de verificar os recursos dos dispositivos iOS ":
Existem duas funções aparentemente semelhantes que usam um parâmetro kSystemSoundID_Vibrate
:
1) AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
2) AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
Ambas as funções vibram o iPhone. Porém, quando você usa a primeira função em dispositivos que não suportam vibração, ele emite um sinal sonoro. A segunda função, por outro lado, não faz nada em dispositivos não suportados. Portanto, se você vibrar o dispositivo continuamente, como alerta, o senso comum diz, use a função 2.
Primeiro, adicione a estrutura AudioToolbox AudioToolbox.framework
ao seu destino em Fases de construção.
Em seguida, importe este arquivo de cabeçalho:
#import <AudioToolbox/AudioServices.h>
AudioServicesPlayAlertSound(UInt32(kSystemSoundID_Vibrate))
(pelo menos a partir da versão beta 2)
AudioToolbox agora apresenta a kSystemSoundID_Vibrate
como um SystemSoundID
tipo, de modo que o código é:
import AudioToolbox.AudioServices
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate)
Em vez de ter que passar pela etapa de elenco extra
(Adereços para @Dov)
E aqui está como você faz isso no Swift (caso você tenha o mesmo problema que eu)
Link contra AudioToolbox.framework
(Vá para o seu projeto, selecione seu destino, crie fases, Vincule o Binário às Bibliotecas, adicione a biblioteca)
Depois de concluído:
import AudioToolbox.AudioServices
// Use either of these
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
AudioServicesPlayAlertSound(SystemSoundID(kSystemSoundID_Vibrate))
A coisa brega é que SystemSoundID
é basicamente um typealias
(fantasia rápida typedef
) para um UInt32
, e o kSystemSoundID_Vibrate
é um regular Int
. O compilador fornece um erro ao tentar converter de Int
paraUInt32
, mas o erro é exibido como "Não é possível converter para SystemSoundID", o que é confuso. Por que a maçã não a transformou em um enum Swift está além de mim.
@ aponomarenko entra em detalhes, minha resposta é apenas para os Swifters por aí.
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
e compilado bem
Uma maneira simples de fazer isso é com os Serviços de áudio:
#import <AudioToolbox/AudioToolbox.h>
...
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
Eu tive um grande problema com isso para dispositivos que tinham a vibração desativada de alguma maneira, mas precisávamos que funcionasse independentemente, porque é fundamental para o funcionamento do aplicativo e, como é apenas um número inteiro para uma chamada de método documentada, ele passará validação. Então, eu tentei alguns sons que estavam fora dos bem documentados aqui: TUNER88 / iOSSystemSoundsLibrary
Tropecei em 1352, que está funcionando independentemente da opção silenciosa ou das configurações do 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);
}
}
Nota importante: Alerta de descontinuação futura.
No iOS 9.0 , a API funciona com a descrição de:
AudioServicesPlaySystemSound(inSystemSoundID: SystemSoundID)
AudioServicesPlayAlertSound(inSystemSoundID: SystemSoundID)
inclui a seguinte nota:
This function will be deprecated in a future release.
Use AudioServicesPlayAlertSoundWithCompletion or
AudioServicesPlaySystemSoundWithCompletion instead.
O caminho certo a seguir será usar qualquer um destes dois:
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)
}
lembrar de
import AVFoundation
Para um iPhone 7/7 Plus ou mais recente, use essas três APIs de feedback tátil.
let generator = UINotificationFeedbackGenerator()
generator.notificationOccured(style: .error)
Estilos disponíveis são .error
, .success
e .warning
. Cada um tem sua própria sensação distinta.
Dos documentos :
Uma
UIFeedbackGenerator
subclasse concreta que cria hápticos para comunicar sucessos, falhas e avisos.
let generator = UIImpactFeedbackGenerator(style: .medium)
generator.impactOccured()
Estilos disponíveis são .heavy
, .medium
e .light
. São vibrações simples com graus variados de "dureza".
Dos documentos :
Uma
UIFeedbackGenerator
subclasse de concreto que cria hápticos para simular impactos físicos
let generator = UISelectionFeedbackGenerator()
generator.selectionChanged()
Esse é o menos perceptível de todos os hápticos e, portanto, é o mais adequado para quando os hápticos não devem assumir a experiência do aplicativo.
Dos documentos :
Uma
UIFeedbackGenerator
subclasse concreta que cria hápticos para indicar uma mudança na seleção.
Vale lembrar algumas coisas ao usar essas APIs.
Na verdade, você não cria o háptico. Você solicita que o sistema gere um haptic. O sistema decidirá com base no abaixo:
Portanto, o sistema ignorará silenciosamente sua solicitação de um háptico, se não for possível. Se isso ocorre devido a um dispositivo não suportado, você pode tentar o seguinte:
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
}
Substitua os comentários no switch
-case
instruções e esse código de geração tátil será portátil para outros dispositivos iOS. Gerará o nível mais alto possível de háptico.
prepare()
método, para colocá-lo em um estado de prontidão. Usando o exemplo de Game Over: você pode saber que o jogo está prestes a terminar, porque o usuário tem um HP muito baixo ou um monstro perigoso está perto deles.
Nesse caso, a preparação do Taptic Engine criaria uma experiência mais responsiva e de maior qualidade.
Por exemplo, digamos que seu aplicativo use um reconhecedor de gestos de panorâmica para alterar a parte do mundo visível. Você deseja gerar um háptico quando o usuário "olhar" em torno de 360 graus. Aqui está como você pode 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
}
import UIKit
!
haptic
dentro deste método. Você não está chamando impactOccured
na mesma instância que chama prepare
.
Nas minhas viagens, descobri que, se você tentar qualquer um dos seguintes itens enquanto estiver gravando áudio, o dispositivo não vibrará, mesmo se estiver ativado.
1) AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
2) AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
Meu método foi chamado em um momento específico na medição dos movimentos do dispositivo. Eu tive que parar a gravação e depois reiniciá-la após a vibração.
Parecia assim.
-(void)vibrate {
[recorder stop];
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
[recorder start];
}
recorder
é uma instância do AVRecorder.
Espero que isso ajude outras pessoas que tiveram o mesmo problema antes.
No iOS 10 e em iPhones mais novos, você também pode usar a API háptica. Esse feedback tátil é mais suave que a API AudioToolbox.
Para o seu cenário GAME OVER, um feedback de impacto na interface do usuário pesado deve ser adequado.
UIImpactFeedbackGenerator(style: .heavy).impactOccurred()
Você pode usar os outros estilos de feedback tátil .
No meu caso, eu estava usando o AVCaptureSession. O AudioToolbox estava nas fases de construção do projeto e foi importado, mas ainda não funcionou. Para fazer funcionar, parei a sessão antes da vibração e continuei depois.
#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];
}
Você pode usar
1) AudioServicesPlayAlertSound (kSystemSoundID_Vibrate);
para iPhone e alguns iPods mais novos.
2) AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
para iPads.