在高于 4.0 的 Android 版本中无法播放声音

Posted

技术标签:

【中文标题】在高于 4.0 的 Android 版本中无法播放声音【英文标题】:Sound not playing in Android version greater than 4.0 【发布时间】:2014-11-09 07:15:18 【问题描述】:

我正在使用以下代码在我的应用程序中播放声音。在 ICS 之前一切正常。但是在 ICS 和更新的版本上,虽然没有出现错误,但听不到声音。

编辑:请注意,以下代码由广播接收器触发。广播接收器调用异步任务。在asycn任务的后处理方法中调用如下方法。

此错误仅发生在特定的移动模型(例如 nexus )上,并且在某些模型上,用户能够播放股票操作系统附带的声音,但不能播放他​​们放在 rigtones 文件夹中的自己的声音。

我无法了解特定手机上发生的问题

错误可能是什么?

public static void playSound(final Context context, final int volume,
            Uri uri, final int stream, int maxTime, int tickTime) 
        //stopPlaying();
        /*
        if (stream < 0 || stream > 100) 
            throw new IllegalArgumentException(
                    "volume must be between 0 and 100 .Current volume "
                            + volume);
        */

        final AudioManager mAudioManager = (AudioManager) context
                .getSystemService(Context.AUDIO_SERVICE);

        int deviceLocalVolume = getDeviceVolume(volume,
                mAudioManager.getStreamMaxVolume(stream));

        Log.d(TAG,
                "device max volume = "
                        + mAudioManager.getStreamMaxVolume(stream)
                        + " for streamType " + stream);
        Log.d(TAG, "playing sound " + uri.toString()
                + " with device local volume " + deviceLocalVolume);

        final int oldVolume = mAudioManager.getStreamVolume(stream);

        // set the volume to what we want it to be. In this case it's max volume
        // for the alarm stream.
        Log.d(Constants.APP_TAG, "setting device local volume to " + deviceLocalVolume);
        mAudioManager.setStreamVolume(stream, deviceLocalVolume,
                AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);

         final MediaPlayer mediaPlayer = new MediaPlayer();
         golbalMMediaPlayer = mediaPlayer;

        try 
             final OnPreparedListener OnPreparedListener = new OnPreparedListener() 

                @Override
                public void onPrepared(final MediaPlayer mp) 
                    Log.d(TAG, "onMediaPlayercompletion listener");
                    mp.start();
                    countDownTimer.start();
                
            ;

            mediaPlayer.setDataSource(context.getApplicationContext(), uri);
            mediaPlayer.setAudiostreamType(stream);
            mediaPlayer.setLooping(false);
            mediaPlayer.setOnPreparedListener(OnPreparedListener);
            mediaPlayer.setOnCompletionListener(new OnCompletionListener() 

                @Override
                public void onCompletion(MediaPlayer mp) 
                    Log.d(Constants.APP_TAG, "Entered onCompletion listener of mediaplayer");
                    mAudioManager.setStreamVolume(stream, oldVolume,
                            AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
                    try
                    if(mediaPlayer != null && mediaPlayer.isPlaying())
                        mediaPlayer.release();
                    
                    catch(Exception ex)
                        Log.e(Constants.APP_TAG, "error on oncompletion listener" ,ex);
                    
                

            );

             CountDownTimer timer = new CountDownTimer(maxTime*1000, tickTime*1000) 

                @Override
                public void onTick(long millisUntilFinished) 
                    Log.d(TAG, "tick while playing sound ");
                

                @Override
                public void onFinish() 
                    Log.d(TAG, "timer finished");
                    stopPlaying();
                
            ;

            countDownTimer = timer;

            mediaPlayer.prepareAsync();

         catch (Exception e) 
            Log.e(TAG, "problem while playing sound", e);
         finally 

        
    

日志

:07-01 00:00:00.030: D/beephourly(9500): device max volume = 7 for streamType 5
07-01 00:00:00.030: D/beephourly(9500): playing sound content://media/internal/audio/media/166 with device local volume 7
07-01 00:00:00.030: D/beephourly(9500): setting device local volume to 7
07-01 00:00:00.080: D/beephourly(9500): vibrating with pattern = [J@428bae20
07-01 00:00:00.090: D/beephourly(9500): will show normal notification
07-01 00:00:00.100: D/beephourly(9500): notification is enabled
07-01 00:00:00.100: D/usersettings(9500): hr = 0
07-01 00:00:00.110: D/beephourly(9500): onMediaPlayercompletion listener
07-01 00:00:00.451: D/beephourly(9500): tick while playing sound 
07-01 00:00:20.460: D/beephourly(9500): timer finished
07-01 00:00:20.460: D/beephourly(9500): got request to stop playing
07-01 00:00:20.460: D/beephourly(9500): cancelling countdowntimer
07-01 00:00:20.460: D/beephourly(9500): releasing mediaplayer now

这个问题是我之前提出的问题的后续问题: sound not playing in android > icecream sandwich

【问题讨论】:

您能否识别出可以播放的声音和无法播放的声音,并告诉我您尝试播放的音频的比特率和格式以及在什么设备上播放? 不能播放的格式之一是mp3 您的代码没有明显的问题——示例应用可以在我的 Nexus 上的 NOTIFICATION 流中播放。我建议您添加一个错误侦听器,并删除您可能拥有的日志过滤器 - 有趣的日志将来自 MediaPlayer 和 NuPlayer。 【参考方案1】:

您应该请求音频焦点,即使是通知。在您的情况下,它看起来像这样:

AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

//request a transient lock on the notification stream
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_NOTIFICATION,
    AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);

if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) 
    // could not get audio focus.

我怀疑设备上运行的其他一些应用程序会给您带来请求音频焦点的问题。如果其他应用程序请求音频焦点,而您没有,则您的应用程序可能不会播放到最终流。自己请求焦点将确保没有其他进程干扰您的通知声音。虽然这是不久前引入的,但较新版本的 Android 对使用这种机制的应用程序更加敏感,尤其是来自后台的应用程序。

正确地说,当您完成通知后,您可以释放焦点:

audioManager.abandonAudioFocus(this);

【讨论】:

以上是关于在高于 4.0 的 Android 版本中无法播放声音的主要内容,如果未能解决你的问题,请参考以下文章

Android-Glide 4.0+ 加载GIF并控制播放次数

此版本的 Android Studio 无法打开此项目,请使用 Android Studio 4.0 或更高版本重试

无法创建支持android 4.0 及更高版本的surfaceview 相机应用。

为 android 4.0 或更高版本创建自定义锁屏?

Android studio 升级到4.0-4.0.1版本项目编译异常问题总结

iPhone 4.0:没有在后台播放音频?