我有一个基于计时器的启动屏幕。我的问题是在调用 finish()
方法之前,我需要检查下一个活动是否已经启动,因为系统会弹出一个对话框,我只想在用户选择对话框选项后才调用 finish()
方法。
我知道有很多问题是关于如何判断活动是否在前台运行,但我不确定这是否适用于位于活动顶部的对话框。
这是问题所在,红色表示我的活动在后台,而对话框在前台:
编辑: 我尝试过不使用 finish()
方法,但是这样我的活动会在应用程序栈中被保留,我要避免这种情况发生。
我有一个基于计时器的启动屏幕。我的问题是在调用 finish()
方法之前,我需要检查下一个活动是否已经启动,因为系统会弹出一个对话框,我只想在用户选择对话框选项后才调用 finish()
方法。
我知道有很多问题是关于如何判断活动是否在前台运行,但我不确定这是否适用于位于活动顶部的对话框。
这是问题所在,红色表示我的活动在后台,而对话框在前台:
编辑: 我尝试过不使用 finish()
方法,但是这样我的活动会在应用程序栈中被保留,我要避免这种情况发生。
可以通过使用Application.ActivityLifecycleCallbacks的高效方式来实现这一点。
例如,假设Activity类名为ProfileActivity,我们需要查找它是在前台还是后台运行。
首先,我们需要通过扩展Application Class来创建我们的应用程序类。
它实现了:
Application.ActivityLifecycleCallbacks
让我们把我的应用程序类定义如下:
应用程序类
public class AppController extends Application implements Application.ActivityLifecycleCallbacks {
private boolean activityInForeground;
@Override
public void onCreate() {
super.onCreate();
//register ActivityLifecycleCallbacks
registerActivityLifecycleCallbacks(this);
}
public static boolean isActivityVisible() {
return activityVisible;
}
public static void activityResumed() {
activityVisible = true;
}
public static void activityPaused() {
activityVisible = false;
}
private static boolean activityVisible;
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
//Here you can add all Activity class you need to check whether its on screen or not
activityInForeground = activity instanceof ProfileActivity;
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
public boolean isActivityInForeground() {
return activityInForeground;
}
}
@Override
public void onActivityResumed(Activity activity) {
//Here you can add all Activity class you need to check whether its on screen or not
activityInForeground = activity instanceof ProfileActivity;
}
可以在屏幕上找到当前显示的所有活动实例,只需通过上述方法检查您的活动是否在屏幕上。
在manifest.xml中注册您的应用程序类。
<application
android:name=".AppController" />
根据上述解决方案检查Activity是前台还是后台,请在需要检查的位置调用以下方法
AppController applicationControl = (AppController) getApplicationContext();
if(applicationControl.isActivityInForeground()){
Log.d("TAG","Activity is in foreground")
}
else
{
Log.d("TAG","Activity is in background")
}
这里是否可以使用Activity.onWindowFocusChanged(boolean hasFocus)
方法?再加上一个类级别的标志,例如isFocused
由onWindowFocusChanged
设置,这将是一种简单的方式,在您的活动的任何时刻告诉它是否处于焦点状态。从阅读文档来看,它似乎会在任何情况下正确地设置为“false”,其中活动不直接处于物理“前景”,例如如果显示对话框或下拉通知托盘。
示例:
boolean isFocused;
@Override
void onWindowFocusChanged (boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
isFocused = hasFocus;
}
void someMethod() {
if (isFocused) {
// The activity is the foremost object on the screen
} else {
// The activity is obscured or otherwise not visible
}
}
如果您已暂停或恢复,请保存一个标志。如果您已恢复,则表示您在前台。
boolean isResumed = false;
@Override
public void onPause() {
super.onPause();
isResumed = false;
}
@Override
public void onResume() {
super.onResume();
isResumed = true;
}
private void finishIfForeground() {
if (isResumed) {
finish();
}
}
private static String instanceId = MainActivity.this.toString();
if(instanceId == null || instanceId.equals(MainActivity.this.toString()))
setVisibility(false);
//else: visibility stays unchanged
SharedPreferences pref = context.getSharedPreferences(SHARED_PREF, 0);
SharedPreferences.Editor editor = pref.edit();
editor.putBoolean("is_activity_paused_a", true);
editor.commit();
我认为这是跟踪活动可见性的可靠方法。
Application
类的解决方案。public class AppSingleton extends Application implements Application.ActivityLifecycleCallbacks {
private WeakReference<Context> foregroundActivity;
@Override
public void onActivityResumed(Activity activity) {
foregroundActivity=new WeakReference<Context>(activity);
}
@Override
public void onActivityPaused(Activity activity) {
String class_name_activity=activity.getClass().getCanonicalName();
if (foregroundActivity != null &&
foregroundActivity.get().getClass().getCanonicalName().equals(class_name_activity)) {
foregroundActivity = null;
}
}
//............................
public boolean isOnForeground(@NonNull Context activity_cntxt) {
return isOnForeground(activity_cntxt.getClass().getCanonicalName());
}
public boolean isOnForeground(@NonNull String activity_canonical_name) {
if (foregroundActivity != null && foregroundActivity.get() != null) {
return foregroundActivity.get().getClass().getCanonicalName().equals(activity_canonical_name);
}
return false;
}
}
您可以像下面这样简单地使用它:
((AppSingleton)context.getApplicationContext()).isOnForeground(context_activity);
//put this in onCreate(..) or any other lifecycle method that suits you best
//notice the string sent to the intent, it will be used to register a receiver!
Intent result = new Intent("broadcast identifier");
result.putString("some message");//this is optional
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(result);
然后在启动页活动中编写一个简单的接收器:
//this goes on the class level (like a class/instance variable, not in a method) of your splash activity:
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//kill activity here!!!
//mission accomplished!
}
};
然后,使用LocalBroadcastManager注册新接收器以侦听来自第二个活动的广播:
//notice the string sent to the intent filter, this is where you tell the BroadcastManager which broadcasts you want to listen to!
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(receiver, new IntentFilter("broadcast identifier"));
LocalBroadcastManager
。 - Alexander Farberfinish()
,则可以在启动新应用程序时使用Intent.FLAG_ACTIVITY_NEW_TASK
标志,并且根本不调用finish()
。根据文档,这是要用于实现“启动器”样式行为的标志。// just add this line before you start an activity
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
可能的解决方案之一是在显示系统对话框时设置一个标志,然后在活动生命周期的onStop方法中检查该标志,如果为真,则结束活动。
例如,如果系统对话框是由某个按钮点击触发的,则onclick监听器可能如下:
private OnClickListener btnClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
CheckActivity.this.startActivity(Intent.createChooser(intent, "Complete action using"));
checkFlag = true; //flag used to check
}
};
并且在活动的 onStop 方法中:
@Override
protected void onStop() {
if(checkFlag){
finish();
}
super.onStop();
}