回到应用程序时,Android 后台活动消失

Posted

技术标签:

【中文标题】回到应用程序时,Android 后台活动消失【英文标题】:Android background activity disappears when coming back to the app 【发布时间】:2020-03-12 10:23:04 【问题描述】:

我的活动AB 同时在屏幕上可见。

A 是全屏活动,B 是较小的对话活动。 B(对话框)位于A 之上,当前处于活动状态。 A 在下方可见,但已暂停。

B 对话框中有一个按钮,单击该按钮后,用户将退出应用程序并共享 Intent,例如 Gmail。回到应用后,后台全屏activityA为黑色,只有对话框activity可见。

有没有办法在不关闭活动B(对话框)的情况下,在返回应用程序时向活动A 发出信号以重绘自身?

下面是退出应用程序之前的屏幕截图。您可以同时看到这两种活动。

以下是返回应用程序后的屏幕截图。可以看到后台Activity不见了,而对话框Activity依然可见且OK。

我想知道是否有一种方法可以在不关闭对话框活动的情况下指示后台活动重绘自身(startActivity 无法做到这一点,因为后台活动会变成前台)。

androidManifest.xml中后台activity的定义是:

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

--- 更新 ---

我想我知道这其中的原因,但仍然没有成功的解决方法。

Activity A 不是根据 XML 定义构建的标准 Activity。这是一个纯粹的SurfaceView 活动。它创建一个SurfaceView 并直接调用setContent(mySurfaceView)。表面视图启动线程onResume 并杀死它onPause。这就是为什么当返回应用程序时,视图不会开始绘制,因为没有调用 onResume

但是,我发现调用了 onStart 方法,我在其中放置了代码,以便在单独的线程中仅呈现当前状态的一帧(也在调用它的线程中尝试过)。但似乎表面视图无法获得holder 和要在其上绘制的画布......如果发现,我将继续调查并发布更多详细信息。

【问题讨论】:

这毫无意义。所有设备都会出现这种情况吗? 实际上,如果Android在启动GMail的时候杀死了你应用的OS进程,那么在从GMail返回到你的应用后,Android会创建一个新的OS进程并重新实例化位于顶部的Activity堆栈(在本例中为以对话框为主题的Activity)。这可能就是你所看到的。要检查这一点,请在两个活动中将日志记录添加到 onCreate()onPause()onResume() 以查看发生了什么。 它发生在所有设备上,我想我知道是什么原因,但我仍然没有成功解决方法。我会在上面的问题中写一个更新。 这不是活动的正常用法。我认为您应该创建由 1 个活动托管的 2 个不同片段,因此您可以轻松管理 2 个屏幕。 如果我无法做到这一点,我可以尝试使用片段的这种方法,谢谢你的想法。但是为什么你认为活动的这种用法不合适呢?有 2 个重叠的活动似乎很好,其中一个较小 - 它可能看起来像一个对话框,或者它可能只是另一个覆盖组件。代码是遗留的,它的开发在引入片段之前就已经开始了,并且有两个这样的活动在概念上似乎并不正确。 Android Toolkit 也允许这样做,但似乎我不知道如何正确处理这种情况。 【参考方案1】:

我终于做到了。我将描述我的解决方法,以防有人碰巧遇到同样的问题。

后台ActivityA的生命周期方法如下:

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)

A 唯一可以重绘自身的地方是onStart 方法。在那里我检查我们是否来自 Share,如果是,我只渲染一个帧。活动A 中的代码如下所示:

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

        if (afterShare) 
            surfaceView.renderSingleFrame();
        
    

奇怪的是,我循环并尝试获取表面支架和画布。如果不成功,睡眠 50ms,然后再试几次。通常第二次迭代就可以成功拿下持有者。

渲染单帧的代码是这样的:


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();


【讨论】:

以上是关于回到应用程序时,Android 后台活动消失的主要内容,如果未能解决你的问题,请参考以下文章

Android:将数据保存到服务器以避免活动破坏

Android 屏幕方向:横向回到纵向

将App发送回最近的应用程序堆栈android

Home 按键行为

每次应用程序来自android的后台时启动第一个屏幕

一段时间后滞后 Android 应用