61

Basically, this is what I'm doing

1) Set AlarmManager to execute BroadcastReceiver (BCR)

Intent intent = new Intent(m_Context, BCR.class);  
intent.putExtras(extras);  
PendingIntent pendingIntent = PendingIntent.getBroadcast(m_Context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);  
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, StartTime, pendingIntent)  

2) Start MyActivity from BCR

@Override  
public void onReceive(Context context, Intent intent) {  
    Intent newIntent = new Intent(context, MyActivity.class);
    newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);  
    context.startActivity(newIntent);  
}

3) Have MyActivity turn on the screen if its not on

@Override  
public void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState); 
    getWindow().addFlags(LayoutParams.FLAG_DISMISS_KEYGUARD);
    getWindow().addFlags(LayoutParams.FLAG_SHOW_WHEN_LOCKED);
    getWindow().addFlags(LayoutParams.FLAG_TURN_SCREEN_ON);
    setContentView(R.layout.myactivity);  
} 

@Overide  
protected void onNewIntent(Intent intent) {  
    super.onNewIntent(intent);  
}  

For some reason, I notice that right when MyActivity is opened, it's flow goes like:

onCreate/onNewIntent -> onResume -> onPause -> onResume

I'm not sure why it does an onPause right away. I notice this only happens when the screened is being turned on by the flags. Does anyone know why this happens? Is there any way this behavior can be prevented?

4

19 回答 19

35

以防万一其他人遇到这种情况,我似乎只有在我通过 XML 布局在活动内膨胀片段时才注意到这种行为。我不知道这种行为是否也发生在 Fragments 的兼容性库版本中(我使用的是 android.app.Fragment)

似乎活动会在调用任何添加的片段Activity#onResume之前调用一次Fragment#onResume,然后Activity#onResume再次调用。

  1. 活动:onCreate
  2. 片段:onAttach
  3. 活动:onAttachFragments
  4. 片段:onCreate
  5. 活动:onStart
  6. 活动: onResume
  7. 片段:onResume
  8. 活动: onResume
于 2013-11-04T21:09:29.913 回答
33

如果您每次都尝试请求权限可能会导致此类问题,请检查您是否已授予它们

requestPermissions可能导致它:

onCreate
onStart
onResume
onPause
onResume

使用此方法ContextCompat.checkSelfPermission(context, permission)在请求之前检查是否已授予权限

此方法返回int,您可以使用PackageManager.PERMISSION_GRANTED常量检查它

于 2018-04-05T18:54:30.683 回答
17

如果你有ES File Explorer然后强制停止它。不知何故,它们打断了您的应用程序的生命周期(评论建议某种覆盖)

onResume出现两次的问题是因为onPause在创建活动后以某种方式被调用.. 有东西打断了我的应用程序。

在安装后第一次打开或从工作室构建后才会发生。

我从另一篇文章中得到了线索,发现这是因为 ES File Explorer。为什么 onResume() 似乎被调用了两次?

一旦我强制停止 ES File Explorer,这种打嗝行为就不再发生......在尝试了许多其他提议的解决方案后知道这令人沮丧。所以要提防任何其他像这样的中断应用程序。

于 2016-08-02T17:12:08.783 回答
7

我对此进行了一段时间的研究,因为在互联网上没有提到这种奇怪的行为。我没有解决方案如何克服这种阴暗面的行为,但我发现了一个确切的场景,当它确实发生时。

onPause-onResume-onPause-onResume每次都会发生,当应用程序在安装后第一次启动时。您可以通过对代码进行任何更改并从 IDE 重新运行(包括重新编译)应用程序来简单地调用此行为。

无论您是否使用 AppCompat 库。我已经测试了这两种情况,并且行为仍在继续。

注意:在 Android Marshmallow 上测试。

