Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/209.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 无法使MediaPlayer.prepareAsync正常工作_Android_Audio - Fatal编程技术网

Android 无法使MediaPlayer.prepareAsync正常工作

Android 无法使MediaPlayer.prepareAsync正常工作,android,audio,Android,Audio,我一直在尝试使用prepareAsync()方法和onPrepared()方法实现一个简单的MediaPlayer(音频)。这些是从IntentService中调用的。相关活动仅发送启动和停止意图操作。我已确认活动正在发送事件。 以下是IntentService中的代码: package com.javacodegeeks.androidmusic_intentservice; import android.app.IntentService; import android.content.I

我一直在尝试使用prepareAsync()方法和onPrepared()方法实现一个简单的MediaPlayer(音频)。这些是从IntentService中调用的。相关活动仅发送启动和停止意图操作。我已确认活动正在发送事件。 以下是IntentService中的代码:

package com.javacodegeeks.androidmusic_intentservice;

import android.app.IntentService;
import android.content.Intent;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.widget.Toast;

import java.io.IOException;
import android.net.Uri;

/**
 * An {@link IntentService} subclass for handling asynchronous task requests in
 * a service on a separate handler thread.
 * <p/>
 * TODO: Customize class - update intent actions, extra parameters and static
 * helper methods.
  */
public class MusicIntentService extends IntentService implements  MediaPlayer.OnErrorListener, MediaPlayer.OnPreparedListener {
// TODO: Rename actions, choose action names that describe tasks that this

private static final String ACTION_PLAY = "com.example.action.PLAY";
private static final String ACTION_STOP = "com.example.action.STOP";
static MediaPlayer mMediaPlayer = null;

