所谓后台,我的意思是应用程序的活动目前对用户都不可见?
当前回答
另一种没有额外依赖的方法是:
只需将此方法添加到应用程序类中,并在onCreate()中调用它即可。
var isInBackground = true
private fun setupActivityLifecycleCallbacks() {
registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
override fun onActivityStarted(activity: Activity) {}
override fun onActivityResumed(activity: Activity) {
isInBackground = false
}
override fun onActivityPaused(activity: Activity) {
isInBackground = true
}
override fun onActivityStopped(activity: Activity) {}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {}
})
}
AFAIK,你甚至可以使isInBackground静态,这样你就可以在没有上下文的情况下使用伴生对象访问它
其他回答
我尝试了推荐的使用Application的解决方案。ActivityLifecycleCallbacks和许多其他的,但是它们没有像预期的那样工作。感谢Sarge,我想出了一个非常简单和直接的解决方案,我将在下面描述。
解决方案的关键是理解这样一个事实:如果我们有ActivityA和ActivityB,并且我们从ActivityA调用ActivityB(而不是调用ActivityA.finish),那么ActivityB的onStart()将在ActivityA onStop()之前被调用。
这也是onStop()和onPause()之间的主要区别,在我读过的文章中没有人提到。
So based on this Activity's Lifecycle behavior, you can simply count how many times did onStart() and onPause() got called in your program. Note that for each Activity of your program, you must override onStart() and onStop(), in order to increment/decrement the static variable used for counting. Below is the code implementing this logic. Note that I am using a class that extends Application, so dont forget to declare on Manifest.xml inside Application tag: android:name=".Utilities", although it can be implemented using a simple custom class too.
public class Utilities extends Application
{
private static int stateCounter;
public void onCreate()
{
super.onCreate();
stateCounter = 0;
}
/**
* @return true if application is on background
* */
public static boolean isApplicationOnBackground()
{
return stateCounter == 0;
}
//to be called on each Activity onStart()
public static void activityStarted()
{
stateCounter++;
}
//to be called on each Activity onStop()
public static void activityStopped()
{
stateCounter--;
}
}
现在,在我们程序的每个活动上,我们应该重写onStart()和onStop()和增量/减量,如下所示:
@Override
public void onStart()
{
super.onStart();
Utilities.activityStarted();
}
@Override
public void onStop()
{
Utilities.activityStopped();
if(Utilities.isApplicationOnBackground())
{
//you should want to check here if your application is on background
}
super.onStop();
}
根据这种逻辑,有两种可能的情况:
stateCounter = 0:停止活动的数量与启动活动的数量相等,这意味着应用程序正在后台运行。 stateCounter > 0:启动的次数大于停止的次数,即应用程序在前台运行。
注意:stateCounter < 0意味着有更多停止的活动而不是启动的活动,这是不可能的。如果您遇到这种情况,那么这意味着您没有像应该的那样增加/减少计数器。
你已经准备好了。你应该在onStop()中检查你的应用程序是否在后台。
根据CommonsWare和Key所说的,你可以扩展Application类,并让你所有的活动在onPause/onResume方法上调用它。这将允许您知道哪些活动是可见的,但这可能会得到更好的处理。
你能详细说明一下你的想法吗?当你说在后台运行,你的意思是简单地让你的应用程序仍然在内存中,即使它目前不在屏幕上?你有没有考虑过使用服务作为一种更持久的方式来管理你的应用程序,当它不在焦点?
唯一正确的解决方法:
MainActivity.java:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
MyApp.mainActivity = this;
super.onCreate(savedInstanceState);
...
}
MyApp.java:
public class MyApp extends Application implements LifecycleObserver {
public static MainActivity mainActivity = null;
@Override
public void onCreate() {
super.onCreate();
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void onAppBackgrounded() {
// app in background
if (mainActivity != null) {
...
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
void onAppForegrounded() {
// app in foreground
if (mainActivity != null) {
...
}
}
}
您应该使用共享首选项来存储属性,并使用来自活动的服务绑定对其进行操作。如果你只使用绑定(也就是从不使用startService),那么你的服务将只在你绑定它时运行,(绑定onResume和取消绑定onPause),这将使它只在前台运行,如果你确实想在后台工作,你可以使用常规的启动停止服务。
这篇旧文章的另一个解决方案(对那些可能有帮助的人来说):
<application android:name=".BaseApplication" ... >
public class BaseApplication extends Application {
private class Status {
public boolean isVisible = true;
public boolean isFocused = true;
}
private Map<Activity, Status> activities;
@Override
public void onCreate() {
activities = new HashMap<Activity, Status>();
super.onCreate();
}
private boolean hasVisibleActivity() {
for (Status status : activities.values())
if (status.isVisible)
return true;
return false;
}
private boolean hasFocusedActivity() {
for (Status status : activities.values())
if (status.isFocused)
return true;
return false;
}
public void onActivityCreate(Activity activity, boolean isStarting) {
if (isStarting && activities.isEmpty())
onApplicationStart();
activities.put(activity, new Status());
}
public void onActivityStart(Activity activity) {
if (!hasVisibleActivity() && !hasFocusedActivity())
onApplicationForeground();
activities.get(activity).isVisible = true;
}
public void onActivityWindowFocusChanged(Activity activity, boolean hasFocus) {
activities.get(activity).isFocused = hasFocus;
}
public void onActivityStop(Activity activity, boolean isFinishing) {
activities.get(activity).isVisible = false;
if (!isFinishing && !hasVisibleActivity() && !hasFocusedActivity())
onApplicationBackground();
}
public void onActivityDestroy(Activity activity, boolean isFinishing) {
activities.remove(activity);
if(isFinishing && activities.isEmpty())
onApplicationStop();
}
private void onApplicationStart() {Log.i(null, "Start");}
private void onApplicationBackground() {Log.i(null, "Background");}
private void onApplicationForeground() {Log.i(null, "Foreground");}
private void onApplicationStop() {Log.i(null, "Stop");}
}
public class MyActivity extends BaseActivity {...}
public class BaseActivity extends Activity {
private BaseApplication application;
@Override
protected void onCreate(Bundle state) {
application = (BaseApplication) getApplication();
application.onActivityCreate(this, state == null);
super.onCreate(state);
}
@Override
protected void onStart() {
application.onActivityStart(this);
super.onStart();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
application.onActivityWindowFocusChanged(this, hasFocus);
super.onWindowFocusChanged(hasFocus);
}
@Override
protected void onStop() {
application.onActivityStop(this, isFinishing());
super.onStop();
}
@Override
protected void onDestroy() {
application.onActivityDestroy(this, isFinishing());
super.onDestroy();
}
}
推荐文章
- 警告:API ' variable . getjavacompile()'已过时,已被' variable . getjavacompileprovider()'取代
- 安装APK时出现错误
- 碎片中的onCreateOptionsMenu
- TextView粗体通过XML文件?
- 如何使线性布局的孩子之间的空间?
- DSL元素android.dataBinding。enabled'已过时,已被'android.buildFeatures.dataBinding'取代
- ConstraintLayout:以编程方式更改约束
- PANIC: AVD系统路径损坏。检查ANDROID_SDK_ROOT值
- 如何生成字符串类型的buildConfigField
- Recyclerview不调用onCreateViewHolder
- Android API 21工具栏填充
- Android L中不支持操作栏导航模式
- 如何在TextView中添加一个子弹符号?
- PreferenceManager getDefaultSharedPreferences在Android Q中已弃用
- 在Android Studio中创建aar文件