在Android 4.0以上的版本中,声音无法播放。

5
我使用以下代码在我的应用程序中播放声音。在ICS之前,一切都运行良好。但是在ICS及更高版本上,虽然没有出现错误,但听不到任何声音。 编辑:请注意,以下代码由广播接收器触发。广播接收器调用异步任务。在异步任务的后处理方法中调用以下方法。
这个错误只会出现在特定的手机型号(例如Nexus)上,在某些型号上,用户可以播放随操作系统提供的声音,但不能播放他们自己放置在铃声文件夹中的声音。
我无法确定问题所在,因为它只在特定的手机上发生。
可能的错误是什么?
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

这个问题是我之前提出的一个问题的后续问题: 在 Android 冰淇淋三明治版本以上无法播放声音


你能否辨别出正在播放和未播放的声音,并告诉我你试图播放的音频的比特率和格式以及使用的设备? - Ben Pearson
无法播放的格式之一是mp3。 - user93796
你的代码似乎没有明显的问题 - 在我的 Nexus 上,示例应用程序可以在 NOTIFICATION 流中播放。我建议你添加一个错误监听器,并删除可能存在的日志过滤器 - 有趣的日志将来自 MediaPlayer 和 NuPlayer。 - rds
1个回答

2

即使是通知,您也应该请求音频焦点。在您的情况下,代码可能如下所示:

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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接