AIR4:在请求麦克风访问后,如何在iOS 8(beta 5)中恢复音频?

AIR4:在请求麦克风访问后,如何在iOS 8(beta 5)中恢复音频?,ios,air,ios8,microphone,Ios,Air,Ios8,Microphone,问题:iOS 8(beta 5)在监听样本数据后会淡出我的应用程序中的所有声音输出,并且永远不会恢复它,但前提是在请求麦克风样本数据之前播放了声音 源于请求麦克风访问,但在以下两种情况下,使用iOS7在我们发布的应用程序中播放的声音与预期一致,并且关闭/重新打开应用程序的解决方案并不可行,因为麦克风录音是我们应用程序中经常出现的一部分 条件: protected var _url:String = 'audio/organfinale.mp3'; protected var _s

问题:iOS 8(beta 5)在监听样本数据后会淡出我的应用程序中的所有声音输出,并且永远不会恢复它,但前提是在请求麦克风样本数据之前播放了声音

源于请求麦克风访问,但在以下两种情况下,使用iOS7在我们发布的应用程序中播放的声音与预期一致,并且关闭/重新打开应用程序的解决方案并不可行,因为麦克风录音是我们应用程序中经常出现的一部分

条件:

    protected var _url:String = 'audio/organfinale.mp3';
    protected var _sound:Sound;
    protected var _soundChannel:SoundChannel;
    protected var _microphone:Microphone;

    public function init():void
    {
        initSound();
    }


    /** SOUND **/

    protected function initSound():void
    {
        // Set up to mimic app
        SoundMixer.audioPlaybackMode = AudioPlaybackMode.MEDIA;

        _sound = new Sound( new URLRequest( _url ) );
        _sound.addEventListener(Event.COMPLETE, onSoundLoaded );
    }

    protected function onSoundLoaded(e:Event):void
    {
        _sound.removeEventListener(Event.COMPLETE, onSoundLoaded);

        switch ( 0 )
        {
            // Will cut audio completely, prevent audio dispatch
            case 0:
                playSound();
                setTimeout( initMicrophone, 1500 );
                break;

            // Works perfectly (because no overlap between sound/microphone?)
            case 1:
                initMicrophone();
                break;
        }
    }

    protected function playSound():void
    {
        trace( 'Play sound' );

        if ( _soundChannel && _soundChannel.hasEventListener( Event.SOUND_COMPLETE ) )
                _soundChannel.removeEventListener( Event.SOUND_COMPLETE, onSoundCompleted );

        _soundChannel = _sound.play( 0 );
        _soundChannel.addEventListener( Event.SOUND_COMPLETE, onSoundCompleted, false, 0, true );
    }

    protected function onSoundCompleted( e:Event ):void
    {
        trace( "Sound complete" );
    }


    /** MICROPHONE **/

    protected function initMicrophone():void
    {
        if ( Microphone.isSupported )
        {
            // Testing pre-emptive disposal of sound that might be conflicting with microphone in iOS 8
            if ( _soundChannel )
            {
                // Tested this, but it throws an error because sound is not streaming
                // _sound.close();

                _soundChannel.removeEventListener( Event.SOUND_COMPLETE, onSoundCompleted );
                _soundChannel.stop();
                _soundChannel = null;

                // Instead the sound will be cut abruptedly, and will fail to dispatch complete event
            }

            _microphone = Microphone.getMicrophone();
            _microphone.setSilenceLevel(0);
            // _microphone.setUseEchoSuppression(true);
            // _microphone.gain = 50;
            // _microphone.rate = 44;
            _microphone.addEventListener( SampleDataEvent.SAMPLE_DATA, onSampleDataReceived, false, 0, true );
        }
        else
        {
            trace( 'Microphone is not supported!' );
        }
    }

    protected function onSampleDataReceived( e:SampleDataEvent ):void
    {
        trace( 'Sample data received' );

        _microphone.removeEventListener( SampleDataEvent.SAMPLE_DATA, onSampleDataReceived );
        _microphone = null;

        setTimeout( playSound, 1500 );
    }
  • Flex 4.6.0和AIR 4.0
  • iPad 3(MD335LL/A)
  • iOS 8(12A4345D)
  • 两个测试用例都假定已授予麦克风权限
