简体   繁体   中英

Android background activity disappears when coming back to the app

I have activity A and B both visible on screen at the same time.

A is a full screen activity, and B is a smaller dialog activity. B (the dialog) is on top of A and is currently active. A is visible below, but is paused.

There's a button in the B dialog which when clicked, takes the user out of the application with a share Intent , for example to Gmail. After going back to the application, the background full screen activity A is black and only the dialog activity is visible.

Is there a way to signal activity A to redraw itself when coming back into the application, without closing activity B (the dialog)?

Below is a screenshot of the screen before going out of the app. You can see both activities one over the other.

离开应用程序之前

Below is a screenshot of the screen after returning back to the app. You can see that the background activity is missing, while the dialog activity is still visible and OK.

回来后

I wonder if there's a way to signal the background activity to redraw itself without closing the dialog activity (startActivity won't do the trick, as the background activity would become foreground).

The definition of the background activity in AndroidManifest.xml is:

        <activity
            android:name="com.mypackage.thegame.GameActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:launchMode="singleTask"
            />

--- UPDATE ---

I think I know the reason for this, but still haven't succeeded with a workaround.

Activity A is not a standard activity built from XML definition. It is a pure SurfaceView activity. It creates a SurfaceView and directly calls setContent(mySurfaceView) . The surface view starts a thread onResume and kills it onPause . That's why when going back to the application the view doesn't starts drawing, as the onResume is not called.

However, I found that the onStart method is called and I placed code inside it to render just one frame of the current state in a separate thread (also tried in the thread where it's called). But it seems that the surface view cannot get the holder and canvas on which to draw... I'll continue investigating and post more details if discovered.

I finally did it. I'll describe my workaround in case someone happens to have the same issue.

Lifecycle methods of the background activity A are as follows:

App Launch

-> onCreate
-> onStart
-> onResume (drawing thread is started)

Dialog Activity B Launches

-> onPause (drawing thread is killed)

Leave App

---

Come back to App

-> onStart (nothing happens, drawing thread does not exist)

The only place where A may redraw itself is the onStart method. There I check if we're coming from Share and if so, I render just a single frame. The code in activity A looks something like this:

class MyActivity {
    public void onStart() {
        super.onStart();

        if (afterShare) {
            surfaceView.renderSingleFrame();
        }
    }
}

The hacky thing is that I loop and try to get the surface holder and canvas. If not successful, sleep for 50ms and try again a few times. It usually succeeds to take the holder on the second iteration.

The code to render a single frame is something like this:


public void renderSingleFrame() {
    Runnable runnable = new Runnable() {
        public void run() {
            int retry = 0;
            while(retry < 5) {
                if (!holder.getSurface().isValid()) {
                    retry++;  
                    try { Thread.sleep(50); } catch (InterruptedException e) {}  
                    continue;               
                }

                Canvas canvas = null;  

                try {  
                    canvas = holder.lockCanvas();  
                    if (canvas != null) {
                        this.drawFrame(canvas, 0); // canvas, deltaTime
                    }
                }  
                catch(Exception e) {}  
                finally {  
                    if (canvas != null && holder.getSurface().isValid()) {  
                        holder.unlockCanvasAndPost(canvas);  
                    } 
                }

                break;
            }
        }
    };

    Thread thread = new Thread(runnable);
    thread.start();
}

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