Android 如何检查活动是在前台还是在可见的后台?
我在计时器上有一个启动屏幕。我的问题是,在我Android 如何检查活动是在前台还是在可见的后台?,android,android-activity,dialog,activity-finish,Android,Android Activity,Dialog,Activity Finish,我在计时器上有一个启动屏幕。我的问题是,在我finish()我的活动之前,我需要检查下一个活动是否已经开始,因为会弹出一个系统对话框,我只想finish();一旦用户从对话框中选择了一个选项 我知道关于如何查看您的活动是否在前台有很多问题,但我不知道这是否也允许在活动顶部设置对话框 问题是,红色是我的活动,背景是对话,前景是对话: 编辑:我尝试过不使用finish(),但是我的活动可以回到我试图避免的应用程序堆栈中。您是否尝试过不调用finish,并将“android:noHistory=”t
finish()
我的活动之前,我需要检查下一个活动是否已经开始,因为会弹出一个系统对话框,我只想finish()
;一旦用户从对话框中选择了一个选项
我知道关于如何查看您的活动是否在前台有很多问题,但我不知道这是否也允许在活动顶部设置对话框
问题是,红色是我的活动,背景是对话,前景是对话:
编辑:我尝试过不使用
finish()
,但是我的活动可以回到我试图避免的应用程序堆栈中。您是否尝试过不调用finish,并将“android:noHistory=”true“在舱单上?这将阻止活动进入堆栈。我必须说,您的工作流不是标准的Android方式。在Android中,如果您想从Intent打开另一个活动,则不需要finish()
您的活动。为了方便用户,Android允许用户使用“后退”键从您打开到应用程序的活动返回
因此,只要让系统停止您的活动,并在您的活动被回调时保存所需的任何内容。这正是活动的
onPause
和onStop
事件之间的区别,如中所述
如果我理解正确,您要做的是从活动顶部调用finish()
,以终止它。
请参阅附件中的图像。这就是从活动A启动活动B时的情况。
事件的顺序是从下到上的,因此您可以看到在已调用活动BonResume
之后调用了活动AonStop
如果显示对话框,您的活动将在后台变暗,并且仅调用暂停时的
onPause
。如果暂停或恢复,请保存一个标志。如果你恢复,这意味着你在前台
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();
}
}
两种可能的解决办法:
1) 活动生命周期回调
使用实现并使用它跟踪应用程序中的活动生命周期事件的。请注意,ActivityLifecycleCallbacks适用于Android api>=14。对于以前的Android api,您需要自己在所有活动中实现它;-)
当您需要共享/存储活动状态时使用
2) 检查正在运行的进程信息
您可以使用此类检查正在运行的进程的状态
使用获取正在运行的进程列表
并筛选结果列表以检查所需的RunningAppProcessInfo并检查其“重要性”一种可能的解决方案可能是在显示系统对话框时设置标志,然后在活动生命周期的顶部方法中,检查标志,如果为真,则完成活动
public static boolean isActivityVisible(Activity mActivity) {
if (mActivity != null) {
Class klass = mActivity.getClass();
while (klass != null) {
try {
Field field = klass.getDeclaredField("mResumed");
field.setAccessible(true);
Object obj = field.get(mActivity);
return (Boolean)obj;
} catch (NoSuchFieldException exception1) {
Log.e(TAG, exception1.toString());
} catch (IllegalAccessException exception2) {
Log.e(TAG, exception2.toString());
}
klass = klass.getSuperclass();
}
}
return false;
}
例如,如果系统对话框是由某个buttonclick触发的,那么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
}
};
在活动的顶部:
@Override
protected void onStop() {
if(checkFlag){
finish();
}
super.onStop();
}
//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!
}
};
//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"));
为什么不使用广播呢?第二个活动(需要启动的活动)可以发送如下本地广播:
//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);
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) {}}
然后在splash活动中编写一个简单的接收器:
@Override
protected void onStop() {
if(checkFlag){
finish();
}
super.onStop();
}
//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!
}
};
//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注册新的接收器,以收听第二个活动中的广播:
@Override
protected void onStop() {
if(checkFlag){
finish();
}
super.onStop();
}
//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!
}
};
//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"));
请注意,您可以使用常量或字符串资源作为“广播标识符”字符串。这是建议的右侧解决方案: 正确的解决方案(归功于Dan、Commonware和NeTeInStEiN) 使用以下命令跟踪应用程序的可见性 Activity.onPause、Activity.onResume方法。存储“可见性”状态 在别的班。好的选择是您自己实现的 应用程序或服务(也有一些变体) 解决方案(如果您希望从服务中检查活动可见性) 示例 实现自定义应用程序类(请注意isActivityVisible()静态方法): 在AndroidManifest.xml中注册应用程序类: 在
finish()
方法中,您希望使用isActivityVisible()
检查活动是否可见。在那里,您还可以检查用户是否选择了选项。当两个条件都满足时继续
消息来源还提到了两个错误的解决方案…所以避免这样做
来源:如果您使用finish()
只是为了避免新应用程序在应用程序堆栈(任务)中启动,那么您可以在启动新应用程序时使用Intent.FLAG\u ACTIVITY\u new\u task
FLAG,并且根本不调用finish()
。根据,这是用于实现“启动器”样式行为的标志
// just add this line before you start an activity
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
我以前喜欢
如果活动不在前台
getIntent()
将返回null.:=P
使用暂停和从后台恢复之间的时间间隔来确定它是否从后台唤醒
在自定义应用程序中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");
}
在BaseActivity类中
@Override
protected void onResume() {
super.onResume();
MyApplication.activityResumed();
}
@Override
protected void onPause() {
super.onPause();
MyApplication.activityPaused();
}
如果目标是API级别14或以上,则可以使用
我已经在github上创建了一个项目
它使用非常简单的逻辑,适用于所有android API级别。我认为我有更好的解决方案。因为您可以简单地在MyApplication.activityResumed()中构建;每一项活动都有一个延伸 首先你必须创造(像控制论的WerkGuruorc) 接下来,您必须将应用程序类添加到AndroidManifest.xml
<application
android:name="your.app.package.MyApplication"
android:icon="@drawable/icon"
android:label="@string/app_name" >
<application
android:name=".AppController" />
最后,当您包装新活动时,您可以简单地通过ActivityBase而不是Activity来扩展它
public class Main extends ActivityBase {
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onPause() {
super.onPause();
}
}
对我来说,它是一种更好的方法,因为您只需记住关于ActivityBase扩展的内容。此外,您可以在将来扩展基本函数。在我的例子中,我为我的服务添加了接收器,并添加了有关netw的警报
<application
android:name=".AppController" />
AppController applicationControl = (AppController) getApplicationContext();
if(applicationControl.isActivityInForeground()){
Log.d("TAG","Activity is in foreground")
}
else
{
Log.d("TAG","Activity is in background")
}
class MyActivity extends Activity {
private AsyncTask<Void, Void, Void> myTask = new AsyncTask<Void, Void, Void>() {
// Don't do this! Inner classes implicitly keep a pointer to their
// parent, which in this case is the Activity!
}
}
class MyActivity extends Activity {
static class MyTask extends AsyncTask<Void, Void, Void> {
// Weak references will still allow the Activity to be garbage-collected
private final WeakReference<MyActivity> weakActivity;
MyTask(MyActivity myActivity) {
this.weakActivity = new WeakReference<>(myActivity);
}
@Override
public Void doInBackground(Void... params) {
// do async stuff here
}
@Override
public void onPostExecute(Void result) {
// Re-acquire a strong reference to the activity, and verify
// that it still exists and is active.
MyActivity activity = weakActivity.get();
if (activity == null
|| activity.isFinishing()
|| activity.isDestroyed()) {
// activity is no longer valid, don't do anything!
return;
}
// The activity is still valid, do main-thread stuff here
}
}
}
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);
SharedPreferences pref = context.getSharedPreferences(SHARED_PREF, 0);
SharedPreferences.Editor editor = pref.edit();
editor.putBoolean("is_activity_paused_a", true);
editor.commit();
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
}
}
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;
}
}
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);
}
}
val isActivityInForeground = activity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)
public static boolean isActivityVisible(Activity mActivity) {
if (mActivity != null) {
Class klass = mActivity.getClass();
while (klass != null) {
try {
Field field = klass.getDeclaredField("mResumed");
field.setAccessible(true);
Object obj = field.get(mActivity);
return (Boolean)obj;
} catch (NoSuchFieldException exception1) {
Log.e(TAG, exception1.toString());
} catch (IllegalAccessException exception2) {
Log.e(TAG, exception2.toString());
}
klass = klass.getSuperclass();
}
}
return false;
}
private static String instanceId = MainActivity.this.toString();
if(instanceId == null || instanceId.equals(MainActivity.this.toString()))
setVisibility(false);
//else: visibility stays unchanged