Haptics don't play in background when bluetooth headphones are connected to Apple Watch - bluetooth

I have a watchOS3 workout app that uses haptic notifications. It setup correctly to run a workout session and haptics work when running in the background. However, if bluetooth headphones are connected to the apple watch, then you only get the haptic vibration OR the audio chime for the haptic, depending on whether the app is currently showing on the watch face or running in background.
Here's how I'm playing the haptic:
WKInterfaceDevice.current().play(.notification)
Here are the details:
Apple Watch Nike+ Unpaired to Headphones: Haptic and chime sound activate regardless of whether the watch face is on or off. Chime sound is loud and clear.
Apple Watch Nike+ Paired to Bluetooth Headphones:
Haptic only active if watch face is on, audio chime is off. Audio chime is on when watch face is off, haptic is off. Chime sound is loud and clear.
I tested the app pairing the Apple Watch separately with the Platronic Backbeat Go 2 (released 7/2013) and the Bose QuietControl 30 (released 10/2016). The results were the same.
Anyone know if this is a limitation of watchOS 3, a bug, or is there something else I need to be doing?
Thanks,
Jeff

There's another factor to consider, which is whether the main Watch mute switch is on or off.
I found the following to be a suitable workaround.
When you want your audio/haptic to be noticed while music is playing on Bluetooth Headphones, have this AVAudioSession category set:
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .duckOthers)
Then, when you're done with your audio/haptic, reset the AVAudioSession back to:
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .mixWithOthers)
I have this helper class to help manage the states:
import AVFoundation
enum AudioPlaybackState {
case playback
case playbackDuckOthers
}
class AVAudio {
private init() {} // strictly a helper class
static func setAudioState(_ state: AudioPlaybackState) {
DispatchQueue.main.async {
do {
deactivateAudioSession()
switch state {
case .playback:
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .mixWithOthers)
case .playbackDuckOthers:
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .duckOthers)
}
activateAudioSession()
} catch {}
}
}
static func deactivateAudioSession() {
activateAudioSession(false)
}
private static func activateAudioSession(_ value: Bool=true) {
do {
try AVAudioSession.sharedInstance().setActive(value)
} catch {}
}
}
Then, I can switch quickly by: AVAudio.setAudioState(.playbackDuckOthers)

The behavior documented in the question is the the way its supposed to be, according to Apple. The given reason is because of the delay between the haptic tap and the haptic audio when using bluetooth headphones. I'm hoping this behavior changes in the future...

Related

Scanner (Ivanti) VELOCITY ver. 2.1.8, adding an error beep while scan an object, which is not counted in store/warehouse

