我试图写一个应用程序,做一些具体的时候,它被带回前台后一段时间。是否有一种方法可以检测应用程序是被发送到后台还是被带到前台?
当前回答
onPause()和onResume()方法在应用程序被带到后台并再次进入前台时被调用。但是,在应用程序第一次启动时和关闭之前也会调用它们。你可以在活动中阅读更多。
没有任何直接的方法来获得应用程序的状态,而在后台或前台,但即使我已经面临这个问题,并找到解决方案与onWindowFocusChanged和onStop。
更多细节请查看这里Android:解决方案检测当一个Android应用程序去后台,回到前台没有getRunningTasks或getRunningAppProcesses。
其他回答
我所做的是确保所有应用程序内的活动启动startActivityForResult,然后检查onActivityResult是否在onResume之前被调用。如果不是,这意味着我们刚刚从应用程序之外的某个地方返回。
boolean onActivityResultCalledBeforeOnResume;
@Override
public void startActivity(Intent intent) {
startActivityForResult(intent, 0);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
onActivityResultCalledBeforeOnResume = true;
}
@Override
protected void onResume() {
super.onResume();
if (!onActivityResultCalledBeforeOnResume) {
// here, app was brought to foreground
}
onActivityResultCalledBeforeOnResume = false;
}
我们可以使用LiveData扩展这个解决方案:
class AppForegroundStateLiveData : LiveData<AppForegroundStateLiveData.State>() {
private var lifecycleListener: LifecycleObserver? = null
override fun onActive() {
super.onActive()
lifecycleListener = AppLifecycleListener().also {
ProcessLifecycleOwner.get().lifecycle.addObserver(it)
}
}
override fun onInactive() {
super.onInactive()
lifecycleListener?.let {
this.lifecycleListener = null
ProcessLifecycleOwner.get().lifecycle.removeObserver(it)
}
}
internal inner class AppLifecycleListener : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onMoveToForeground() {
value = State.FOREGROUND
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onMoveToBackground() {
value = State.BACKGROUND
}
}
enum class State {
FOREGROUND, BACKGROUND
}
}
现在我们可以订阅这个LiveData并捕获所需的事件。例如:
appForegroundStateLiveData.observeForever { state ->
when(state) {
AppForegroundStateLiveData.State.FOREGROUND -> { /* app move to foreground */ }
AppForegroundStateLiveData.State.BACKGROUND -> { /* app move to background */ }
}
}
我的解决方案受到@d60402的答案的启发,也依赖于一个时间窗口,但不使用定时器:
public abstract class BaseActivity extends ActionBarActivity {
protected boolean wasInBackground = false;
@Override
protected void onStart() {
super.onStart();
wasInBackground = getApp().isInBackground;
getApp().isInBackground = false;
getApp().lastForegroundTransition = System.currentTimeMillis();
}
@Override
protected void onStop() {
super.onStop();
if( 1500 < System.currentTimeMillis() - getApp().lastForegroundTransition )
getApp().isInBackground = true;
}
protected SingletonApplication getApp(){
return (SingletonApplication)getApplication();
}
}
其中SingletonApplication是Application类的扩展:
public class SingletonApplication extends Application {
public boolean isInBackground = false;
public long lastForegroundTransition = 0;
}
这是我的解决方案。只需在您的主Application类中注册这个ActivityLifecycleCallbacks。在评论中,我提到了一个用户配置文件活动边缘情况。该活动只是一个具有透明边缘的活动。
/**
* This class used Activity lifecycle callbacks to determine when the application goes to the
* background as well as when it is brought to the foreground.
*/
public class Foreground implements Application.ActivityLifecycleCallbacks
{
/**
* How long to wait before checking onStart()/onStop() count to determine if the app has been
* backgrounded.
*/
public static final long BACKGROUND_CHECK_DELAY_MS = 500;
private static Foreground sInstance;
private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
private boolean mIsForeground = false;
private int mCount;
public static void init(final Application application)
{
if (sInstance == null)
{
sInstance = new Foreground();
application.registerActivityLifecycleCallbacks(sInstance);
}
}
public static Foreground getInstance()
{
return sInstance;
}
public boolean isForeground()
{
return mIsForeground;
}
public boolean isBackground()
{
return !mIsForeground;
}
@Override
public void onActivityStarted(final Activity activity)
{
mCount++;
// Remove posted Runnables so any Meteor disconnect is cancelled if the user comes back to
// the app before it runs.
mMainThreadHandler.removeCallbacksAndMessages(null);
if (!mIsForeground)
{
mIsForeground = true;
}
}
@Override
public void onActivityStopped(final Activity activity)
{
mCount--;
// A transparent Activity like community user profile won't stop the Activity that launched
// it. If you launch another Activity from the user profile or hit the Android home button,
// there are two onStops(). One for the user profile and one for its parent. Remove any
// posted Runnables so we don't get two session ended events.
mMainThreadHandler.removeCallbacksAndMessages(null);
mMainThreadHandler.postDelayed(new Runnable()
{
@Override
public void run()
{
if (mCount == 0)
{
mIsForeground = false;
}
}
}, BACKGROUND_CHECK_DELAY_MS);
}
@Override
public void onActivityCreated(final Activity activity, final Bundle savedInstanceState)
{
}
@Override
public void onActivityResumed(final Activity activity)
{
}
@Override
public void onActivityPaused(final Activity activity)
{
}
@Override
public void onActivitySaveInstanceState(final Activity activity, final Bundle outState)
{
}
@Override
public void onActivityDestroyed(final Activity activity)
{
}
}
通过使用下面的代码,我能够得到我的应用程序的前台或后台状态。
更多关于它的工作细节,强文本点击这里
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private Context context;
private Toast toast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
}
private void showToast(String message) {
//If toast is already showing cancel it
if (toast != null) {
toast.cancel();
}
toast = Toast.makeText(context, message, Toast.LENGTH_SHORT);
toast.show();
}
@Override
protected void onStart() {
super.onStart();
showToast("App In Foreground");
}
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
showToast("App In Background");
}
}
}
推荐文章
- 警告: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文件