我有一个基于计时器的启动屏幕。我的问题是在调用 finish()
方法之前,我需要检查下一个活动是否已经启动,因为系统会弹出一个对话框,我只想在用户选择对话框选项后才调用 finish()
方法。
我知道有很多问题是关于如何判断活动是否在前台运行,但我不确定这是否适用于位于活动顶部的对话框。
这是问题所在,红色表示我的活动在后台,而对话框在前台:
编辑: 我尝试过不使用 finish()
方法,但是这样我的活动会在应用程序栈中被保留,我要避免这种情况发生。
我有一个基于计时器的启动屏幕。我的问题是在调用 finish()
方法之前,我需要检查下一个活动是否已经启动,因为系统会弹出一个对话框,我只想在用户选择对话框选项后才调用 finish()
方法。
我知道有很多问题是关于如何判断活动是否在前台运行,但我不确定这是否适用于位于活动顶部的对话框。
这是问题所在,红色表示我的活动在后台,而对话框在前台:
编辑: 我尝试过不使用 finish()
方法,但是这样我的活动会在应用程序栈中被保留,我要避免这种情况发生。
这是推荐的正确解决方案:
正确的解决方案(感谢Dan、CommonsWare和NeTeInStEiN)是通过使用Activity.onPause,Activity.onResume等方法来自己跟踪应用程序的可见性。在一些其他类中存储“可见性”状态。好的选择是你自己实现的Application或Service(如果您想从服务中检查活动的可见性,还有一些其它的变化形式可供选择)。
示例 实现自定义Application类(注意isActivityVisible()静态方法):
public class MyApplication extends Application {
public static boolean isActivityVisible() {
return activityVisible;
}
public static void activityResumed() {
activityVisible = true;
}
public static void activityPaused() {
activityVisible = false;
}
private static boolean activityVisible;
}
在AndroidManifest.xml中注册你的应用程序类:
<application
android:name="your.app.package.MyApplication"
android:icon="@drawable/icon"
android:label="@string/app_name" >
在项目中的每个Activity中添加onPause和onResume(如果您想要,您可以为您的Activities创建一个共同的祖先,但是如果您的Activity已经扩展自MapActivity/ListActivity等,则仍需要手动编写以下内容):
@Override
protected void onResume() {
super.onResume();
MyApplication.activityResumed();
}
@Override
protected void onPause() {
super.onPause();
MyApplication.activityPaused();
}
在您的finish()
方法中,您想使用isActivityVisible()
来检查活动是否可见。在那里,您还可以检查用户是否选择了选项。只有在满足这两个条件时才继续。
该来源还提到了两个错误的解决方案...所以要避免这样做。
onPause
、onStop
或onResume
事件。那么如果没有触发这些事件,你该怎么办呢?! - user4750643如果目标 API 级别为 14 或更高,则可以使用 android.app.Application.ActivityLifecycleCallbacks
。
public class MyApplication extends Application implements ActivityLifecycleCallbacks {
private static boolean isInterestingActivityVisible;
@Override
public void onCreate() {
super.onCreate();
// Register to be notified of activity state changes
registerActivityLifecycleCallbacks(this);
// ...
}
public boolean isInterestingActivityVisible() {
return isInterestingActivityVisible;
}
@Override
public void onActivityResumed(Activity activity) {
if (activity instanceof MyInterestingActivity) {
isInterestingActivityVisible = true;
}
}
@Override
public void onActivityStopped(Activity activity) {
if (activity instanceof MyInterestingActivity) {
isInterestingActivityVisible = false;
}
}
// Other state change callback stubs
// ...
}
activity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)
或者STARTED
放在这里,而不是使用INITIALIZED
,因为INITIALIZED
并不能保证应用在前台运行。 - htafoyalifecycle.addObserver(object : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (event == Lifecycle.Event.ON_RESUME || event == Lifecycle.Event.ON_START || event == Lifecycle.Event.ON_CREATE) {
Toast.makeText(this, "ON_RESUME", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this, "ON_PAUSE", Toast.LENGTH_SHORT).show()
}
}
})
- JavadActivity::hasWindowFocus() 返回你需要的布尔值。
public class ActivityForegroundChecker extends TimerTask
{
private static final long FOREGROUND_CHECK_PERIOD = 5000;
private static final long FIRST_DELAY = 3000;
private Activity m_activity;
private Timer m_timer;
public ActivityForegroundChecker (Activity p_activity)
{
m_activity = p_activity;
}
@Override
public void run()
{
if (m_activity.hasWindowFocus() == true) {
// Activity is on foreground
return;
}
// Activity is on background.
}
public void start ()
{
if (m_timer != null) {
return;
}
m_timer = new Timer();
m_timer.schedule(this, FIRST_DELAY, FOREGROUND_CHECK_PERIOD);
}
public void stop ()
{
if (m_timer == null) {
return;
}
m_timer.cancel();
m_timer.purge();
m_timer = null;
}
}
这是一个示例类,可以检查您的活动在任何地方的可见性。
请记住,如果您显示一个对话框,结果将为false,因为该对话框将具有主要焦点。除此之外,它非常方便,比建议的解决方案更可靠。
这正是活动的onPause
和onStop
事件之间的区别,如Activity类文档所述。
如果我理解你的意思正确,你想做的是从你的活动onStop
中调用finish()
来终止它。
请参见Activity生命周期演示应用程序的附加图像。当从活动A启动活动B时,它看起来就像这样。
事件的顺序是从下到上,因此您可以看到在已经调用了Activity B onResume
之后,Activity A onStop
被调用。
如果显示对话框,则您的活动会在后台变暗,只调用onPause
。
使用实现了ActivityLifecycleCallbacks的应用程序来跟踪您的应用程序中的活动生命周期事件。请注意,ActivityLifecycleCallbacks适用于Android api >= 14。对于早期的Android api,您需要在所有活动中自己实现它;-)
当您需要在活动之间共享/存储状态时,请使用应用程序。
我认为我有更好的解决方案。因为您可以通过一个扩展简单地将MyApplication.activityResumed(); 添加到每个Activity中。
首先,您需要创建(例如CyberneticTwerkGuruOrc)
public class MyApplication extends Application {
public static boolean isActivityVisible() {
return activityVisible;
}
public static void activityResumed() {
activityVisible = true;
}
public static void activityPaused() {
activityVisible = false;
}
private static boolean activityVisible;
}
<application
android:name="your.app.package.MyApplication"
android:icon="@drawable/icon"
android:label="@string/app_name" >
接着,创建一个名为ActivityBase的类
public class ActivityBase extends Activity {
@Override
protected void onPause() {
super.onPause();
MyApplication.activityPaused();
}
@Override
protected void onResume() {
super.onResume();
MyApplication.activityResumed();
}
}
public class Main extends ActivityBase {
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onPause() {
super.onPause();
}
}
对我来说,这是一种更好的方法,因为你只需要记住通过ActivityBase进行扩展即可。此外,您还可以在未来扩展基本函数。在我的情况下,我在一个类中添加了我的服务接收器和网络警报。
如果您想检查应用程序的可见性,可以简单地调用
MyApplication.isActivityVisible()
利用从后台暂停到恢复之间的时间差来判断应用是否从后台唤醒
在自定义应用中
private static boolean isInBackground;
private static boolean isAwakeFromBackground;
private static final int backgroundAllowance = 10000;
public static void activityPaused() {
isInBackground = true;
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (isInBackground) {
isAwakeFromBackground = true;
}
}
}, backgroundAllowance);
Log.v("activity status", "activityPaused");
}
public static void activityResumed() {
isInBackground = false;
if(isAwakeFromBackground){
// do something when awake from background
Log.v("activity status", "isAwakeFromBackground");
}
isAwakeFromBackground = false;
Log.v("activity status", "activityResumed");
}
@Override
protected void onResume() {
super.onResume();
MyApplication.activityResumed();
}
@Override
protected void onPause() {
super.onPause();
MyApplication.activityPaused();
}
如果您想知道应用程序的任何活动是否可见于屏幕上,您可以像这样操作:
public class MyAppActivityCallbacks implements Application.ActivityLifecycleCallbacks {
private Set<Class<Activity>> visibleActivities = new HashSet<>();
@Override
public void onActivityResumed(Activity activity) {
visibleActivities.add((Class<Activity>) activity.getClass());
}
@Override
public void onActivityStopped(Activity activity) {
visibleActivities.remove(activity.getClass());
}
public boolean isAnyActivityVisible() {
return !visibleActivities.isEmpty();
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}
@Override
public void onActivityStarted(Activity activity) {}
@Override
public void onActivityPaused(Activity activity) {}
@Override
public void onActivityDestroyed(Activity activity) {}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}}
class App extends Application{
@Override
public void onCreate() {
registerActivityLifecycleCallbacks(myAppActivityCallbacks);
}
}
然后你可以在任何地方使用你的MyAppActivityCallbacks实例的isAnyActivityVisible()方法!