  public MusicIntentService() {
    super("MusicIntentService");
}

@Override
public void onHandleIntent(Intent intent) {
    if (intent != null) if (intent.getAction().equals(ACTION_PLAY)) {
        if (mMediaPlayer == null) {
            mMediaPlayer = new MediaPlayer();
            String fileName = "android.resource://" + getPackageName() + "/" + R.raw.georgeharrisonlivinginthematerialworld;

            try {
                mMediaPlayer.setDataSource(this, Uri.parse(fileName));

            } catch (IllegalArgumentException e) {
                Toast.makeText(getApplicationContext(), "IllegalArgumentException", Toast.LENGTH_LONG).show();
            } catch (SecurityException e) {
                Toast.makeText(getApplicationContext(), "SecurityException", Toast.LENGTH_LONG).show();
            } catch (IllegalStateException e) {
                Toast.makeText(getApplicationContext(), "IllegalStateException", Toast.LENGTH_LONG).show();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        mMediaPlayer.setOnErrorListener(this);
        mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        mMediaPlayer.setOnPreparedListener(this);


      try {
            mMediaPlayer.prepareAsync();
        } catch (IllegalStateException e) {
            Toast.makeText(getApplicationContext(), "IllegalStateException", Toast.LENGTH_LONG).show();
        }
             /*calling prepare() and start() works ok*/
             /* it is better to have the prepareAsync() and onPrepared() pattern implemented*/
             /* try {
                    mMediaPlayer.prepare();
                } catch (IllegalStateException e) {
                    Toast.makeText(getApplicationContext(), "IllegalStateException prepare()", Toast.LENGTH_LONG).show();
                } catch (IOException e) {
                    Toast.makeText(getApplicationContext(), "IOException prepare()", Toast.LENGTH_LONG).show();
                }*/

               /* try {
                    mMediaPlayer.start();
                } catch (IllegalStateException e) {
                    Toast.makeText(getApplicationContext(), "IllegalStateException start()", Toast.LENGTH_LONG).show();
                }*/

    } else if (intent.getAction().equals(ACTION_STOP)) {
        if (mMediaPlayer.isPlaying()) {
            mMediaPlayer.stop();
        }
    }
}

/** Called when MediaPlayer is ready */
public void onPrepared(MediaPlayer player) {
    try {
        mMediaPlayer.start();
    } catch (IllegalStateException e) {
        Toast.makeText(getApplicationContext(), "IllegalStateException in onPrepared", Toast.LENGTH_LONG).show();
    }
}


public boolean onError(MediaPlayer mp, int what, int extra) {

    /*
    ... react appropriately ...
    The MediaPlayer has moved to the Error state, must be reset!
    */
    return true;
}
}
但是,当我调试并设置以下行的断点时:

    mMediaPlayer.setOnErrorListener(this);
    mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    mMediaPlayer.setOnPreparedListener(this);


  try {
        mMediaPlayer.prepareAsync();
并单步执行这些语句,然后在单步执行prepareAsync()语句后选择Resume,代码将到达onPrepared()方法,音频输出正常。

当我取消对prepare()和play()语句的注释并注释掉prepareAsynch()语句时,当我在设置或不设置断点的情况下运行或调试时,会得到音频输出。(这就是为什么我在注释掉的代码中留下来,以显示什么是有效的。)我理解这只是运气,在到达play()方法之前,准备工作已经完成

onError()从未到达过,我知道那里还有工作要做

另一件事是,我确实尝试过:

 mMediaPlayer.setOnPreparedListener(MusicIntentService.this);
这似乎没有什么不同。事实上,当我打开一个带有“MusicIntentService.this”的手表窗口时,我看到了与“this”相同的元素和值

如果有人能给我指出正确的方向,我将不胜感激。我的下一步是尝试在调用setOnpreparedListener(..)时实现侦听器,但我想了解为什么当前的实现不能始终如一地工作。 提前谢谢。 吉姆这是我做的

我最初的目标是利用prepareAsync()方法实现一个简单的媒体播放器。这将允许更健壮的设计,因为我们不必只希望媒体播放器在调用start()方法之前达到准备好的状态

如上所述,pskink直截了当地告诉我IntentService不适合处理媒体播放器控件

然后,我假设我将使用一个服务,我开始考虑处理按钮按下,并保持媒体播放器状态与UI一致

根据我对棒棒糖中包含的功能所做的一些阅读,我回到了我从以下网站下载的一个项目:

该活动启动一项服务,处理按钮输入和媒体播放器控制:

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Intent intent = new Intent( getApplicationContext(), MediaPlayerService.class );
    intent.setAction( MediaPlayerService.ACTION_PLAY );
    startService( intent );
}
}
MediaPlayerService如下所示:

/**
 * Created by paulruiz on 10/28/14.
 */
public class MediaPlayerService extends Service {

public static final String ACTION_PLAY = "action_play";
public static final String ACTION_PAUSE = "action_pause";
public static final String ACTION_REWIND = "action_rewind";
public static final String ACTION_FAST_FORWARD = "action_fast_foward";
public static final String ACTION_NEXT = "action_next";
public static final String ACTION_PREVIOUS = "action_previous";
public static final String ACTION_STOP = "action_stop";

private MediaPlayer mMediaPlayer;
private MediaSessionManager mManager;
private MediaSession mSession;
private MediaController mController;

@Override
public IBinder onBind(Intent intent) {
    return null;
}

private void handleIntent( Intent intent ) {
    if( intent == null || intent.getAction() == null )
        return;

    String action = intent.getAction();

    if( action.equalsIgnoreCase( ACTION_PLAY ) ) {
        mController.getTransportControls().play();
    } else if( action.equalsIgnoreCase( ACTION_PAUSE ) ) {
        mController.getTransportControls().pause();
    } else if( action.equalsIgnoreCase( ACTION_FAST_FORWARD ) ) {
        mController.getTransportControls().fastForward();
    } else if( action.equalsIgnoreCase( ACTION_REWIND ) ) {
        mController.getTransportControls().rewind();
    } else if( action.equalsIgnoreCase( ACTION_PREVIOUS ) ) {
        mController.getTransportControls().skipToPrevious();
    } else if( action.equalsIgnoreCase( ACTION_NEXT ) ) {
        mController.getTransportControls().skipToNext();
    } else if( action.equalsIgnoreCase( ACTION_STOP ) ) {
        mController.getTransportControls().stop();
    }
}

private Notification.Action generateAction( int icon, String title, String intentAction ) {
    Intent intent = new Intent( getApplicationContext(), MediaPlayerService.class );
    intent.setAction( intentAction );
    PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 1, intent, 0);
    return new Notification.Action.Builder( icon, title, pendingIntent ).build();
}

private void buildNotification( Notification.Action action ) {
        Notification.MediaStyle style = new Notification.MediaStyle();

        Intent intent = new Intent( getApplicationContext(), MediaPlayerService.class );
        intent.setAction( ACTION_STOP );
        PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 1, intent, 0);
        Notification.Builder builder = new Notification.Builder( this )
                .setSmallIcon(R.drawable.ic_launcher)
                .setContentTitle( "Media Title" )
                .setContentText( "Media Artist" )
                .setDeleteIntent( pendingIntent )
                .setStyle(style);

