Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-1608] Android: Audio not stopped on incoming call

GitHub Issuen/a
TypeBug
PriorityMedium
StatusClosed
ResolutionInvalid
Resolution Date2013-07-22T17:55:33.000+0000
Affected Version/sn/a
Fix Version/s2013 Sprint 15 API, 2013 Sprint 15
ComponentsAndroid
Labelsandroid, audioplayer, interrupt, ios, ipass1, supportTeam
ReporterAndrew Heebner
AssigneePing Wang
Created2011-04-15T02:57:15.000+0000
Updated2017-03-29T16:05:08.000+0000

Description

Issue

createAudioPlayer() do not stop audio playback on an incoming. No events actually passed through these objects in order to check for calls.

Target environment

TiSDK 3.1.1.GA & new HTC One/Android 4.1.2

Sample

To reproduce run snippet, start audio playback then call to phone.
var win = Titanium.UI.createWindow({  
    title:'Audio Test',
    backgroundColor:'#fff',
    layout: 'vertical'
});

var startStopButton = Titanium.UI.createButton({
    title:'Start/Stop Streaming',
    top:10,
    width:200,
    height:40
});

var pauseResumeButton = Titanium.UI.createButton({
    title:'Pause/Resume Streaming',
    top:10,
    width:200,
    height:40,
    enabled:false
});

win.add(startStopButton);
win.add(pauseResumeButton);

// allowBackground: true on Android allows the 
// player to keep playing when the app is in the 
// background. 
var audioUrl = 'http://broadcast.infomaniak.net:80/energyzuerich-high.mp3';
var audioPlayer = Ti.Media.createAudioPlayer({ 
    url: audioUrl,
    allowBackground: true
});           
    
startStopButton.addEventListener('click',function() {
    // When paused, playing returns false.
    // If both are false, playback is stopped.
    if (audioPlayer.playing || audioPlayer.paused)
    {
        audioPlayer.stop();
        pauseResumeButton.enabled = false;
        if (Ti.Platform.name === 'android')
        { 
            audioPlayer.release();
        }   
    }
    else
    {
        audioPlayer.start();
        pauseResumeButton.enabled = true;
    }
});

pauseResumeButton.addEventListener('click', function() {
    if (audioPlayer.paused) {
        audioPlayer.start();
    }
    else {
        audioPlayer.pause();
    }
});

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

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

win.addEventListener('close',function() {
    audioPlayer.stop();
    if (Ti.Platform.osname === 'android')
    { 
        audioPlayer.release();
    }
});

win.open();

Attachments

FileDateSize
Razr_2.3.5_AudioPlayer_CallIncoming.txt2013-07-01T20:25:21.000+0000548291

