android – textureview onSurfaceTextureAvailable never called inside relativelayout inside fragment-ThrowExceptions

Exception or error:

onSurfaceTextureAvailable in VideoView is never called…
I have this view that is holding the textureview.

public class MyMediaPlayer extends RelativeLayout{

Context mContext;
VideoView player;//this is a custom textureview that streams video

public MyMediaPlayer(Context context) {
    super(context);
    mContext = context; 
    init();
}
public MyMediaPlayer(Context context, AttributeSet attrs) {
    super(context, attrs);
    mContext = context; 
    init();
}
public MyMediaPlayer(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    mContext = context; 
    init();
}
private void init() {
    setBackgroundColor(Color.BLACK);    
    player = new VideoView(mContext);
    LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    addView(player,lp);
}
public void setURL(String url){
    player.setVideoPath(url);
}
public void start(){
    player.start();
}

}

VideoView is set up like this:

public class VideoView extends TextureView {

public VideoView(final Context context) {
    super(context);
    mContext = context;
    initVideoView();
}

public VideoView(final Context context, final AttributeSet attrs) {
    super(context, attrs);
    mContext = context;
    initVideoView();
}

public VideoView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    mContext = context;
    initVideoView();
}

public void initVideoView() {
    Log.d(LOG_TAG, "Initializing video view.");
    videoHeight = 0;
    videoWidth = 0;
    setFocusable(false);
    setSurfaceTextureListener(surfaceTextureListener);
}
SurfaceTextureListener surfaceTextureListener = new SurfaceTextureListener() {
    @Override
    public void onSurfaceTextureAvailable(final SurfaceTexture surface, final int width, final int height) {
        Log.d(LOG_TAG, "Surface texture now avaialble.");
        surfaceTexture = surface;
        openVideo();
    }

    @Override
    public void onSurfaceTextureSizeChanged(final SurfaceTexture surface, final int width, final int height) {
        Log.d(LOG_TAG, "Resized surface texture: " + width + '/' + height);
        surfaceWidth = width;
        surfaceHeight = height;
        boolean isValidState =  (targetState == STATE_PLAYING);
        boolean hasValidSize = (videoWidth == width && videoHeight == height);
        if (mediaPlayer != null && isValidState && hasValidSize) {
            start();
        }
    }

    @Override
    public boolean onSurfaceTextureDestroyed(final SurfaceTexture surface) {
        Log.i(LOG_TAG, "Destroyed surface number " + number);
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(final SurfaceTexture surface) {

    }
};
}

MyMediaPlayer is setup in a xml of a fragment.
If i place the VideoView inside the fragment then everything works fine.
But if it is in mymediaplayer inside the fragment onSurfaceTextureAvailable is never called.

How to solve:

onSurfaceTextureAvailable doesn’t seem to get called if the SurfaceTexture is already available. You can check if it is available and call your onSurfaceTextureAvailable method like below.

textureView.setSurfaceTextureListener(this);

/*
 * onSurfaceTextureAvailable does not get called if it is already available.
 */
if (view.isAvailable()) {
    onSurfaceTextureAvailable(view.getSurfaceTexture(), view.getWidth(), view.getHeight());
}

###

As for me ,the key to solve the problem is that add android:hardwareAccelerated=”true” for the activity in the AndroidManifest.xml .

You can use TextureView in a Scrolling-Container(Such as ListView,ScrollView,ViewPager etc) only if the activity for the TextureView with hardwareAccelerated property on.

The last few words in this blog mentioned that

Hope it works for you.

###

In my case I initially had my TextureView invisible and then loaded after fetching some data and this was causing onSurfaceTextureAvailable not to be called. I am guessing that for TextureView to be said to be ‘available’, it must be visible. My solution was to just make the TextureView visible from the start.

###

You need to enable hardware acceleration to use TextureView. If you don’t, its callback methods will not be called. Just pout that in your activity’s onCreate method:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

It worked for me.

###

i had the same problem , strangely resolved it with the following code

videoPreview = (TextureView) linearLayout.findViewById(R.id.videoView);
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams)videoPreview.getLayoutParams();
params.height = 130;
params.width = 508;
videoPreview.setLayoutParams(params);
videoPreview.setSurfaceTextureListener(this);

More strangely if i set only the width or the height that dosent work either.

###

I have met the same issue, onSurfaceTextureAvailable never called. Finally I found my textureview is invisible before setSurfaceTextureListener. So check status of textureview at first.

###

try to put mTextureView.setSurfaceTextureListener() in onCreate().

RootCause is that: onCreate() -> drawUI -> getHardwareLayer() -> callback SurfaceTextureListener.
So to fix this issue: setSurfaceTextureListener() before UI draw or redraw the UI.

Leave a Reply

Your email address will not be published. Required fields are marked *