        builder.addAction( generateAction( android.R.drawable.ic_media_previous, "Previous", ACTION_PREVIOUS ) );
        builder.addAction( generateAction( android.R.drawable.ic_media_rew, "Rewind", ACTION_REWIND ) );
        builder.addAction( action );
        builder.addAction( generateAction( android.R.drawable.ic_media_ff, "Fast Foward", ACTION_FAST_FORWARD ) );
        builder.addAction( generateAction( android.R.drawable.ic_media_next, "Next", ACTION_NEXT ) );
        style.setShowActionsInCompactView(0,1,2,3,4);

        NotificationManager notificationManager = (NotificationManager) getSystemService( Context.NOTIFICATION_SERVICE );
        notificationManager.notify( 1, builder.build() );
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    if( mManager == null ) {
        initMediaSessions();
    }

    handleIntent( intent );
    return super.onStartCommand(intent, flags, startId);
}

private void initMediaSessions() {
    mMediaPlayer = new MediaPlayer();

    mSession = new MediaSession(getApplicationContext(), "simple player session");
    mController =new MediaController(getApplicationContext(), mSession.getSessionToken());

    mSession.setCallback(new MediaSession.Callback(){
        @Override
        public void onPlay() {
            super.onPlay();
            Log.e( "MediaPlayerService", "onPlay");
            buildNotification( generateAction( android.R.drawable.ic_media_pause, "Pause", ACTION_PAUSE ) );
        }

        @Override
        public void onPause() {
            super.onPause();
            Log.e( "MediaPlayerService", "onPause");
            buildNotification(generateAction(android.R.drawable.ic_media_play, "Play", ACTION_PLAY));
        }

        @Override
        public void onSkipToNext() {
            super.onSkipToNext();
            Log.e( "MediaPlayerService", "onSkipToNext");
            //Change media here
            buildNotification( generateAction( android.R.drawable.ic_media_pause, "Pause", ACTION_PAUSE ) );
        }

        @Override
        public void onSkipToPrevious() {
            super.onSkipToPrevious();
            Log.e( "MediaPlayerService", "onSkipToPrevious");
            //Change media here
            buildNotification( generateAction( android.R.drawable.ic_media_pause, "Pause", ACTION_PAUSE ) );
        }

        @Override
        public void onFastForward() {
            super.onFastForward();
            Log.e( "MediaPlayerService", "onFastForward");
            //Manipulate current media here
        }

        @Override
        public void onRewind() {
            super.onRewind();
            Log.e( "MediaPlayerService", "onRewind");
            //Manipulate current media here
        }

        @Override
        public void onStop() {
            super.onStop();
            Log.e( "MediaPlayerService", "onStop");
            //Stop media player here
            NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.cancel( 1 );
            Intent intent = new Intent( getApplicationContext(), MediaPlayerService.class );
            stopService( intent );
        }

        @Override
        public void onSeekTo(long pos) {
            super.onSeekTo(pos);
        }

        @Override
        public void onSetRating(Rating rating) {
            super.onSetRating(rating);
        }
        }
    );
}
正如作者所指出的,实际的媒体播放器实例化和实现并不存在,但是:“现在我们在锁屏和通知抽屉中有了一个完全工作的MediaStyle通知,它利用MediaSession进行播放控制。享受吧!”

