我试图写一个应用程序,做一些具体的时候,它被带回前台后一段时间。是否有一种方法可以检测应用程序是被发送到后台还是被带到前台?
当前回答
我发现了一个很好的方法来检测应用程序是否进入前台或后台。 这是我的代码。 希望这对你有帮助。
/**
* Custom Application which can detect application state of whether it enter
* background or enter foreground.
*
* @reference http://www.vardhan-justlikethat.blogspot.sg/2014/02/android-solution-to-detect-when-android.html
*/
public abstract class StatusApplication extends Application implements ActivityLifecycleCallbacks {
public static final int STATE_UNKNOWN = 0x00;
public static final int STATE_CREATED = 0x01;
public static final int STATE_STARTED = 0x02;
public static final int STATE_RESUMED = 0x03;
public static final int STATE_PAUSED = 0x04;
public static final int STATE_STOPPED = 0x05;
public static final int STATE_DESTROYED = 0x06;
private static final int FLAG_STATE_FOREGROUND = -1;
private static final int FLAG_STATE_BACKGROUND = -2;
private int mCurrentState = STATE_UNKNOWN;
private int mStateFlag = FLAG_STATE_BACKGROUND;
@Override
public void onCreate() {
super.onCreate();
mCurrentState = STATE_UNKNOWN;
registerActivityLifecycleCallbacks(this);
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
// mCurrentState = STATE_CREATED;
}
@Override
public void onActivityStarted(Activity activity) {
if (mCurrentState == STATE_UNKNOWN || mCurrentState == STATE_STOPPED) {
if (mStateFlag == FLAG_STATE_BACKGROUND) {
applicationWillEnterForeground();
mStateFlag = FLAG_STATE_FOREGROUND;
}
}
mCurrentState = STATE_STARTED;
}
@Override
public void onActivityResumed(Activity activity) {
mCurrentState = STATE_RESUMED;
}
@Override
public void onActivityPaused(Activity activity) {
mCurrentState = STATE_PAUSED;
}
@Override
public void onActivityStopped(Activity activity) {
mCurrentState = STATE_STOPPED;
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
mCurrentState = STATE_DESTROYED;
}
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
if (mCurrentState == STATE_STOPPED && level >= TRIM_MEMORY_UI_HIDDEN) {
if (mStateFlag == FLAG_STATE_FOREGROUND) {
applicationDidEnterBackground();
mStateFlag = FLAG_STATE_BACKGROUND;
}
}else if (mCurrentState == STATE_DESTROYED && level >= TRIM_MEMORY_UI_HIDDEN) {
if (mStateFlag == FLAG_STATE_FOREGROUND) {
applicationDidDestroyed();
mStateFlag = FLAG_STATE_BACKGROUND;
}
}
}
/**
* The method be called when the application been destroyed. But when the
* device screen off,this method will not invoked.
*/
protected abstract void applicationDidDestroyed();
/**
* The method be called when the application enter background. But when the
* device screen off,this method will not invoked.
*/
protected abstract void applicationDidEnterBackground();
/**
* The method be called when the application enter foreground.
*/
protected abstract void applicationWillEnterForeground();
}
其他回答
onPause()和onResume()方法在应用程序被带到后台并再次进入前台时被调用。但是,在应用程序第一次启动时和关闭之前也会调用它们。你可以在活动中阅读更多。
没有任何直接的方法来获得应用程序的状态,而在后台或前台,但即使我已经面临这个问题,并找到解决方案与onWindowFocusChanged和onStop。
更多细节请查看这里Android:解决方案检测当一个Android应用程序去后台,回到前台没有getRunningTasks或getRunningAppProcesses。
这里有一个解决方案,通过使用deboning逻辑,确保我们不会得到连续的背景/前景事件。所以,它总是反映一种稳定的背景/前景状态。
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import java.util.Timer
import java.util.TimerTask
/**
* An observer class to listen on the app's lifecycle.
*/
class AppLifecycleObserver(
private val onAppGoesToBackground: () -> Unit = {},
private val onAppEntersForeground: () -> Unit = {}
) : LifecycleEventObserver {
private val debounce = DebouncingTimer(timeout = 10)
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
debounce.refresh {
when (event.targetState) {
Lifecycle.State.CREATED -> onAppGoesToBackground()
Lifecycle.State.RESUMED -> onAppEntersForeground()
else -> Unit
}
}
}
fun attach() {
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
}
fun detach() {
ProcessLifecycleOwner.get().lifecycle.removeObserver(this)
}
private class DebouncingTimer(private val timeout: Long) {
private var timer: Timer? = null
fun refresh(job: () -> Unit) {
timer?.cancel()
timer = Timer()
timer?.schedule(object : TimerTask() {
override fun run() = job.invoke()
}, timeout)
}
}
}
只需要创建一个AppLifecycleObserver实例:
private val appLifecycleObserver = AppLifecycleObserver(
onAppGoesToBackground = { // do whatever... },
onAppEntersForeground = { // do whatever... }
)
// Attach the observer when it is needed:
appLifecycleObserver.attach()
// Remove when there is no need to it:
appLifecycleObserver.detach()
不要忘记添加一个合适的依赖版本:
implementation("androidx.lifecycle:lifecycle-process:$lifecycle_version")
我喜欢ProcessLifecycleOwner方法,但实际上可以跳过所有这些,因为在Activity的onCreate()方法中,可以很容易地确定它是第一次运行还是后续运行:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
/* savedInstanceState is always null on first run */
} else {
/* it's a subsequent run */
}
}
这是我的解决方案。只需在您的主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)
{
}
}
我发现了一个很好的方法来检测应用程序是否进入前台或后台。 这是我的代码。 希望这对你有帮助。
/**
* Custom Application which can detect application state of whether it enter
* background or enter foreground.
*
* @reference http://www.vardhan-justlikethat.blogspot.sg/2014/02/android-solution-to-detect-when-android.html
*/
public abstract class StatusApplication extends Application implements ActivityLifecycleCallbacks {
public static final int STATE_UNKNOWN = 0x00;
public static final int STATE_CREATED = 0x01;
public static final int STATE_STARTED = 0x02;
public static final int STATE_RESUMED = 0x03;
public static final int STATE_PAUSED = 0x04;
public static final int STATE_STOPPED = 0x05;
public static final int STATE_DESTROYED = 0x06;
private static final int FLAG_STATE_FOREGROUND = -1;
private static final int FLAG_STATE_BACKGROUND = -2;
private int mCurrentState = STATE_UNKNOWN;
private int mStateFlag = FLAG_STATE_BACKGROUND;
@Override
public void onCreate() {
super.onCreate();
mCurrentState = STATE_UNKNOWN;
registerActivityLifecycleCallbacks(this);
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
// mCurrentState = STATE_CREATED;
}
@Override
public void onActivityStarted(Activity activity) {
if (mCurrentState == STATE_UNKNOWN || mCurrentState == STATE_STOPPED) {
if (mStateFlag == FLAG_STATE_BACKGROUND) {
applicationWillEnterForeground();
mStateFlag = FLAG_STATE_FOREGROUND;
}
}
mCurrentState = STATE_STARTED;
}
@Override
public void onActivityResumed(Activity activity) {
mCurrentState = STATE_RESUMED;
}
@Override
public void onActivityPaused(Activity activity) {
mCurrentState = STATE_PAUSED;
}
@Override
public void onActivityStopped(Activity activity) {
mCurrentState = STATE_STOPPED;
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
mCurrentState = STATE_DESTROYED;
}
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
if (mCurrentState == STATE_STOPPED && level >= TRIM_MEMORY_UI_HIDDEN) {
if (mStateFlag == FLAG_STATE_FOREGROUND) {
applicationDidEnterBackground();
mStateFlag = FLAG_STATE_BACKGROUND;
}
}else if (mCurrentState == STATE_DESTROYED && level >= TRIM_MEMORY_UI_HIDDEN) {
if (mStateFlag == FLAG_STATE_FOREGROUND) {
applicationDidDestroyed();
mStateFlag = FLAG_STATE_BACKGROUND;
}
}
}
/**
* The method be called when the application been destroyed. But when the
* device screen off,this method will not invoked.
*/
protected abstract void applicationDidDestroyed();
/**
* The method be called when the application enter background. But when the
* device screen off,this method will not invoked.
*/
protected abstract void applicationDidEnterBackground();
/**
* The method be called when the application enter foreground.
*/
protected abstract void applicationWillEnterForeground();
}
推荐文章
- 警告: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文件