简体   繁体   中英

Calling finish() from SurfaceView does not destroy Activity

I want to finish() the activity VideoPlayer from the class RenderView . However calling finish() from RenderView does not call onDestroy() . The Activity is not destroyed and does not return back to the previous Main Activity.

public class VideoPlayer extends Activity  {

    @Override
    protected void onPause(){
        super.onPause();
        renderView.pause();     
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        naClose2();
    }

}

mFinished = true but it returns back to the method parseServerInfo() where finish() was called and continues executing the rest of the code.

EDIT

public class RenderView extends SurfaceView implements SurfaceHolder.Callback   {
    private Context mContext;

    private Runnable prDisplayVideoTask = new Runnable() {
        public void run() {
            if(zoomState.isPlaying()==false){
                if(zoomState.getFlag()==FlagType.PAUSE){
                    zoomState.setFlag(FlagType.NONE);
                    naPause();
                }
            } else {
                naStart();
            }
            prVideoDisplayHandler.postDelayed(this, prDelay);
        }
    };

    public RenderView(...) {
        super(_context);
        this.mContext = _context;
        init(address, windowWidth, windowHeight, videoWidth, videoHeight,
                server_ip, server_port);
        SurfaceHolder holder = getHolder();
        holder.setFormat(PixelFormat.RGBA_8888);
        holder.addCallback(this);
    }

    @SuppressLint("NewApi")
    public void init(...) {
        parseServerInfo(receivedData);
        prVideoDisplayHandler.removeCallbacks(prDisplayVideoTask);
        prVideoDisplayHandler.postDelayed(prDisplayVideoTask, prDelay);
    }

    public void pause(){
        naPause();
        prVideoDisplayHandler.removeCallbacks(prDisplayVideoTask);
    }

    public void resume(){
        prVideoDisplayHandler.postDelayed(prDisplayVideoTask, prDelay);
    }

    public void parseServerInfo(String data) {
        if (numCameras == 0) {
            Toast.makeText(mContext, "No stream detected!", Toast.LENGTH_LONG).show();

            // Finish is called here
            VideoPlayer videoplayer = (VideoPlayer) mContext;
            videoplayer.finish();
            return;
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if (mCreated  == true) {
            surfaceDestroyed(holder);
        }
        Surface surface = holder.getSurface();
        render(surface);
        mCreated = true;
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mCreated = false;
    }
}

Hope someone could help point out what I am doing wrong.

This is why it is continuing on and freezing up (as mentioned in the comments to your question). It should. That is how the java language works. Here,

@SuppressLint("NewApi")
public void init(...) {
    parseServerInfo(receivedData);
    ...
}

You call parseServerInfo(receivedData); which does

public void parseServerInfo(String data) {
    if (numCameras == 0) {
        Toast.makeText(mContext, "No stream detected!", Toast.LENGTH_LONG).show();

        // Finish is called here
        VideoPlayer videoplayer = (VideoPlayer)getContext();
        videoplayer.finish();
        return;
    }
}

So you are seeing the Toast, getting finish called, and saying good to go. But you aren't looking back at where you came from. With comments, what your init method should say is

@SuppressLint("NewApi")
public void init(...) {
    // make a call to check that the number of cameras is not 0
    parseServerInfo(receivedData);    
    // AND CONTINUE NO MATTER WHAT...
    prVideoDisplayHandler.removeCallbacks(prDisplayVideoTask);
    prVideoDisplayHandler.postDelayed(prDisplayVideoTask, prDelay);
}

What you need is

public boolean parseServerInfo(String data) {
    if (numCameras == 0) {
        Toast.makeText(mContext, "No stream detected!", Toast.LENGTH_LONG).show();

        // Finish is called here... AND FALSE IS RETURNED
        VideoPlayer videoplayer = (VideoPlayer) mContext;
        videoplayer.finish();
        return false;
    }
    return true;
}

then

@SuppressLint("NewApi")
public void init(...) {
    // make a call to check that the number of cameras is not 0
    // AND CONTINUE IF GOOD (TRUE)
    if(parseServerInfo(receivedData)){
        prVideoDisplayHandler.removeCallbacks(prDisplayVideoTask);
        prVideoDisplayHandler.postDelayed(prDisplayVideoTask, prDelay);
    }
}

this will parse your data, finish the activity if it should, and then stop progress with your SurfaceView init method. Sorry for so much redundant code but it is just easiest to explain :P

You have to reference the Activity which you would like to finish inside the SurfaceView . You get the context from the constructor of the SurfaceView class. Use this to finish() your activity, like so

//class member
private Context mContext;

public RenderView(...) {
    super(_context);

    //make the context accessible from the whole class
    this.mContext = _context;

    ...
}

Finally you call finish() on the that context to finish your VideoPlayer activity.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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