简体   繁体   English

在Android 2.3的服务中使用的Mediaplayer

[英]Mediaplayer used in a service on Android 2.3

I have the following code written for a service in Android that plays video from a URL. 我为在Android中播放来自URL的视频的服务编写了以下代码。 The reason I am using a service is because I want the mediaplayer to keep the audio playing when switching from an activity with a surfaceview to one without (for example). 我使用一项服务的原因是因为我希望媒体播放器在从具有Surfaceview的活动切换为不具有SurfaceView的活动时(例如)保持音频播放。

While the code works on Android 4.0+ devices, I am having trouble solving: 当代码在Android 4.0+设备上运行时,我无法解决以下问题:

  • Error(100, 0) 错误(100,0)
  • Error(-38, 0) 错误(-38,0)

When running on Android 2.3 (Currently testing on a Samsung Galaxy S1). 在Android 2.3上运行时(当前在Samsung Galaxy S1上进行测试)。

Below you have the code for my service: 下面有您为我服务的代码:

/**
     * 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;
        }

Also, the logcat output: 另外,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

Please keep in mind that 请记住

  • This is only a test-project made so I can understand the steps before implementing this into the app I'm working on 这只是一个测试项目,因此在将其实现到正在开发的应用程序中之前,我可以理解这些步骤
  • I left out parts of the VideoService class regarding communication to and from the Activity (since the crash is mediaplayer-related). 我忽略了VideoService类中与Activity之间的通讯的部分(因为崩溃与Mediaplayer相关)。
  • SurfaceViewHolder is a singleton used to keep various UI elements (such as a reference to the progress bar or currently available SurfaceView if any), useful for switching between Activities (with different UIs) and keeping the video playing (or keeping the audio in the background) SurfaceViewHolder是用于保留各种UI元素(例如,对进度条的引用或当前可用的SurfaceView,如果有的话)的单例,可用于在“活动”(具有不同的UI)之间切换以及保持视频播放(或将音频保留在后台) )

LE: LE:

After returning true in onErrorListener for Errors 100 and -38 I get the following logcat output whenever I try to play the video. 在onErrorListener中针对错误100和-38返回true之后,每当尝试播放视频时,都会得到以下logcat输出。 The Media Server died error is still present. 媒体服务器死亡错误仍然存​​在。

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.

Hopefully someone with more experience than me can help me out. 希望比我有更多经验的人可以帮助我。

Thanks in advance! 提前致谢!

Start called in state 0 (the -38) means you are calling start before properly setting the media and preparing. 在状态0(-38)下调用Start表示您在正确设置媒体和准备之前正在调用start。 The 100 error is the media server died message. 100错误是介质服务器死亡消息。 You are supplying invalid media and calling start anyway. 您正在提供无效的媒体,并且仍在调用start。 You should add some if statements as safeguards before prepare and start, and handle error output in the onInfo and onError callbacks of the MediaPlayer. 您应该在准备和启动之前添加一些if语句作为保护措施,并处理MediaPlayer的onInfo和onError回调中的错误输出。

Edit: In the onError handler, differentiate between fatal errors and non-fatal errors. 编辑:在onError处理程序中,区分致命错误和非致命错误。 Return true for non-fatal errors to indicate that the error was handled. 对于非严重错误,返回true,以指示已处理该错误。 Returning false tells the MediaPlayer to call the onCompletion handler and stop. 返回false告诉MediaPlayer调用onCompletion处理程序并停止。 I see the "media server died" error quite often and it doesn't necessarily mean the media is invalid (as you have noted). 我经常看到“媒体服务器死机”错误,这并不一定意味着媒体无效(如您所述)。 Sorry I didn't notice that before. 抱歉,我之前没有注意到。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM