0

I have the following code written for a service in Android that plays video from a 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).

While the code works on Android 4.0+ devices, I am having trouble solving:

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

When running on Android 2.3 (Currently testing on a 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:

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).
  • 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)

LE:

After returning true in onErrorListener for Errors 100 and -38 I get the following logcat output whenever I try to play the video. 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!

Eugen
  • 1,537
  • 7
  • 29
  • 57
  • Error 100 and Error -38 dont mean anything to me. I think you have to be more specific, for example logcat messages. – Fredrick Gauss Sep 24 '13 at 12:06
  • Added the logcat output, though it doesn't really say much unfortunately. – Eugen Sep 24 '13 at 12:12
  • if these error expressions and codes come from `e.printStackTrace();` calls, how about adding extra mark so you can see which ones generate these errors. – Fredrick Gauss Sep 24 '13 at 12:24
  • possible duplicate of [Android MediaPlayer Problems :"Error (-38 , 0) " and "stop called in state 1"](http://stackoverflow.com/questions/11913108/android-mediaplayer-problems-error-38-0-and-stop-called-in-state-1) – rds Jun 22 '15 at 08:54

1 Answers1

0

Start called in state 0 (the -38) means you are calling start before properly setting the media and preparing. The 100 error is the media server died message. You are supplying invalid media and calling start anyway. 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.

Edit: In the onError handler, differentiate between fatal errors and non-fatal errors. Return true for non-fatal errors to indicate that the error was handled. Returning false tells the MediaPlayer to call the onCompletion handler and stop. 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.

Dave
  • 4,282
  • 2
  • 19
  • 24
  • Thanks, Dave. I know, I've looked up the errors. However, the media is valid (I'm passing urls to .mp4 on-line videos) and the logic seems ok, since I'm using this in Android 4.0+ devices and works as expected. If clauses will only stop my application on "onPrepared", not actually solve the Error 100. – Eugen Sep 25 '13 at 06:58
  • See my edit. Not all errors passed to onError are fatal, so you shouldn't always return false. – Dave Sep 25 '13 at 07:08
  • Thanks. I'll look into that and let you know what I worked out. – Eugen Sep 25 '13 at 07:19
  • I did some research and some modifications, but I'm still not able to get passed mostly the same errors. I still get 100 and -38 and the media server still "dies". – Eugen Sep 25 '13 at 08:10
  • My apologies if these questions seem silly. Do you have the Internet permission in your manifest? Are you using the emulator, and if so have you tried on an actual device? I've verified the URI is fine, and I don't see anything glaringly wrong in the code provided. – Dave Sep 25 '13 at 10:37
  • Yes...I do have the permission. The problem only occurs when testing on Android 2.3 (since compatibility is required) and I'm using a Galaxy S1 to test it on. I haven't tried it on any other GB device yet as I don't have any available and the app works fine on 4.0+ devices. I'm stumped as this seems to be either an S1-specific issue somwhere or GB-specific...I'm not sure – Eugen Sep 25 '13 at 10:39
  • Right, didn't read the entire question again before asking. My only other suggestion would be to boil it down to the basics. Start a new project with just an Activity & MediaPlayer and test it on the S1. If that works, start morphing it piecemeal to look like your current setup until something breaks. I used to have a GB device and don't remember any problems with it. Of course, we can't be sure what Samsung may have done, but somehow I doubt they messed with the MediaPlayer much if at all. Good luck to you. – Dave Sep 25 '13 at 14:28
  • Yeah, that's what I'm working on now. Thanks for your suggestions! :) – Eugen Sep 25 '13 at 14:33