unity黑屏现状问题总结

2019-05-28  本文已影响0人  weiinter105

总结下unity的游戏接sdk时的黑屏问题现状

现象:

目前黑屏有两种情况:

1. 点击登录面板,从面板中点击跳到三方界面或者跳到第三个界面;再点击返回键时会出现下面的游戏界面黑屏;

2. 点击登录面板之后,按桌面键返回桌面;然后再从最近任务键进入会发现下面的游戏界面黑屏;

原因:

以第一种情况为例,一般情况下出现:

05-28 10:27:04.642  1000  2154  3441 I am_create_activity: [0,41511060,4450,com.ss.android.ugc.aweme/.openauthorize.AwemeAuthorizedActivity,NULL,NULL,NULL,872448000]`

05-28 10:27:04.642  1000  2154  3441 I wm_task_moved: [4450,0,2147483647]`

05-28 10:27:04.649  1000  2154  3441 I am_pause_activity: [25025,39231624,com.hermes.fgame/com.bytedance.ttgame.sdk.module.account.login.ui.LoginActivity,userLeaving=true]`

05-28 10:27:04.654 10454 25025 25025 I am_on_paused_called: [0,com.bytedance.ttgame.sdk.module.account.login.ui.LoginActivity,performPause]`

05-28 10:27:04.663  1000  2154  3329 I am_proc_bound: [0,25874,com.ss.android.ugc.aweme:push]`

05-28 10:27:04.715  1000  2154  3441 I configuration_changed: 536872064`

05-28 10:27:04.778  1000  2154  2194 I am_stop_activity: [0,214407528,com.hermes.fgame/.SDKBridgeActivity]`

05-28 10:27:04.793  1000  2154  2194 I sysui_count: [window_time_0,7]`

`05-28 10:27:04.793  1000  2154  2194 I sysui_multi_action: [757,803,799,window_time_0,802,7]`

05-28 10:27:04.804 10454 25025 25025 I am_on_stop_called: [0,com.hermes.fgame.SDKBridgeActivity,STOP_ACTIVITY_ITEM]`

05-28 10:27:05.975 10421 25905 25905 I am_on_resume_called: [0,com.ss.android.ugc.aweme.openauthorize.AwemeAuthorizedActivity,RESUME_ACTIVITY]`

黑屏的原因是游戏界面调用了onstop,则会出现黑屏;直到其重新调用onResume才能重新可见;

想法:

1. 在stop的时候调用onResume

2. 想办法起到三方授权界面的时候不调用onstop

3. 想办法只生成一个界面

方案1已经被游戏否决了,其实也能理解;改变Activity的生命周期总是要承担很大的风险的,那么方案2和方案3

方案2:如何使调起三方授权界面时不再调用unity游戏界面的onstop


`1554    private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {`

`1555        ActivityRecord prev = mPausingActivity;`

`1556        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);`

`1557`

`1558        if (prev != null) {`

`1559            prev.setWillCloseOrEnterPip(false);`

`1560            final boolean wasStopping = prev.isState(STOPPING);`

`1561            prev.setState(PAUSED, "completePausedLocked");`

`1562            if (prev.finishing) {`

`1563                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);`

`1564                prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false,`

`1565                        "completedPausedLocked");`

`1566            } else if (prev.app != null) {`

`1567                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev`

`1568                        + " wasStopping=" + wasStopping + " visible=" + prev.visible);`

`1569                if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(prev)) {`

`1570                    if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE,`

`1571                            "Complete pause, no longer waiting: " + prev);`

`1572                }`

`1573                if (prev.deferRelaunchUntilPaused) {`

`1574                    // Complete the deferred relaunch that was waiting for pause to complete.`

`1575                    if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);`

`1576                    prev.relaunchActivityLocked(false /* andResume */,`

`1577                            prev.preserveWindowOnDeferredRelaunch);`

`1578                } else if (wasStopping) {`

`1579                    // We are also stopping, the stop request must have gone soon after the pause.`

`1580                    // We can't clobber it, because the stop confirmation will not be handled.`

`1581                    // We don't need to schedule another stop, we only need to let it happen.`

`1582                    prev.setState(STOPPING, "completePausedLocked");`

`1583                } else if (!prev.visible || shouldSleepOrShutDownActivities()) {`

`1584                    // Clear out any deferred client hide we might currently have.`

`1585                    prev.setDeferHidingClient(false);`

`1586                    // If we were visible then resumeTopActivities will release resources before`

`1587                    // stopping.`

`1588                    addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */);`

