[英]Mediaplayer used in a service on Android 2.3
我为在Android中播放来自URL的视频的服务编写了以下代码。 我使用一项服务的原因是因为我希望媒体播放器在从具有Surfaceview的活动切换为不具有SurfaceView的活动时(例如)保持音频播放。
当代码在Android 4.0+设备上运行时,我无法解决以下问题:
在Android 2.3上运行时(当前在Samsung Galaxy S1上进行测试)。
下面有您为我服务的代码:
/**
* The MediaPlayer instance
*/
private MediaPlayer mediaPlayer;
/**
* Boolean value indicating if the service is running or not.
*/
private static boolean videoServiceRunning = false;
/**
* Boolean value indicating if the video is playing or not.
*/
private static boolean videoPlaying = false;
/**
* Boolean value indicating if the video has not been started yet or if it has ended playing.
*/
private static boolean videoPrepared = false;
@Override
public void onCreate() {
super.onCreate();
Log.i(LOGTAG, "Service Started.");
mediaPlayer = new MediaPlayer();
videoServiceRunning = true;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i("MyService", "Service Stopped.");
videoServiceRunning = false;
try {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
setVideoPlaying(false);
}
mediaPlayer.release();
}
catch (IllegalStateException e) {
e.printStackTrace();
sendMessageToActivity(MEDIAPLAYER_ERROR);
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(LOGTAG, "Received start id " + startId + ": " + intent);
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnErrorListener(this);
return START_STICKY; // Run until explicitly stopped.
}
@Override
public IBinder onBind(Intent intent) {
Log.i(LOGTAG, "onBind");
return inMessenger.getBinder();
}
public static boolean isVideoServiceRunning()
{
return videoServiceRunning;
}
private void prepareVideo() {
try {
mediaPlayer.setDataSource(getApplicationContext(), Uri.parse(videoURL));
mediaPlayer.setScreenOnWhilePlaying(true);
mediaPlayer.prepare();
setVideoPrepared(true);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
String message = isNetworkAvailable() ?
getApplicationContext().getString(R.string.movie_unavailable) :
getApplicationContext().getString(R.string.network_error);
sendErrorMessageToActivity(message);
}
}
private void play() {
try {
mediaPlayer.start();
setVideoPlaying(true);
sendMessageToActivity(MEDIAPLAYER_PLAYING);
}
catch (IllegalStateException e) {
e.printStackTrace();
sendMessageToActivity(MEDIAPLAYER_ERROR);
}
}
private void pause() {
try {
mediaPlayer.pause();
setVideoPlaying(false);
sendMessageToActivity(MEDIAPLAYER_PAUSED);
}
catch (IllegalStateException e) {
e.printStackTrace();
sendMessageToActivity(MEDIAPLAYER_ERROR);
}
}
private void coupleSurface() {
try {
SurfaceHolder surfaceHolder = SurfaceViewHolder.getInstance().getSurfaceHolder();
mediaPlayer.setDisplay(surfaceHolder);
sendMessageToActivity(MEDIAPLAYER_SURFACE_COUPLED);
}
catch (IllegalStateException e) {
e.printStackTrace();
sendMessageToActivity(MEDIAPLAYER_ERROR);
}
}
private void uncoupleSurface() {
try {
mediaPlayer.setDisplay(null);
sendMessageToActivity(MEDIAPLAYER_SURFACE_UNCOUPLED);
}
catch (IllegalStateException e) {
e.printStackTrace();
sendMessageToActivity(MEDIAPLAYER_ERROR);
}
}
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
setVideoPlaying(false);
sendMessageToActivity(MEDIAPLAYER_ENDED);
}
@Override
public void onPrepared(MediaPlayer mp) {
sendMessageToActivity(ACTIVITY_VIDEO_PREPARED);
VideoService.videoDuration = mediaPlayer.getDuration();
VideoService.videoWidth = mediaPlayer.getVideoWidth();
VideoService.videoHeight = mediaPlayer.getVideoHeight();
Runnable updateProgressRunnable = new Runnable() {
@Override
public void run() {
if (videoServiceRunning) {
currentPosition = -1;
try {
currentPosition = mediaPlayer.getCurrentPosition();
}
catch (IllegalStateException e) {
Log.e(LOGTAG, "An exception has occurred while trying to retrieve the current position: "+ e);
}
if (currentPosition != -1) {
SurfaceViewHolder.getInstance().updateSeekBarProgress(currentPosition);
}
//TODO should the handler continue scheduling the runnable for execution in case of an exception?
handler.postDelayed(this, 1000);
}
}
};
handler.postDelayed(updateProgressRunnable, 1000);
SurfaceHolder surfaceHolder = SurfaceViewHolder.getInstance().getSurfaceHolder();
mediaPlayer.setDisplay(surfaceHolder);
if (playVideo) {
play();
}
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.e(LOGTAG, "What: "+what+", Extra: "+extra);
return false;
}
public static synchronized boolean isVideoPlaying() {
return VideoService.videoPlaying;
}
public static synchronized void setVideoPlaying(boolean videoPlaying) {
VideoService.videoPlaying = videoPlaying;
}
public static synchronized boolean isVideoPrepared() {
return videoPrepared;
}
public static synchronized void setVideoPrepared(boolean videoPrepared) {
VideoService.videoPrepared = videoPrepared;
}
另外,logcat输出:
09-24 15:10:57.671: D/VideoService(5561): handleMessage: 4
09-24 15:10:57.765: D/VideoService(5561): handleMessage: 0
09-24 15:10:57.765: I/MediaPlayer(5561): uri is:http://techslides.com/demos/sample-videos/small.mp4
09-24 15:10:57.765: I/MediaPlayer(5561): path is null
09-24 15:10:57.769: D/MediaPlayer(5561): Couldn't open file on client side, trying server side
09-24 15:11:00.679: D/VideoService(5561): handleMessage: 1
09-24 15:11:08.718: I/dalvikvm(5561): threadid=4: reacting to signal 3
09-24 15:11:08.730: I/dalvikvm(5561): Wrote stack traces to '/data/anr/traces.txt'
09-24 15:11:12.214: D/VideoService(5561): handleMessage: 7
09-24 15:11:15.722: W/IMediaDeathNotifier(5561): media server died
09-24 15:11:15.726: E/MediaPlayer(5561): error (100, 0)
09-24 15:11:15.726: W/AudioSystem(5561): AudioFlinger server died!
09-24 15:11:15.753: E/MediaPlayer(5561): Error (100,0)
09-24 15:11:15.753: E/VideoService(5561): What: 100, Extra: 0
09-24 15:11:15.812: D/VideoService(5561): handleMessage: 1
09-24 15:11:15.812: E/MediaPlayer(5561): start called in state 0
09-24 15:11:15.812: E/MediaPlayer(5561): error (-38, 0)
09-24 15:11:15.921: E/MediaPlayer(5561): Error (-38,0)
09-24 15:11:15.921: E/VideoService(5561): What: -38, Extra: 0
09-24 15:11:16.996: D/VideoService(5561): handleMessage: 1
09-24 15:11:16.996: E/MediaPlayer(5561): start called in state 0
09-24 15:11:17.000: E/MediaPlayer(5561): error (-38, 0)
09-24 15:11:17.003: E/MediaPlayer(5561): Error (-38,0)
09-24 15:11:17.007: E/VideoService(5561): What: -38, Extra: 0
请记住
LE:
在onErrorListener中针对错误100和-38返回true之后,每当尝试播放视频时,都会得到以下logcat输出。 媒体服务器死亡错误仍然存在。
09-25 11:07:12.226: E/AndroidRuntime(7921): Set to default setting_6 : region=-Duser.region=US propRegn=US
09-25 11:07:15.378: E/AndroidRuntime(7930): Set to default setting_6 : region=-Duser.region=US propRegn=US
09-25 11:07:19.097: E/AndroidRuntime(7946): Set to default setting_6 : region=-Duser.region=US propRegn=US
09-25 11:07:30.027: E/MediaPlayerService(7886): MediaPlayerService::mIsAnyDrmVideoPlaying : 0
09-25 11:07:30.449: E/SecHardwareRenderer(7886): Unable to create the overlay!
09-25 11:07:30.449: A/SoftwareRenderer(7886): frameworks/base/media/libstagefright/colorconversion/SoftwareRenderer.cpp:59 mConverter.isValid()
09-25 11:07:35.167: E/dalvikvm(1566): Failed to write stack traces to /data/anr/traces.txt (1627 of 2166): No such file or directory
09-25 11:07:35.941: E/dalvikvm(1642): Failed to write stack traces to /data/anr/traces.txt (816 of 2839): No such file or directory
09-25 11:07:37.449: E/dalvikvm(7751): Failed to write stack traces to /data/anr/traces.txt (1162 of 2250): No such file or directory
09-25 11:07:37.449: E/dalvikvm(7787): Failed to write stack traces to /data/anr/traces.txt (-1 of 2249): Math result not representable
09-25 11:07:37.468: E/dalvikvm(7763): Failed to write stack traces to /data/anr/traces.txt (-1 of 2250): Math result not representable
09-25 11:07:37.476: E/dalvikvm(7803): Failed to write stack traces to /data/anr/traces.txt (-1 of 3216): Math result not representable
09-25 11:07:37.796: E/dalvikvm(7954): Failed to write stack traces to /data/anr/traces.txt (-1 of 2376): Math result not representable
09-25 11:07:37.800: E/dalvikvm(7744): Failed to write stack traces to /data/anr/traces.txt (-1 of 2241): Math result not representable
09-25 11:07:37.804: E/dalvikvm(7907): Failed to write stack traces to /data/anr/traces.txt (-1 of 2230): Math result not representable
09-25 11:07:37.929: E/dalvikvm(7829): Failed to write stack traces to /data/anr/traces.txt (10370 of 13387): No such file or directory
09-25 11:07:44.617: E/MediaPlayer(7954): error (100, 0)
09-25 11:07:44.625: E/MediaPlayer(7954): Error (100,0)
09-25 11:07:44.632: E/VideoService(7954): What: 100, Extra: 0
09-25 11:07:45.074: E/SoundBooster(7989): readSBTable: file open error!
09-25 11:07:45.074: E/AcousticEQ(7989): [AEQ] aeqcoe.txt: file open error!
09-25 11:07:46.117: E/AudioService(1462): Media server died.
09-25 11:07:46.125: E/AudioService(1462): Media server started.
希望比我有更多经验的人可以帮助我。
提前致谢!
在状态0(-38)下调用Start表示您在正确设置媒体和准备之前正在调用start。 100错误是介质服务器死亡消息。 您正在提供无效的媒体,并且仍在调用start。 您应该在准备和启动之前添加一些if语句作为保护措施,并处理MediaPlayer的onInfo和onError回调中的错误输出。
编辑:在onError处理程序中,区分致命错误和非致命错误。 对于非严重错误,返回true,以指示已处理该错误。 返回false告诉MediaPlayer
调用onCompletion处理程序并停止。 我经常看到“媒体服务器死机”错误,这并不一定意味着媒体无效(如您所述)。 抱歉,我之前没有注意到。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.