我从这个线程中借用了关于片段和活动生命周期的代码,在这里(只需复制、粘贴、在清单中声明活动并运行 Forest run):

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class TestActivity extends Activity {

    private static final String TAG = "ACTIVITY";

    public TestActivity() {
        super();
        Log.d(TAG, this + ": this()");
    }

    protected void finalize() throws Throwable {
        super.finalize();
        Log.d(TAG, this + ": finalize()");
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, this + ": onCreate()");


        TextView tv = new TextView(this);
        tv.setText("Hello world");
        setContentView(tv);

        if (getFragmentManager().findFragmentByTag("test_fragment") == null) {
            Log.d(TAG, this + ": Existing fragment not found.");
            FragmentTransaction ft = getFragmentManager().beginTransaction();
            ft.add(new TestFragment(), "test_fragment").commit();
        } else {
            Log.d(TAG, this + ": Existing fragment found.");
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.d(TAG, this + ": onStart()");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d(TAG, this + ": onResume()");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.d(TAG, this + ": onPause()");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.d(TAG, this + ": onStop()");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, this + ": onDestroy()");
    }


    public static class TestFragment extends Fragment {

        private static final String TAG = "FRAGMENT";

        public TestFragment() {
            super();
            Log.d(TAG, this + ": this() " + this);
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d(TAG, this + ": onCreate()");
        }


        @Override
        public void onAttach(final Context context) {
            super.onAttach(context);
            Log.d(TAG, this + ": onAttach(" + context + ")");
        }

        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            Log.d(TAG, this + ": onActivityCreated()");
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            Log.d(TAG, this + ": onCreateView()");
            return null;
        }

        @Override
        public void onViewCreated(View view, Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            Log.d(TAG, this + ": onViewCreated()");
        }

        @Override
        public void onDestroyView() {
            super.onDestroyView();
            Log.d(TAG, this + ": onDestroyView()");
        }

        @Override
        public void onDetach() {
            super.onDetach();
            Log.d(TAG, this + ": onDetach()");
        }

        @Override
        public void onStart() {
            super.onStart();
            Log.d(TAG, this + ": onStart()");
        }

        @Override
        public void onResume() {
            super.onResume();
            Log.d(TAG, this + ": onResume()");
        }

        @Override
        public void onPause() {
            super.onPause();
            Log.d(TAG, this + ": onPause()");
        }

        @Override
        public void onStop() {
            super.onStop();
            Log.d(TAG, this + ": onStop()");
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.d(TAG, this + ": onDestroy()");
        }
    }

}
于 2016-02-03T01:02:17.773 回答
5

我不确定发生了什么,但我怀疑您的活动正在重新启动,因为设置屏幕被系统视为配置更改。您可以尝试在每次调用时记录配置,onResume以查看是否发生了这种情况,如果是,实际发生了什么变化。然后,您可以修改清单以告诉系统您的活动将自行处理更改。

protected void onResume() [
    super.onResume();
    Configuration config = new Configuration();
    config.setToDefaults();
    Log.d("Config", config.toString());
    . . .
}
于 2013-04-16T00:30:26.157 回答
3

我有类似的问题。我的情况是下一个 CurrentActivity extends MainActivity CurrentFragment extends MainFragment

我像往常一样带着意图打开CurrentActivity 。在 onCreate CurrentAcitivity中,我替换了 CurrentFragment。

生命周期是:1. onResume MainActivity 2. onResume CurrentActivity 3. onResume MainFragment 4. onResume CurrentFragment

自动调用 onPause,然后再次调用

  1. onResume MainActivity
  2. onResume 当前活动
  3. onResume MainFragment
  4. onResume 当前片段

我决定重新测试所有内容,经过几个小时的尝试和玩耍,我发现了根本问题。在 MainFragment onStart 中,我每次都调用 startActivityForResult(在我的情况下是用于打开 Wifi 的 android 弹出窗口),在 MainFragment 上调用 onPause。我们都知道,在 onPause 之后下一个是 onResume。

所以它不是 Android 错误,它只是我的 :-)

快乐的生命周期调试!

于 2017-04-20T23:07:38.243 回答
1

我也遇到了这个 onresume-onpause-onresume 序列(在 4.1.2 及更高版本上,但我在 2.3 上没有遇到过这种情况)。我的问题与唤醒锁处理有关:我不小心忘记释放唤醒锁并重新获取它导致错误消息“WakeLock 在仍被持有时已完成”。此问题导致在 onResume 之后立即调用 onPause 并导致错误行为。

我的建议是:检查日志中的错误,这些错误可能与此问题有关。

另一个提示:打开屏幕可能比简单地使用窗口标志更棘手。您可能想在此处查看此答案 - 它建议您设置一个接收器以检查屏幕是否已打开并仅在以下之后启动所需的活动:https ://stackoverflow.com/a/16346369/875442

于 2014-01-20T15:16:00.973 回答
0

似乎Activity从支持库中使用会自动保存和恢复实例。savedInstanceState因此,只有在是时才做你的工作null

于 2014-05-14T19:43:50.533 回答
0