我做了几处修改。
主要更改是方法initMediaSessions()。添加了用于实例化和初始化媒体播放器的代码。这是添加prepareAsync()和setOnPreparedListener()调用的地方。 还对onPlay()和onPause()回调进行了更改,以包括媒体播放器控制方法

public void initMediaSessions () {
   Uri uri =  Uri.parse("http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8" );

     //String fileName = "android.resource://" + getPackageName() + "/" + R.raw.georgeharrisonlivinginthematerialworld;
   //Uri uri = Uri.parse(fileName);


    try {
        mMediaPlayer = new MediaPlayer();

    } catch (IllegalArgumentException e) {
        Toast.makeText(getApplicationContext(), "IllegalArgumentException", Toast.LENGTH_LONG).show();
    } catch (SecurityException e) {
        Toast.makeText(getApplicationContext(), "SecurityException", Toast.LENGTH_LONG).show();
    } catch (IllegalStateException e) {
        Toast.makeText(getApplicationContext(), "IllegalStateException", Toast.LENGTH_LONG).show();
    }

    try {
        mMediaPlayer.setDataSource(this, uri);

    } catch (IllegalArgumentException e) {
        Toast.makeText(getApplicationContext(), "IllegalArgumentException", Toast.LENGTH_LONG).show();
    } catch (SecurityException e) {
        Toast.makeText(getApplicationContext(), "SecurityException", Toast.LENGTH_LONG).show();
    } catch (IllegalStateException e) {
        Toast.makeText(getApplicationContext(), "IllegalStateException", Toast.LENGTH_LONG).show();
    } catch (IOException e) {
        e.printStackTrace();
    }
    mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

    mMediaPlayer.setOnPreparedListener(this);

    try {
        mMediaPlayer.prepareAsync();
    } catch (IllegalArgumentException e) {
        Toast.makeText(getApplicationContext(), "IllegalArgumentException", Toast.LENGTH_LONG).show();
    } catch (SecurityException e) {
        Toast.makeText(getApplicationContext(), "SecurityException", Toast.LENGTH_LONG).show();
    } catch (IllegalStateException e) {
        Toast.makeText(getApplicationContext(), "IllegalStateException", Toast.LENGTH_LONG).show();
    }

    mManager= (MediaSessionManager)getSystemService(Context.MEDIA_SESSION_SERVICE);
    mSession = new MediaSession(getApplicationContext(), "simple player session");
    mController =new MediaController(getApplicationContext(), mSession.getSessionToken());

    mSession.setCallback(new MediaSession.Callback(){
        @Override
        public void onPlay() {
            super.onPlay();
            Log.e("MediaPlayerService", "onPlay");

            if(first_time_through == true)
            {
                first_time_through = false;
            }
            else {
                try {
                    mMediaPlayer.start();
                } catch (IllegalArgumentException e) {
                    Toast.makeText(getApplicationContext(), "IllegalArgumentException", Toast.LENGTH_LONG).show();
                } catch (SecurityException e) {
                    Toast.makeText(getApplicationContext(), "SecurityException", Toast.LENGTH_LONG).show();
                } catch (IllegalStateException e) {
                    Toast.makeText(getApplicationContext(), "IllegalStateException", Toast.LENGTH_LONG).show();
                }
            }
            buildNotification(generateAction(android.R.drawable.ic_media_pause, "Pause", ACTION_PAUSE));
        }

        @Override
        public void onPause() {

            super.onPause();
            mMediaPlayer.pause();
            Log.e( "MediaPlayerService", "onPause");
            buildNotification(generateAction(android.R.drawable.ic_media_play, "Play", ACTION_PLAY));
        }

        @Override
        public void onSkipToNext() {
            super.onSkipToNext();
            Log.e( "MediaPlayerService", "onSkipToNext");
            //Change media here
            buildNotification( generateAction( android.R.drawable.ic_media_pause, "Pause", ACTION_PAUSE ) );
        }

        @Override
        public void onSkipToPrevious() {
            super.onSkipToPrevious();
            Log.e( "MediaPlayerService", "onSkipToPrevious");
            //Change media here
            buildNotification( generateAction( android.R.drawable.ic_media_pause, "Pause", ACTION_PAUSE ) );
        }

        @Override
        public void onFastForward() {
            super.onFastForward();
            Log.e( "MediaPlayerService", "onFastForward");
            //Manipulate current media here
        }

        @Override
        public void onRewind() {
            super.onRewind();
            Log.e( "MediaPlayerService", "onRewind");
            //Manipulate current media here
        }

        @Override
        public void onStop() {
            super.onStop();
            Log.e( "MediaPlayerService", "onStop");
            //Stop media player here
            NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.cancel( 1 );
            Intent intent = new Intent( getApplicationContext(), MediaPlayerService.class );
            stopService( intent );
        }

        @Override
        public void onSeekTo(long pos) {
            super.onSeekTo(pos);
        }

        @Override
        public void onSetRating(Rating rating) {
            super.onSetRating(rating);
        }
        }
    );
}
该活动使用“播放意图”操作启动MediaPlayerService:

    intent.setAction( MediaPlayerService.ACTION_PLAY );
