Using Viewpager with MediaPlayer

左心房为你撑大大i 提交于 2019-12-11 12:19:23

问题


I'm trying to use a viewpager with a mediaplayer and i'm running into some issues. My app is set up where you click on a video in the gridview and then when the screen becomes visable it will start playing the video. When I first open up the video it plays fine. The viewpager works for two pages to the left or right. However when I go over that the app freezes up and crashes.

I set up some logs and I found in my pageradapater class, right after setPrimaryItem is called there is an IllegalArgumentException when I call Mediaplayer.setdisplay(holder) that says that The surface has been relased I've tried to so some research and testing but I can't find where the surface is being released. It seems weird to me that this error comes up but the video still plays. I'm not sure why this happens.

My best guess is that the pageradapater sets up all the pages in the Viewgroup at the beginning This might be causing some sort of issues because the surface is being set somewhere else in the ViewGroup.

I was looking for some help with this. My code is below

FullImageActivity.java

public class FullImageActivity extends Activity {


private static final String TAG = "MediaPlayer shit";
//MediaPlayer player;
//SurfaceView surfaceview;
SurfaceHolder surfaceHolder;
Gridview gridview = new Gridview();
int width;
int height;
Cursor cursor;
DisplayImageOptions options;
ViewPager viewpager;
TheViewPager theviewpager;
String path;
int position;
String[] projection = { GridviewData.ROWID, GridviewData.BITMAPPATH, GridviewData.VIDEOFILEPATH};
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.image_pager);

    Intent i = getIntent();

    position = i.getExtras().getInt("position");
    path = i.getExtras().getString("videopath");


    cursor = getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, 
                                gridview.mediaColumns, 
                                MediaStore.Video.Media.DATA + " like ?", 
                                new String[] {Environment.getExternalStorageDirectory().getPath() + "/Reelcam/TheReelcams/%"}, 
                                null); 

    theviewpager = new  TheViewPager(cursor, this);
    viewpager = (ViewPager) findViewById(R.id.pager);
    viewpager.setOffscreenPageLimit(2);
    viewpager.setAdapter(theviewpager);

}


@Override
protected void onPause() {
    //surfaceview.setVisibility(View.GONE);

    if ( theviewpager.player != null ) 
    {
        if ( theviewpager.player.isPlaying() )
            theviewpager.player.stop();
        theviewpager.player.release();
        theviewpager.player = null;
    }
    super.onPause();
}
@Override
protected void onResume() {
    //surfaceview.setVisibility(View.VISIBLE);
    viewpager.setCurrentItem(position);
    super.onResume();
}


@Override
protected void onDestroy() {
    cursor.close();
    super.onDestroy();
}

 }

TheViewPager.java

public class TheViewPager extends PagerAdapter implements OnCompletionListener, Callback, OnPreparedListener  {

private static final String TAG = "MediaPlayer shit";
LayoutInflater inflater;
MediaPlayer player;
String vpath;

Cursor cursor;
Activity activity;
LayoutInflater layoutInflater;
boolean hasActiveHolder = false;
FullImageActivity fullimage;
public TheViewPager(Cursor cursor2, Activity activity) {
    this.cursor = cursor2;
    layoutInflater = activity.getLayoutInflater();
    this.activity = activity;
    this.fullimage = new FullImageActivity();


}

@Override
public int getCount() {
    return cursor.getCount();
}

@Override
public void finishUpdate(ViewGroup container) {
    super.finishUpdate(container);
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {

    container.removeView((View) object);
}

@Override
public Object instantiateItem(ViewGroup view, int position) {

    View v = layoutInflater.inflate(R.layout.full_image, null, false);

    SurfaceView surfaceview = (SurfaceView)v.findViewById(R.id.surfaceview);



    SurfaceHolder holder = surfaceview.getHolder();
    v.setTag(holder);
    ((ViewPager) view).addView(v, 0);
    return v;

}

@Override
public boolean isViewFromObject(View view, Object object) {
    return view.equals(((View) object));
}

@Override
public void setPrimaryItem(ViewGroup container, int position,
        Object object) {
    Log.i(TAG, "setPrimaryItem");
    View view = (View) object;


    cursor.moveToPosition(position);
    vpath = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA));


    SurfaceHolder holder = (SurfaceHolder) view.getTag();
    player = new MediaPlayer();
    try {
        player.reset();
        player.setDataSource(vpath);            
        player.setOnCompletionListener(this);
        player.setOnPreparedListener(this);

        player.setDisplay(holder);
        player.prepare();

    }   
     catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }


    super.setPrimaryItem(container, position, object);
}

@Override
public void onCompletion(MediaPlayer player) {
    Log.i(TAG, "onCompleiton");

    if (player != null){
        if ( player.isPlaying() )
            player.stop();
    player.reset();
    player.release();
    player = null;
    }
}
@Override
public void startUpdate(ViewGroup container) {
    super.startUpdate(container);
}



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

}

As a side note here is my logic:

I'm using the instantiateItem method to set up the view. Android documentation says is will Create the page for the given position so I assume I will set up the view here that will later be populated in the setPrimaryItem. The documentation for the setPrimaryItem method says Called to inform the adapter of which item is currently considered to be the "primary", that is the one show to the user as the current page. Because of this I want to set the mediaplayer here because it is the only place the video will be viewed. I think I might be missing something.


回答1:


ViewPagers, by default only keep pages that are directly adjacent to the current page (i.e., the page to the left of the current, the current, and the page to the right of the current). Therefore if you are two pages away from your video playing page, it will be detached and no longer be active. You can change the number of pages kept in memory via the ViewPager.setOffscreenPageLimit to something higher than the default of 1. Note that this does increase the amount of memory needed and shouldn't be put too high - be sure to test on devices with a low amount of memory.



来源:https://stackoverflow.com/questions/17601226/using-viewpager-with-mediaplayer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!