Search code examples
titaniumappcelerator-titaniumtitanium-alloyappcelerator-alloy

Titanium Alloy - 'Global' Listener


I have multiple windows that 'require' livebar so that the entire bar persists over all windows. However, whenever the 'change' function is called, it works and logs, however my $.livebar_datalbl.text fails with the following error: "undefined is not an object (evaluating '$.livebar_datalbl.text = 'State: ' + e.description + ' (' + e.state + ')'')"

Am I structuring the code incorrectly or missing something?

index.js

(function constructor() {
    audioPlayer = Ti.Media.createAudioPlayer({
        url: 'https://allthingsaudio.wikispaces.com/file/view/Shuffle%20for%20K.M.mp3/139190697/Shuffle%20for%20K.M.mp3',
        allowBackground: true
    });

    audioPlayer.addEventListener('progress', function(e) {
        Ti.API.info('Time Played: ' + Math.round(e.progress) + ' milliseconds');
    });

    audioPlayer.addEventListener('change', function(e) {
        $.livebar_datalbl.text = 'State: ' + e.description + ' (' + e.state + ')';
        Ti.API.info('State: ' + e.description + ' (' + e.state + ')');
    });

    window = Alloy.createController('listen').getView();
    window.open();
})();

livebar.xml

<Alloy>
    <View class="livebar">
        <View class="livebar_livelblcontainer">
            <Label class="livebar_livelbl">LIVE</Label>
        </View>
        <Label class="livebar_datalbl" id="livebar_datalbl">HELLO WORLD</Label>
        <ImageView id="livebar_playpausebtn" class="livebar_playpausebtn"/>
    </View>
</Alloy>

livebar.js

$.livebar_playpausebtn.addEventListener('click', function(event) {
    if (audioPlayer.playing || audioPlayer.paused) {
        audioPlayer.stop();
        if (Ti.Platform.name === 'android')
        {
            audioPlayer.release();
        }
    } else {
        audioPlayer.start();
    }
});

audioPlayer.addEventListener('progress', function(e) {
    Ti.API.info('Time Played: ' + Math.round(e.progress) + ' milliseconds');
});

audioPlayer.addEventListener('change', function(e) {
    $.livebar_datalbl.text = 'State: ' + e.description + ' (' + e.state + ')';
    Ti.API.info('State: ' + e.description + ' (' + e.state + ')');
});

Solution

  • The audioPlayer.addEventListener event will only listen to events in the controller that you have created the audioPlayer in, in this case index.js. In your example the audioPlayer.addEventListener events in livebar.js have no effect as there is no audioPlayer to add event to.

    If you would like to have the audioplayer in index.js and then have the livebar be updated and still keep the livebar in its own view+controller you will need to fire events across the controllers. To do this you can make use of Ti.App.fireEvent

    You can read more here - Search for the "Application-Level Events" Section

    http://docs.appcelerator.com/platform/latest/#!/guide/Event_Handling

    You could do something like below.

    Remember to be careful with App wide event listeners, you should always remove those when you are done with them via the function below

    Ti.App.removeEventListener("eventlistenername", eventfunctionname);
    

    index.js

    (function constructor() {
        audioPlayer = Ti.Media.createAudioPlayer({
            url: 'https://allthingsaudio.wikispaces.com/file/view/Shuffle%20for%20K.M.mp3/139190697/Shuffle%20for%20K.M.mp3',
            allowBackground: true
        });
    
        audioPlayer.addEventListener('progress', function(e) {
            Ti.API.info('Time Played: ' + Math.round(e.progress) + ' milliseconds');
        });
    
        audioPlayer.addEventListener('change', function(e) {
    
            // set livebareText
            var livebareText = 'State: ' + e.description + ' (' + e.state + ')';
    
            // fire app wide event
            Ti.App.fireEvent("app:updateLivebar",livebareText);
    
            Ti.API.info('State: ' + e.description + ' (' + e.state + ')');
        });
    
        window = Alloy.createController('listen').getView();
        window.open();
    })();
    

    livebar.js

    $.livebar_playpausebtn.addEventListener('click', function(event) {
        if (audioPlayer.playing || audioPlayer.paused) {
            audioPlayer.stop();
            if (Ti.Platform.name === 'android')
            {
                audioPlayer.release();
            }
        } else {
            audioPlayer.start();
        }
    });
    
    // Add App eventlistener to listen for updateSingleProgessBar
    Ti.App.addEventListener("app:updateLivebar", updateLivebar);
    
    function updateLivebar(livebarText){
    
        $.livebar_datalbl.text = livebarText;
        Ti.API.info('State: ' + e.description + ' (' + e.state + ')');
    
    }