`1589                }`

`1590            } else {`

`1591                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev);`

`1592                prev = null;`

`1593            }`

`1594            // It is possible the activity was freezing the screen before it was paused.`

`1595            // In that case go ahead and remove the freeze this activity has on the screen`

`1596            // since it is no longer visible.`

`1597            if (prev != null) {`

`1598                prev.stopFreezingScreenLocked(true /*force*/);`

`1599            }`

`1600            mPausingActivity = null;`

`1601        }`

`1602`

`1603        if (resumeNext) {`

`1604            final ActivityStack topStack = mStackSupervisor.getFocusedStack();`

`1605            if (!topStack.shouldSleepOrShutDownActivities()) {`

`1606                mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);`

`1607            } else {`

`1608                checkReadyForSleep();`

`1609                ActivityRecord top = topStack.topRunningActivityLocked();`

`1610                if (top == null || (prev != null && top != prev)) {`

`1611                    // If there are no more activities available to run, do resume anyway to start`

`1612                    // something. Also if the top activity on the stack is not the just paused`

`1613                    // activity, we need to go ahead and resume it to ensure we complete an`

`1614                    // in-flight app switch.`

`1615                    mStackSupervisor.resumeFocusedStackTopActivityLocked();`

`1616                }`

`1617            }`

`1618        }`

`1619`

`1620        if (prev != null) {`

`1621            prev.resumeKeyDispatchingLocked();`

`1622`

`1623            if (prev.app != null && prev.cpuTimeAtResume > 0`

`1624                    && mService.mBatteryStatsService.isOnBattery()) {`

`1625                long diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)`

`1626                        - prev.cpuTimeAtResume;`

`1627                if (diff > 0) {`

`1628                    BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();`

`1629                    synchronized (bsi) {`

`1630                        BatteryStatsImpl.Uid.Proc ps =`

`1631                                bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,`

`1632                                        prev.info.packageName);`

`1633                        if (ps != null) {`

`1634                            ps.addForegroundTimeLocked(diff);`

`1635                        }`

`1636                    }`

`1637                }`

`1638            }`

`1639            prev.cpuTimeAtResume = 0; // reset it`

`1640        }`

`1641`

`1642        // Notify when the task stack has changed, but only if visibilities changed (not just`

`1643        // focus). Also if there is an active pinned stack - we always want to notify it about`

`1644        // task stack changes, because its positioning may depend on it.`

`1645        if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause`

`1646                || getDisplay().hasPinnedStack()) {`

`1647            mService.mTaskChangeNotificationController.notifyTaskStackChanged();`

`1648            mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;`

`1649        }`

`1650`

`1651        mStackSupervisor.ensureActivitiesVisibleLocked(resuming, 0, !PRESERVE_WINDOWS);`

`1652    }`

想要不被stop那么不能被调用到addToStopping;这就有两种可能

1. 使unity activity调用relaunch的逻辑

prev.relaunchActivityLocked(false /* andResume */, prev.preserveWindowOnDeferredRelaunch);

2. 使unity Activity的visable属性为true

结论

1. 经调研不太好实现,因为unity实现了对所有config change的监听以便于属性变化时及时变化游戏界面

2. 需要三方配合;将三方授权界面Activity的fullscreen属性置为false;如写成Dialog style的形式

经试验,方案2对情况1可行;缺点: 1. 需要授权sdk方的配合 2.对情况2还是没办法解决;

方案3; 将游戏activity和登陆面板合并,将登陆面板以Dialog形式显示,依附于游戏unity activity,此时两种情况应该都能解决; 缺点:改动太大;对于sdk限制也太大

业内方案:

想了下,想要根治这个问题可能只能讲登陆面板置位dialog形式;但是这种方式局限太大了,业界的sdk不可能都是以style形式实现的吧?至少我接的uc渠道就有这个问题;

因此用unity demo继承下uc的sdk,发现情况1和情况2都能复现

bilibili黑屏情况1.jpg uc黑屏情况2.jpg

因此这个问题确实也是正常的,属于AMS管理Activity的生命周期的正常逻辑

结论:

  1. 如果要有两个Activity;那么点击登录面板之后,按桌面键返回桌面;然后再从最近任务键进入游戏界面黑屏;

  2. 如果有三个activity,且第三个activity为全屏的,那么返回时如果登陆面板不自动取消,那么就会出现unity activity的黑屏;同时,个人认为三方授权界面不要写成fullscreen格式的比较好

上一篇下一篇

猜你喜欢

热点阅读