1

On my PC I get a sound in chrome browser when I send a message via my smart phone (android) But on my phone I don't get a sound. I tested this with 2 laptops and it works now with those but my phone's browser does not give a beep. The goal is that I get a sound when I receive a message. The strange thing is that my phone gives a sound when I use the standard meteor example app. I mean when you create your app with meteor create you get a skeleton code and I inserted "new Audio('path to sound file').play(); into the click event. It works perfectly!

But in my app it only works sometimes and never on my mobile. I use the same audio file and have it in my public folder of the meteor app.

var msgId=0;
var old=Session.get('msgCount');

Template.berichtenlijst.messages=function(){

    if(old<Session.get('msgCount')){//there is a new message in Message collection

        old=Session.get('msgCount');

        var array=Messages.find().fetch();

        if(array.length>0&&(msgId!==array[array.length-1]._id)){
            //notify new message

            new Audio('audio.mp3').play();
        }

    }



    return Messages.find({}, { sort: { timestamp: -1 },limit:100});


}

msgId has a value, the id is from Messages.insert(..) I have debugged that and that is right. Also the SESSION variable is the right one. And with the example app I get the sound also on mobile. I have no idea what is going on. Sorry I know it might be a vague question but it is a vague problem to me.

Joris
  • 105
  • 2
  • 9

3 Answers3

2

I think a lot of mobile browsers limit your ability to play sounds that aren't in direct response to a user action.

So, you can play a sound in the callback of a click eventListener... but you can't do it at an arbitrary time (say, as a response to a websocket message).

Also: traditionally you'd want to wait to call play until the canplaythrough event has fired on the audio element, so something like this:

var audio = new Audio('audio.mp3');
audio.addEventListener('canplaythrough', function() {
  audio.play();
});
Kevin Ennis
  • 14,226
  • 2
  • 43
  • 44
  • 1
    I have a really evil work around for the whole 'will only enable audio on a user interaction EventListener restriction'. It seems in most browsers, it's a global flag which gets turned off, when you do anything audio related in a EventListener callback. So you can have a EventListener for ANY click event on the DOM which plays a dummy Audio element when volume set to 0. So after the first interaction with the DOM, all other Audio objects will make sound. – notthetup Sep 16 '14 at 07:06
  • I have also tried to trigger events but that does not help either.In mobile browsers user interaction is needed, you are right. http://stackoverflow.com/questions/10951524/play-and-replay-a-sound-on-safari-mobile-- That is something I will try later. – Joris Sep 16 '14 at 12:39
  • Very strange: android browser and desktop browser (both chrome) play sound automatically after I make a little change in a javascript file (like add a comment, no code change) (meteor starts automatically after that). But when I manually restart meteor it does not work anymore. Very vague , I have no idea what that means. Any ideas? – Joris Sep 18 '14 at 13:06
  • Sorry, not really familiar with Meteor. – Kevin Ennis Sep 18 '14 at 14:48
0

I have been successful using buzz.js (https://github.com/brentjanderson/meteor-buzz.git). I had tried using Audio before with lots of compatibility issues, whereas it might work in the most modern browsers but not in reactive settings.

The application plays sounds based on reactive events both from updating session and collections and is working fine in an android app as well as in most modern browsers. However on android I've noticed that only one sound can be played at each time (successive play attempts cancel the currently playing sound out).

Playing sound is very simple:

var audio = new buzz.sound('/sounds/warning.mp3');
audio.play();
0

This is overly difficult, would have been nice to have a "On New Data Function".

Instead, you need to spit out unique ID's for each message. Then use Jquery to scan for the last one every 1 second. Store that last ID in a client side memory, I'm just using a window variable. Then, if the last message id changes in the next second, play a sound.

But in this method, you'll get your own message sounds. So, add more complexity. Also store your userId() in client memory, and compare if the new message is from myself, or another user.

{{#each chatMessages}}

                                        <div class="chat-message left" id="chatMessage_{{_id}}">
                                            <div id="owner_id" style="display:none;">{{owner_id}}</div>
                                            <a class="message-author" href="/people/{{username}}">
                                                <img class="message-avatar" src="{{avatar}}" alt="">
                                            </a>
                                            <div class="message">
                                                <a class="message-author" href="/people/{{username}}">{{title}}</a>
                                                <span class="message-date">{{timeAgo}}</span>
                                                    <span class="message-content">
                                                    {{content}}
                                                    </span>
                                            </div>
                                        </div>

                                    {{/each}}

    // Set last message seen on client
window.chatMessage_messageId = $(".chat-message:last").attr("id");
window.chatMessage_userId = $(".chat-message:last").attr("id");

setInterval( function(){ 

    // New message?
    if(window.chatMessage_messageId != $(".chat-message:last").attr("id") ){

        // Do I own this? (no sound)
        var owner = $("#"+window.chatMessage_messageId+" #owner_id").html();
        if(owner != Meteor.userId()){
            window.chatMessage_messageId = $(".chat-message:last").attr("id");

            ringAudio = new Audio('/sounds/chat_message.mp3'); 
            ringAudio.pause();
            ringAudio.currentTime = 0;
            ringAudio.play();
        }

    }

}, 1000);
Andy
  • 966
  • 11
  • 16