我有一个计时器启动画面。我的问题是,在我finish()
我的活动我需要检查下一个活动已经开始,因为一个系统对话框弹出,而我只想finish()
;一旦用户选择了从对话框中的选项?
我知道,有就怎么看,如果你的活动是在前台的许多问题,但我不知道是否该允许对话盒上的活动之上了。
这里的问题是,红色是我的活动是在后台对话是在前台:
编辑:我曾尝试只是不使用finish()
但后来我的活动可以在我正努力避免应用程序堆栈中回到了。
这是被推荐为正确的解决方案:
正确的解决方案(学分去丹,CommonsWare和NeTeInStEiN)使用Activity.onPause,Activity.onResume方法你自己的应用程序的轨道知名度。在其它的类商店“知名度”的地位。比较好的选择是自己执行应用程序或服务的(也有这种解决方案的一些变化,如果你想从服务检查活动的可见性)。
例如实现自定义应用程序类(注意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" >
添加的onPause和的onResume每一个活动项目(您可能为您的活动的共同祖先,如果你想,但如果你的活动已经从MapActivity / ListActivity等扩展,你仍然需要手工编写以下) :
@Override
protected void onResume() {
super.onResume();
MyApplication.activityResumed();
}
@Override
protected void onPause() {
super.onPause();
MyApplication.activityPaused();
}
在你finish()
方法,你想用isActivityVisible()
以检查活动是否可见。在那里,你也可以检查,如果用户选择一个选项或没有。在满足这两个条件继续。
该人士还提到了两种错误的做法解决方案......所以要避免这样做。
这可以通过使用Application.ActivityLifecycleCallbacks以高效的方式实现这一目标
例如让我们的活动类名作为ProfileActivity可以发现其是否在前台或后台
首先,我们需要通过扩展qazxsw POI创建应用程序类
它实现
Application.ActivityLifecycleCallbacks
让我的应用程序类,如下所示
应用类
Application Class
在上面的类有onActivityResumed ActivityLifecycleCallbacks的倍率methord
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;
}
}
其中,这是目前在屏幕上显示的所有活动实例可以发现,只需要检查你的活动是否在屏幕上或不按上述方法。
在注册的manifest.xml应用程序类
@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;
}
要检查的天气活动是前景或背景按上述方案调用下面的方法对地方,你需要检查
<application
android:name=".AppController" />
你试过没有要求完成,并把“机器人:noHistory =”?清单中的真正”这将防止从去到堆栈中的活动。
我不得不说,你的工作流程是不是在一个标准的Android方式。在Android中,如果你想从意图打开另一个活动,你不需要AppController applicationControl = (AppController) getApplicationContext();
if(applicationControl.isActivityInForeground()){
Log.d("TAG","Activity is in foreground")
}
else
{
Log.d("TAG","Activity is in background")
}
您的活动。至于用户的方便,Android版允许用户使用“返回”键,从您打开您的应用程序的活动回去。
所以才让系统停止你的活动,并保存任何需要的时候,你的活动被称为回。
如果你想知道,如果你的应用程序的任何活动是在屏幕上可见,你可以这样做:
finish()
只要创建这个类的单一,并设置它在你的应用实例如下图所示:
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) {}}
然后你可以使用你的MyAppActivityCallbacks实例的isAnyActivityVisible()方法,无处不在!
保存一个标志,如果你被暂停或恢复。如果你正在恢复它意味着你在前台
class App extends Application{
@Override
public void onCreate() {
registerActivityLifecycleCallbacks(myAppActivityCallbacks);
}
}
一个可能的解决方案可能会设置一个标志,同时显示系统对话框,然后在活动生命周期的方法的onStop,检查标志,如果是真的,完成活动。
例如,如果系统对话框是由一些buttonclick触发,那么听者的onclick可能会像
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();
}
}
在活动的onStop:
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();
}
然后写飞溅活动中一个简单的接收器:
//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);
并注册与LocalBroadcastManager新的接收器收听来自你的第二个活动的广播:
//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"));
只是为了避免在你的堆栈(任务)应用程序的新应用开始,你可以开始新的应用程序时使用finish()
标志,并且不叫Intent.FLAG_ACTIVITY_NEW_TASK
可言。按照finish()
,这是标志被用于实现“发射”式的行为。
documentation
使用// just add this line before you start an activity
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
内这些方法。
Activity
在API 17 如果最终的onDestroy()调用已对活动作出返回true,所以这种情况下,现在已经死了。
isDestroyed()
在API 1 请检查是否这项活动是在整理的过程中,或者是因为你叫光洁度()或其他人已要求它完成。这通常是在的onPause()用于确定活动是否被简单地暂停或完全整理。
从
isFinishing()
与Memory Leaks Documentation一个常见的错误是捕获的强引用主机AsyncTask
(或Activity
):
Fragment
这是一个问题,因为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!
}
}
可以很容易地活得比父AsyncTask
,例如,如果该任务运行时的配置发生了变化。
要做到这一点,正确的做法是让你的任务Activity
类,它不捕获父,并保持static
到主机weak reference:
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
}
}
}
类的解决方案。
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;
}
}
如果您有需要的活动或使用活动的规范名称的引用,你可以发现无论是在前台与否。这种解决方案可能无法做到万无一失。因此,您的意见是真正欢迎。
如果定位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
....
}
我不知道为什么没有人提及sharedPreferences,为活动A,(在的onPause例如())设置SharedPreference这样的:
((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();
有用吗?这样,再加一个类级别的标志,像Activity.onWindowFocusChanged(boolean hasFocus)
是isFocused
套,将是一个简单的方法在你活动的任何一点说,如果它集中与否。从阅读的文档,它看起来像它会正确设置在该活动并非直接在物理“前台”任何情况下“假”,就像如果正在显示一个对话框或通知托盘被拉低。
例:
onWindowFocusChanged
我以前做的一样,
如果该活动是不是在前台
getIntent()
将返回null。 := P
UPD:更新状态Lifecycle.State.RESUMED
。由于@htafoya了点。
在2019年新的支持库28+
或AndroidX的帮助下,你可以简单地使用:
val isActivityInForeground = activity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)
你可以阅读更多的the documenation了解引擎盖下发生了什么。
这正是onPause
和在onStop
中,活性Activity class documentation事件之间的差别。
如果我理解正确的话,你需要做的是从你的活动finish()
通话onStop
终止它。看到Activity Lifecycle Demo App的附加图像。这是它的外观,当活动B从活动A.事件的顺序是从底部启动到顶部,所以你可以看到,活动结束后活动B onStop
已经被称为A onResume
被称为等。
在情况下会出现一个对话框您的活动在后台变暗,只有onPause
被调用。
Activity::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;
}
}
下面是一个例子类,无论你在哪里检查activites'的知名度。
请记住,如果你显示一个对话框,其结果将是错误的,因为该对话框会的主要焦点。除此之外,它真的很方便,比建议的解决方案更可靠。
使用实现Application的ActivityLifecycleCallbacks并用它来跟踪你的应用程序活动生命周期事件。需要注意的是ActivityLifecycleCallbacks是为Android API> = 14,对于以前的Android API,您需要自己实现它里面所有的活动的;-)
当你需要跨越的活动共享/存储的状态使用Application。
您可以查看正在运行的进程的状态与此类RunningAppProcessInfo
取正在运行的进程列表以ActivityManager.getRunningAppProcesses()和过滤结果列表检查所需RunningAppProcessInfo并检查其“重要性”
我已创建GitHub上app-foreground-background-listen项目
它使用了非常简单的逻辑和正常工作与所有Android API级别。
使用从后台暂停和恢复之间的时间间隔,以确定它是否是从背景清醒
在自定义应用程序
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();
}
我觉得我有更好的解决方案。因为你可以建立在简单的我Application.activity简历();由一个每个Activity延伸。
首先,你必须创建(如控制论Twerk大师兽人)
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" >
然后,创建一流ACTIVITYBASE
public class ActivityBase extends Activity {
@Override
protected void onPause() {
super.onPause();
MyApplication.activityPaused();
}
@Override
protected void onResume() {
super.onResume();
MyApplication.activityResumed();
}
}
最后,当你箱新的活动,你可以简单地通过ACTIVITYBASE,而不是活动进行了扩展。
public class Main extends ActivityBase {
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onPause() {
super.onPause();
}
}
对我来说,这是最好的方法,因为你必须只记得有关ACTIVITYBASE延伸。此外,你可以展开你的未来的基础功能。在我来说,我在一个类中增加了对我的服务型接收器,并提醒有关网络。
如果你的应用程序的你想检查的知名度,你可以简单地调用
MyApplication.isActivityVisible()