测试用例0:

    protected var _url:String = 'audio/organfinale.mp3';
    protected var _sound:Sound;
    protected var _soundChannel:SoundChannel;
    protected var _microphone:Microphone;

    public function init():void
    {
        initSound();
    }


    /** SOUND **/

    protected function initSound():void
    {
        // Set up to mimic app
        SoundMixer.audioPlaybackMode = AudioPlaybackMode.MEDIA;

        _sound = new Sound( new URLRequest( _url ) );
        _sound.addEventListener(Event.COMPLETE, onSoundLoaded );
    }

    protected function onSoundLoaded(e:Event):void
    {
        _sound.removeEventListener(Event.COMPLETE, onSoundLoaded);

        switch ( 0 )
        {
            // Will cut audio completely, prevent audio dispatch
            case 0:
                playSound();
                setTimeout( initMicrophone, 1500 );
                break;

            // Works perfectly (because no overlap between sound/microphone?)
            case 1:
                initMicrophone();
                break;
        }
    }

    protected function playSound():void
    {
        trace( 'Play sound' );

        if ( _soundChannel && _soundChannel.hasEventListener( Event.SOUND_COMPLETE ) )
                _soundChannel.removeEventListener( Event.SOUND_COMPLETE, onSoundCompleted );

        _soundChannel = _sound.play( 0 );
        _soundChannel.addEventListener( Event.SOUND_COMPLETE, onSoundCompleted, false, 0, true );
    }

    protected function onSoundCompleted( e:Event ):void
    {
        trace( "Sound complete" );
    }


    /** MICROPHONE **/

    protected function initMicrophone():void
    {
        if ( Microphone.isSupported )
        {
            // Testing pre-emptive disposal of sound that might be conflicting with microphone in iOS 8
            if ( _soundChannel )
            {
                // Tested this, but it throws an error because sound is not streaming
                // _sound.close();

                _soundChannel.removeEventListener( Event.SOUND_COMPLETE, onSoundCompleted );
                _soundChannel.stop();
                _soundChannel = null;

                // Instead the sound will be cut abruptedly, and will fail to dispatch complete event
            }

            _microphone = Microphone.getMicrophone();
            _microphone.setSilenceLevel(0);
            // _microphone.setUseEchoSuppression(true);
            // _microphone.gain = 50;
            // _microphone.rate = 44;
            _microphone.addEventListener( SampleDataEvent.SAMPLE_DATA, onSampleDataReceived, false, 0, true );
        }
        else
        {
            trace( 'Microphone is not supported!' );
        }
    }

    protected function onSampleDataReceived( e:SampleDataEvent ):void
    {
        trace( 'Sample data received' );

        _microphone.removeEventListener( SampleDataEvent.SAMPLE_DATA, onSampleDataReceived );
        _microphone = null;

        setTimeout( playSound, 1500 );
    }
  • 播放声音
  • 停止声道
  • 音频停止
  • 连接到麦克风,接收到样本数据后移除监听器
  • 尝试播放声音
  • 没有声音输出,声音完成事件也不会触发
测试用例1:

    protected var _url:String = 'audio/organfinale.mp3';
    protected var _sound:Sound;
    protected var _soundChannel:SoundChannel;
    protected var _microphone:Microphone;

    public function init():void
    {
        initSound();
    }


    /** SOUND **/

    protected function initSound():void
    {
        // Set up to mimic app
        SoundMixer.audioPlaybackMode = AudioPlaybackMode.MEDIA;

        _sound = new Sound( new URLRequest( _url ) );
        _sound.addEventListener(Event.COMPLETE, onSoundLoaded );
    }

    protected function onSoundLoaded(e:Event):void
    {
        _sound.removeEventListener(Event.COMPLETE, onSoundLoaded);

        switch ( 0 )
        {
            // Will cut audio completely, prevent audio dispatch
            case 0:
                playSound();
                setTimeout( initMicrophone, 1500 );
                break;

            // Works perfectly (because no overlap between sound/microphone?)
            case 1:
                initMicrophone();
                break;
        }
    }

    protected function playSound():void
    {
        trace( 'Play sound' );

        if ( _soundChannel && _soundChannel.hasEventListener( Event.SOUND_COMPLETE ) )
                _soundChannel.removeEventListener( Event.SOUND_COMPLETE, onSoundCompleted );

        _soundChannel = _sound.play( 0 );
        _soundChannel.addEventListener( Event.SOUND_COMPLETE, onSoundCompleted, false, 0, true );
    }

    protected function onSoundCompleted( e:Event ):void
    {
        trace( "Sound complete" );
    }


    /** MICROPHONE **/

    protected function initMicrophone():void
    {
        if ( Microphone.isSupported )
        {
            // Testing pre-emptive disposal of sound that might be conflicting with microphone in iOS 8
            if ( _soundChannel )
            {
                // Tested this, but it throws an error because sound is not streaming
                // _sound.close();

                _soundChannel.removeEventListener( Event.SOUND_COMPLETE, onSoundCompleted );
                _soundChannel.stop();
                _soundChannel = null;

                // Instead the sound will be cut abruptedly, and will fail to dispatch complete event
            }

            _microphone = Microphone.getMicrophone();
            _microphone.setSilenceLevel(0);
            // _microphone.setUseEchoSuppression(true);
            // _microphone.gain = 50;
            // _microphone.rate = 44;
            _microphone.addEventListener( SampleDataEvent.SAMPLE_DATA, onSampleDataReceived, false, 0, true );
        }
        else
        {
            trace( 'Microphone is not supported!' );
        }
    }

    protected function onSampleDataReceived( e:SampleDataEvent ):void
    {
        trace( 'Sample data received' );

        _microphone.removeEventListener( SampleDataEvent.SAMPLE_DATA, onSampleDataReceived );
        _microphone = null;

        setTimeout( playSound, 1500 );
    }
  • 连接到麦克风,接收到样本数据后移除监听器
  • 声音播放没有问题,声音完成事件被触发