我有一个类似的问题,我的问题是在 onCreate() 方法中,我正在做:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    super.setContentView(R.layout.friends);  <-- problem
}

我对“超级”的呼唤。触发了 onResume() 两次。在我将其更改为以下内容后,它按预期工作:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.friends);  <-- 'super.' removed
}

希望能帮助到你。

于 2015-01-31T21:40:27.853 回答
0

我确信这发生在我的应用程序中,直到我意识到我已经种植了两棵 Jake Wharton 的木材树,并且 onResume() 只是被记录了两次,而不是被调用了两次。

于 2020-12-16T15:38:29.600 回答
0

Basically a lot of stuff can trigger this. Some resume processes that loses focus can do it. A few apps will cause it to happen too. The only way to cope is to block the double running. Note, this will also have an errant pause thrown in for good measure.

    boolean resumeblock = false;

    @Override
    protected void onResume() {
        super.onResume();
        sceneView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                sceneView.getViewTreeObserver().removeOnPreDrawListener(this);
                if (resumeblock) return false;
                resumeblock = true;

                //Some code.

                return false;
            }
        });
    }

This is a solid way to prevent such things. It will block double resumes. But, it will also block two resumes that preserve the memory. So if you just lost focus and it doesn't need to rebuild your stuff. It will block that too. Which might be a benefit clearly, since if you're using the resume to control some changes over focus, you only actually care if you need to rebuild that stuff because of focus. Since the pre-draw listeners can only be called by the one thread and they must be called in sequence, the code here will only run once. Until something properly destroys the entire activity and sets resumeblock back to false.

于 2017-06-14T15:58:33.150 回答
0

由于在of中设置了UiMode,我遇到了同样的问题。更改主题触发了娱乐并对和进行了两次调用。onCreate()MainActivityactivityonPause()onStart()

于 2020-07-06T15:01:43.713 回答
0

我没有看到这个问题的充分答案,所以我决定了这个。

从我的笔记:“似乎活动运行 onResume() onPause() 然后再次 onResume。运行的最后一个方法是 onSizeChanged()。所以一个好的做法是仅在 onSizeChanged() 方法之后启动线程被处决了。”

所以你可以: 记录每个运行的方法。确定最后运行的方法。确保您有一个初始化为 false 的布尔值,并且仅在最后一个方法运行后才更改为 true。然后,一旦您检查布尔值是否为真,您就可以开始所有线程操作。

- 对于任何想知道的人:我正在使用一个表面视图,它有一个最后执行的 onSizeChanged() 方法。

于 2020-01-05T06:31:43.037 回答
0

我有同样的问题。我的是运行时的这段代码

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

我只是把它放在清单中

android:screenOrientation="landscape"

没有更多关于两次调用 onCreate 和 onResume 的问题。

于 2018-12-07T16:39:15.310 回答
0

您是否尝试过在调用方法getWindow().addFlags(...)之前调用您super.onCreate(savedInstanceState)onCreate方法?

我有一个类似的问题。当我看起来像这样onResume时被调用了两次:onCreate

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
    setContentView(R.layout.main);
    ...
}

将其更改为:

@Override
public void onCreate(Bundle savedInstanceState) {

    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);

    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    ...
}

...解决了问题。

于 2020-11-30T16:48:28.137 回答
0

我刚刚遇到了这个问题,似乎一般来说getWindow().addFlags()调整Window属性可能是罪魁祸首。

当我的代码是这样的

@Override
protected void onCreate(Bundle savedInstanceState) {
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_generic_fragment_host);
    // performing fragment transaction when instance state is null...

onResume()被触发两次,但是当我删除时requestWindowFeature(),它只被调用一次。

于 2016-01-08T20:48:52.493 回答
0

正如@TWL 所说, ES File Explorer 对我来说是个问题!卸载应用程序解决了这个问题。安装此 ES 文件资源管理器时,onStart() -> onResume() -> onPause() -> onResume().. 是问题所在。 onResume()被称为2'ce。

于 2018-11-09T16:02:21.850 回答
0

我认为你应该看看这个问题: Nexus 5 进入睡眠模式会使活动生命周期出现问题 你应该找到线索

于 2016-03-21T19:48:01.183 回答
-1

我也遇到了这个问题,这是因为碎片..您在活动中拥有的碎片数量onResume()将调用该次数。为了克服我在SharedPrefrences

于 2017-07-14T09:20:48.787 回答