第一次通过逻辑添加到onPlay()回调中,以防止在执行onPrepared()回调之前调用mmediplayer.start()方法。以下内容已添加到MediaPlayerService类:

public static boolean first_time_through = true;
onPrepared()回调也被添加到MediaPlayerService中

/** Called when MediaPlayer is ready */
public void onPrepared(MediaPlayer player) {
    try {

        mMediaPlayer.start();
    } catch (IllegalStateException e) {
        Toast.makeText(getApplicationContext(), "IllegalStateException in onPrepared", Toast.LENGTH_LONG).show();
    }
}
由于我尝试使用HLS源执行此操作,因此在AndroidManifest.xml文件中添加了以下行:

     <uses-permission android:name="android.permission.INTERNET" />
    <permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
当我在我的三星Galaxy S5上使用相同的音频源时,使用简化的(API 4.4.2版本的应用程序),音频播放效果很好。此外,正如预期的那样,当从Safari启动时,相同的HLS源可以正常运行。我认为通过模拟器查看HLS回放不会获得太多好处

再次感谢你,亲爱的


Jim试图使用简单服务而不是IntentService?这里真的不需要IntentService,如果您真的需要知道原因,请参阅IntentService.javapskink中的ServiceHandler类是如何实现的。听起来你在极力推荐使用这项服务。我将把代码重写为so,然后将结果作为后续发布。我还将按照您的建议介绍IntentService的实现。我要去服务中心了。我对Android、Java和stackoverflow的世界比较陌生。如果我对使用服务的实现有疑问,我会在这个线程中发布它吗?再次感谢。是的,你可以在这里问。服务有效吗?
    <permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
01-10 01:25:22.074    1219-1237/system_process I/ActivityManager﹕ Waited long enough for: ServiceRecord{3ca21a0b u0 com.google.android.gms/.wearable.service.WearableService}
 01-10 01:25:26.204     931-1216/? I/AudioFlinger﹕ BUFFER TIMEOUT: remove(4096) from active list on thread 0xb62b8000
 01-10 01:25:34.675    2076-2100/com.android.calendar D/InitAlarmsService﹕ Clearing and rescheduling alarms.
 01-10 01:25:59.696    1219-1232/system_process I/MediaFocusControl﹕ AudioFocus  abandonAudioFocus() from android.media.AudioManager@1c78d923com.android.music.MediaPlaybackService$3@5af4e20