Comments

  1. Stephen Tramer 2011-04-15

    May actually be valid; not necessarily a call interrupt (which we do check for, I believe, and which users can handle). Would have to be fired on the media module.

    Tagging for both iOS and Android, though this was originally filed for Android only.

  2. Gerry Cardinal III 2011-04-15

    On iOS, it does not look like the AudioStreamerCUR is currently listening for interruptions:

       #ifdef TARGET_OS_IPHONE         
       //
       // MyAudioSessionInterruptionListener
       //
       // Invoked if the audio session is interrupted (like when the phone rings)
       //
       // TODO: Need to add this into the interruption framework, it's a bug!
       void MyAudioSessionInterruptionListenerCUR(void *inClientData, UInt32 inInterruptionState)
       {
           AudioStreamerCUR* streamer = (AudioStreamerCUR *)inClientData;
           [streamer handleInterruptionChangeToState:inInterruptionState];
       }
       #endif
       
  3. Junaid Younus 2012-08-20

    No test case, ticket marked as invalid.
  4. Neeraj Gupta 2012-08-20

    We should be able to put together a simple test case based on the description here.
  5. Rahul Dhingra 2013-06-09

    Audio streaming apps require background streaming and with the incoming call event not automatically handled on the appcelerator android audioplayer, it leaves our appcelerator app with playing a stream while a user is having a telephonic conversation. Request to change priority of this ticket from trivial to higher priority and a fix implemented. Please do suggest if you need code examples, but this can typically be replicated in kitchensink itself with a remote stream / shoutcast stream and the audio player.
  6. Rahul Dhingra 2013-06-16

    Hi all, Any updates? Can you atleast suggest a work around for now? I have exhausted all attempts with broadcast receivers, android modules, etc. - Rahul
  7. Rahul Dhingra 2013-06-23

    Hi all, Anyone looking into this? Would be great if I could get a lead in the right direction for a work around in the meanwhile... - Rahul
  8. Ping Wang 2013-07-19

    If the audio is created with {allowBackground: false}, it will stop on incoming call. Because setting allowBackground to false means the audio should stop playing when its activity is paused. Please see our [doc](http://docs.appcelerator.com/titanium/latest/#!/api/Titanium.Media.Sound-property-allowBackground).
  9. Joel Hulen 2013-07-22

    I don't see this request as invalid, because the requirement to set allowBackground to true is valid in most audio-based apps I've developed. Most people don't want to keep the application in the foreground while listening to music/streaming audio for long periods of time. To support this, you must have the allowBackground set to true, then you run across the issue of the audio not automatically pausing when a call comes in. Please re-open this support ticket to address this issue for audio applications that require background playback.
  10. Ping Wang 2013-07-22

    The developers can use [BroadcastReceiver](http://docs.appcelerator.com/titanium/latest/#!/api/Titanium.Android.BroadcastReceiver) to get the phone state. But right now, we don't expose the intent constant [ACTION_PHONE_STATE_CHANGED](http://developer.android.com/reference/android/telephony/TelephonyManager.html#ACTION_PHONE_STATE_CHANGED). Will file a feature request for that. For now, the developers can use the workaround attached below:
        var win = Titanium.UI.createWindow({  
            title:'Audio Test',
            backgroundColor:'#fff',
            layout: 'vertical'
        });
         
        var startStopButton = Titanium.UI.createButton({
            title:'Start/Stop Streaming',
            top:10,
            width:200,
            //height:40
        });
         
        var pauseResumeButton = Titanium.UI.createButton({
            title:'Pause/Resume Streaming',
            top:10,
            width:200,
            //height:40,
            enabled:false
        });
         
        win.add(startStopButton);
        win.add(pauseResumeButton);
         
        // allowBackground: true on Android allows the 
        // player to keep playing when the app is in the 
        // background. 
        var audioUrl = 'http://broadcast.infomaniak.net:80/energyzuerich-high.mp3';
        var audioPlayer = Ti.Media.createAudioPlayer({ 
            url: audioUrl,
            allowBackground: true
        });           
             
        startStopButton.addEventListener('click',function() {
            // When paused, playing returns false.
            // If both are false, playback is stopped.
            if (audioPlayer.playing || audioPlayer.paused)
            {
                audioPlayer.stop();
                pauseResumeButton.enabled = false;
                if (Ti.Platform.name === 'android')
                { 
                    audioPlayer.release();
                }   
            }
            else
            {
                audioPlayer.start();
                pauseResumeButton.enabled = true;
            }
        });
         
        pauseResumeButton.addEventListener('click', function() {
            if (audioPlayer.paused) {
                audioPlayer.start();
            }
            else {
                audioPlayer.pause();
            }
        });
         
        audioPlayer.addEventListener('progress',function(e) {
            Ti.API.info('Time Played: ' + Math.round(e.progress) + ' milliseconds');
        });
         
        audioPlayer.addEventListener('change',function(e)
        {
            Ti.API.info('State: ' + e.description + ' (' + e.state + ')');
        });
         
        win.addEventListener('close',function() {
            audioPlayer.stop();
            if (Ti.Platform.osname === 'android')
            { 
                audioPlayer.release();
            }
        });
        
        var bc = Ti.Android.createBroadcastReceiver({
        	onReceived : function(e) {
        		Ti.API.info('****************** Handling broadcast: ');
        		if (e.intent) {
        			var state = e.intent.getStringExtra("state");
        			Ti.API.info("phone state: " + state);
        			if (state === "RINGING") {
        				// Incoming call. Pause the audio.
        				Ti.API.info("RINGING");
        				audioPlayer.pause()
        			}
        			if (state === "OFFHOOK") {
        				// A call is dialing, active or on hold
        				Ti.API.info("OFFHOOK");
        			}
        			if (state === "IDLE") {
        				// Not in call. Resume the audio.
        				Ti.API.info("IDLE");
        				audioPlayer.start()
        			}
        		}
        	}
        }); 
        
        Ti.Android.registerBroadcastReceiver(bc, ["android.intent.action.PHONE_STATE"]);
         
        win.open();
        
    In order to get the phone state, the READ_PHONE_STATE permission is required. So please add the permission to the tiapp.xml:
        <android xmlns:android="http://schemas.android.com/apk/res/android">
                <manifest>
                    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
                </manifest>
            </android>
        
  11. Lee Morris 2017-03-29

    Closing ticket as invalid.

JSON Source