示例代码:

    protected var _url:String = 'audio/organfinale.mp3';
    protected var _sound:Sound;
    protected var _soundChannel:SoundChannel;
    protected var _microphone:Microphone;

    public function init():void
    {
        initSound();
    }


    /** SOUND **/

    protected function initSound():void
    {
        // Set up to mimic app
        SoundMixer.audioPlaybackMode = AudioPlaybackMode.MEDIA;

        _sound = new Sound( new URLRequest( _url ) );
        _sound.addEventListener(Event.COMPLETE, onSoundLoaded );
    }

    protected function onSoundLoaded(e:Event):void
    {
        _sound.removeEventListener(Event.COMPLETE, onSoundLoaded);

        switch ( 0 )
        {
            // Will cut audio completely, prevent audio dispatch
            case 0:
                playSound();
                setTimeout( initMicrophone, 1500 );
                break;

            // Works perfectly (because no overlap between sound/microphone?)
            case 1:
                initMicrophone();
                break;
        }
    }

    protected function playSound():void
    {
        trace( 'Play sound' );

        if ( _soundChannel && _soundChannel.hasEventListener( Event.SOUND_COMPLETE ) )
                _soundChannel.removeEventListener( Event.SOUND_COMPLETE, onSoundCompleted );

        _soundChannel = _sound.play( 0 );
        _soundChannel.addEventListener( Event.SOUND_COMPLETE, onSoundCompleted, false, 0, true );
    }

    protected function onSoundCompleted( e:Event ):void
    {
        trace( "Sound complete" );
    }


    /** MICROPHONE **/

    protected function initMicrophone():void
    {
        if ( Microphone.isSupported )
        {
            // Testing pre-emptive disposal of sound that might be conflicting with microphone in iOS 8
            if ( _soundChannel )
            {
                // Tested this, but it throws an error because sound is not streaming
                // _sound.close();

                _soundChannel.removeEventListener( Event.SOUND_COMPLETE, onSoundCompleted );
                _soundChannel.stop();
                _soundChannel = null;

                // Instead the sound will be cut abruptedly, and will fail to dispatch complete event
            }

            _microphone = Microphone.getMicrophone();
            _microphone.setSilenceLevel(0);
            // _microphone.setUseEchoSuppression(true);
            // _microphone.gain = 50;
            // _microphone.rate = 44;
            _microphone.addEventListener( SampleDataEvent.SAMPLE_DATA, onSampleDataReceived, false, 0, true );
        }
        else
        {
            trace( 'Microphone is not supported!' );
        }
    }

    protected function onSampleDataReceived( e:SampleDataEvent ):void
    {
        trace( 'Sample data received' );

        _microphone.removeEventListener( SampleDataEvent.SAMPLE_DATA, onSampleDataReceived );
        _microphone = null;

        setTimeout( playSound, 1500 );
    }
注:

  • 在添加麦克风侦听器之前,我停止了声道,假设这可能会导致冲突,但没有任何区别
  • 在使用Flex 4.6.0和AIR 14.0编译应用程序后,我使用相同的设备/操作系统进行了测试,但问题仍然存在
  • 相比之下,在iOS 7上测试该应用程序在这两种情况下都有效
有什么想法吗

更新1:此处已记录错误:

更新2:从AIR 15.0.0.274开始,错误已修复: