Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/216.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何检查活动是在前台还是在可见的后台?_Android_Android Activity_Dialog_Activity Finish - Fatal编程技术网

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时的情况。 事件的顺序是从下到上的,因此您可以看到在已调用活动B
onResume
之后调用了活动A
onStop


如果显示对话框,您的活动将在后台变暗,并且仅调用暂停时的
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