community!
I use ZEBRA MC3300/android 8.1
I would really appreciate if you'll help me with one question.
The main reason I want to do it is to reduce amount of human error possibly can happen.
When VELOCITY app is on and a worker scans a barcode, there is usually plays a beep sound.
But the problem is that if a worker scans wrong barcode or an object, that is not counted in store, usually the same sound plays.
So I tried to edit this via console.
so, basically, the sound I've added works fine, but an error beep isn't playing when I try to scan any random(not our) object's barcode.
Is there a solution for my problem?
Sorry if my code looks too silly, I'm just trying to improve my workspace :(
Thanks in advance!
function replaceBeep(beepType,soundFile) {
function onBeep(event) {
if(event.type == beepType)
{
Device.beepPlayFile(soundFile);
event.eventHandled = true;
}
}
WLEvent.on("Beep", onBeep);
Device.errorBeep(1000, 300, 50, 0.5);
}
WLEvent.registerScope("session",replaceBeep,null,["2","error.wav"]);`
expecting to play separate beep sounds for wrong and right scan.

Getting a sound trigger to work

I don't understand why my sound trigger is not working. I have created a GameObject and added an Audio Source to it (on Audio Source I have the Play On Wake and Loop checked. Then I added a Sphere Collider (I have the Is Trigger checked). Finally I added my script and added the sound clips into the inspector. Unity also says that: "There are 2 audio listeners in the scene." I have pretty much unchecked all the audio listeners and it still says it, what am I doing wrong?
Here is a look at my code:
#pragma strict
var WalkAudio:AudioClip;
var OutCry:AudioClip;
function Update (){
var Audio= gameObject.GetComponent(AudioSource);
if(Input.GetButton("Horizontal") || Input.GetButton("Vertical"))
{
Audio.Play();
}
else
{
Audio.Pause();
}
}
function OnControllerColliderHit (hit : ControllerColliderHit)
{
var Audio= gameObject.GetComponent(AudioSource);
if (hit.gameObject.tag == "templeFloor")
{
var groundType = 1;
print("Temple");
Audio.clip=OutCry;
}
else{
Audio.clip=WalkAudio;
}
}
As you said:
I have pretty much unchecked all the audio listeners
The component AudioListener attached to the Main Camera must be enabled. Probably you have used LoadLevelAdditive so you have two camera and two AudioListener components, one on each of them. Please make sure this additive camera and any other gameObject should have this component disabled.
Also at runtime, you can search which component(s) have AudioListener component attached using this in the Hierarchy window search bar.
t:AudioListener
This should help you out. Also double check using Debug.Log that OnControllerColliderHit function calls and Audio.clip is not null after assignment. Also is it necessary to play sound in Update ?
Also, you should move this line from Update to Start function instead, due to performance cost:
var Audio= gameObject.GetComponent(AudioSource);
and use this Audio variable throughout your script.

IMFMediaPlayer hangs during SetSourceFromByteStream

Background: I'm coding a metro-styled app for Win8. I need to be able to play music-file. Because of quality and space requirements we're using encoded audio (mp3/ogg).
I'm using XAudio2 to play sound effects (.wav files), but since I couldn't figure out a way to play encoded audio with it, I decided to play the music files with Media Foundation (IMFMediaPlayer interface).
I downloaded metro apps sample, and found out that the Media Engine Native C++ video playback sample was closest to what I needed.
Now that my app has MediaPlayer playing musics, I ran into a problem. If the device running the app is slow enough, MediaPlayer hangs. When I'm running the release-version of the app on my device, it's fine and I can hear the music just fine. But when I attach the debugger or run it on a slower device, it hangs when I'm setting bytestream for the MediaPlayer to play.
Here's some code, you'll find it pretty similiar to the sample:
StorageFolder^ installedLocation = Windows::ApplicationModel::Package::Current->InstalledLocation;
m_pickFileTask = Concurrency::task<StorageFile^>(installedLocation->GetFileAsync(filename)), m_tcs.get_token());
auto player = this;
m_pickFileTask.then([player](StorageFile^ fileHandle)
{
player->SetURL(fileHandle->Path);
Concurrency::task<IRandomAccessStream^> fOpenStreamTask = Concurrency::task<IRandomAccessStream^> (fileHandle->OpenAsync(Windows::Storage::FileAccessMode::Read));
fOpenStreamTask.then([player](IRandomAccessStream^ streamHandle)
{
MEDIA::ThrowIfFailed(
player->m_spMediaEngine->Pause()
);
MEDIA::GetMediaError(player->m_spMediaEngine);
player->SetBytestream(streamHandle);
if (player->m_spMediaEngine)
{
MEDIA::ThrowIfFailed(
player->m_spEngineEx->Play()
);
MEDIA::GetMediaError(player->m_spMediaEngine);
}
}
);
}
);
And here's the SetBytestream method:
SetBytestream(IRandomAccessStream^ streamHandle)
{
if(m_spMFByteStream != nullptr)
{
m_spMFByteStream->Close();
m_spMFByteStream = nullptr;
}
MEDIA::ThrowIfFailed(
MFCreateMFByteStreamOnStreamEx((IUnknown*)streamHandle, &m_spMFByteStream)
);
MEDIA::ThrowIfFailed(
m_spEngineEx->SetSourceFromByteStream(m_spMFByteStream.Get(), m_bstrURL)
);
MEDIA::GetMediaError(m_spEngineEx);
return;
}
The line where it hangs is:
m_spEngineEx->SetSourceFromByteStream(m_spMFByteStream.Get(), m_bstrURL)
When I'm debugging the app, I can press pause and see the stack. Well, not much of it, but atleast I can see it that it's indefinitely at
ntdll.dll!77b7f4dc()
Any ideas why my app would hang in such a way?
(OPTIONAL: If you know a better way to play mp3/ogg in a c++ metro-styled app, let me know)
Could not figure out why this is happening, but I managed to code a work-a-round:
IMFSourceReader can be used to decode MP3s and feed bytes into XAudio2SourceVoice.
XAudio2 audio stream effect sample contains good example how to do this.

Notification sound not playing in J2ME

I am working on a J2ME application.
I am using Nokia 6131 NFC phone. I am using NetBeans IDE.
I have 4 forms and I am playing some notification sounds for the user while filling the form.
The problem is sound goes off suddenly after 3 to 4 min and the only solution is to exit the application and again open it.
My Code
public void playSoundOK()
{
try
{
InputStream is = getClass().getResourceAsStream("/OK.wav");
Player player = Manager.createPlayer(is,"audio/X-wav");
player.realize();
player.prefetch();
player.start();
}
catch(Exception e)
{
e.printStackTrace();
}
}
Exception
at com.nokia.mid.impl.isa.mmedia.audio.AudioOutImpl.openSession(AudioOutImpl.java:206)
at com.nokia.mid.impl.isa.mmedia.MediaOut.openDataSession(MediaOut.java:282)
at com.nokia.mid.impl.isa.mmedia.MediaPlayer.doPrefetch(MediaPlayer.java:155)
at com.nokia.mid.impl.isa.amms.audio.AdvancedSampledPlayer.doPrefetch(+4)
at com.nokia.mid.impl.isa.mmedia.BasicPlayer.prefetch(BasicPlayer.java:409)
at org.ird.epi.ui.UtilityClass.playSoundOK(UtilityClass.java:139)
at org.ird.epi.ui.EnrollmentForm.targetDetected(+695)
at javax.microedition.contactless.DiscoveryManager.notifyTargetListeners(DiscoveryManager.java : 700)
at javax.microedition.contactless.DiscoveryManager.access$1200(DiscoveryManager.java:103)
at javax.microedition.contactless.DiscoveryManager$Discoverer.notifyIndication(DiscoveryManager.java:882)
at com.nokia.mid.impl.isa.io.protocol.external.nfc.isi.NFCConnectionHandler$IndicationNotifier.run(+67) javax.microedition.media.MediaException: AUD
I would advise you to split NFC and audio playback into 2 different threads.
It is typically a bad idea to call a method that should take some time to complete (like prefetch) from inside an API callback (like targetDetected) because it makes you rely on a particularly robust kind of internal threading model that may not actually exist in your phone's implementation of MIDP.
You should have one thread whose sole purpose is to play the sounds that your application can emit. Use the NFC callback to send a non-blocking command to play a sound (typically using synchronized access to a queue of commands). The audio playback thread can decide to ignore commands if they were issued at a time when it was busy playing a sound (no point in notifying the users of multiple simultaneous NFC contacts)
You should close your player. Add the following code to your method:
PlayerListener listener = new PlayerListener() {
public void playerUpdate(Player player, String event, Object eventData) {
if (PlayerListener.END_OF_MEDIA.equals(event)) {
player.close();
}
}
};
player.addPlayerListener(listener);

Detecting Vibration on a Table with the iPhone

is it possible to detect vibration on the iPhone? I'm trying to figure out how to detect when the user smacks a desk or table when the phone is sitting on it. I remember reading somewhere you could detect a smack on a wooden table using the mic and AVFoundation. Any ideas?
Thanks
if you go down the microphone route, something like this might do the trick:
//somewhere during setup call this line
[anAVAudioRecorder setMeteringEnabled:YES];
//then in a method used to poll the audioMeter
[anAVAudioRecorder updateMeters];
averagePower = [anAVAudioRecorder averagePowerForChannel:0];
if (averagePower > threshold ) {
[musicPlayerClass play];
}

Resources