Подтвердить что ты не робот

Поверхность была выпущена, когда я пытаюсь установить Disisplay в MediaPlayer

Мой xml файл:

<SurfaceView
    android:id="@+id/surfaceView"
    android:layout_marginTop="50dp"
    android:layout_width="fill_parent"
    android:layout_height="300dp" />

Моя функция setDisplay:

public void playVideo() {
    MediaPlayer mp = new MediaPlayer();
    SurfaceView sv = (SurfaceView) this.findViewById(R.id.surfaceView);
    try {
        mp.setDataSource("sdcard/test/a.3gp");
        SurfaceHolder sh = sv.getHolder();
        mp.setDisplay(sh);***----the exception occured here***
        mp.prepare();
        mp.start();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

журнал, как показано ниже:

04-24 22:19:33.645: W/System.err(16106): java.lang.IllegalArgumentException: The surface has been released
04-24 22:19:33.645: W/System.err(16106):    at android.media.MediaPlayer._setVideoSurface(Native Method)
04-24 22:19:33.645: W/System.err(16106):    at android.media.MediaPlayer.setDisplay(MediaPlayer.java:698)

Здесь я нашел несколько подобных вопросов, но все они не подходят для меня. Жду ваших ответов. Большое спасибо.

4b9b3361

Ответ 1

Поверхность может быть уничтожена. Для этого вам нужно добавить a public void surfaceDestroyed(SurfaceHolder holder) к реализации SurfaceView следующим образом:

  @Override
public void surfaceDestroyed(SurfaceHolder holder) {
    synchronized (this) {
        hasActiveHolder = false;

        synchronized(this)          {
              this.notifyAll(); 
        }
    } 
}

Вы также должны добавить функцию, которая обрабатывает создание поверхности:

@Override
public void surfaceCreated(SurfaceHolder holder) {
     synchronized (this) {
        hasActiveHolder = true;
        this.notifyAll()
     }
}

И измените свою собственную функцию следующим образом:

    mp.setDataSource("sdcard/test/a.3gp");
    SurfaceHolder sh = sv.getHolder();
    synchronized (this) {
       while (!hasActiveHolder) {
              try {
                  this.wait();
              } catch (InterruptedException e) {
                //Print something
              }
        }
        mp.setDisplay(sh);
        mp.prepare();
    }

У вас есть еще один вариант, который Google предлагает использовать SurfaceView: в отдельном потоке.

Ответ 2

Это что-то связано с последовательностью выполнения, так как поверхность должна быть создана сначала, прежде чем устанавливать отображение для MediaPlayer, so you have to override the callback method surfaceCreated` на следующее:

@Override
public void surfaceCreated(SurfaceHolder holder) {
    mp.setDisplay(sh); // now "mp" is defined as a class variable
}

и теперь нет необходимости устанавливать отображение внутри вашего метода воспроизведения:

private MediaPlayer mp; // to use it inside surfaceCreated callback method
public void playVideo() {
    mp = new MediaPlayer();
    SurfaceView sv = (SurfaceView) this.findViewById(R.id.surfaceView);
    try {
        mp.setDataSource("sdcard/test/a.3gp");
        SurfaceHolder sh = sv.getHolder();
        mp.prepare();
        mp.start();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Ответ 3

Для тех, у кого проблемы, попробуйте выполнить SurfaceHolder.Callback в своей деятельности/фрагменте/etc и в методе onCreate/onCreateView, вызовите addCallback ( SurfaceHolder.Callback callback), используя вашу активность/фрагмент/etc в качестве обратного вызова параметра.

Ответ 4

Самый простой способ - просто позвонить setDisplay в surfaceCreated:

@Override
public void surfaceCreated(SurfaceHolder holder) {
    mp.setDisplay(holder)
}

и не забудьте развязать поверхность:

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    mp.setDisplay(null);
}

Примечание. Медиа-плеер должен быть инициализирован где-то раньше, например, в onCreate.

Ответ 5

Используйте SurfaceHolder.Callback, как показано ниже

SurfaceView mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
SurfaceHolder holder = mSurfaceView.getHolder();
final MediaPlayer player = new MediaPlayer();

holder.addCallback(new SurfaceHolder.Callback() {
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        player.setDisplay(holder);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, 
    int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }
});

String UrlPath="android.resource://"+getActivity().getPackageName()+"/"+R.raw.your_file_name_without_extension;
try {
    player.setDataSource(getActivity(),Uri.parse(UrlPath));
    player.prepareAsync();
} catch (IOException e) {
    e.printStackTrace();
}
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {

    @Override
    public void onPrepared(MediaPlayer mp) {
        mp.start();
    }
});