App이 foreground 인지 background 인지 구별하기
android 2017. 3. 30. 22:24안드로이드 App을 만들다 보면은 App이 background로 내려가는 시점을 알아야 할 때가 있다.
그런데, 안드로이드에서는 Home 버튼을 눌렀는지 알 수 있는 방법이 없어서 약간의 편법을 사용해야 한다.
먼저 고전적인 방밥으로는 ActivityManager를 이용하는 방법이다.
코드로 보면 아래와 같다.
private boolean isAppIsInBackground(Context context) {
boolean isInBackground = true;
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
for (String activeProcess : processInfo.pkgList) {
if (activeProcess.equals(context.getPackageName())) {
isInBackground = false;
}
}
}
}
} else {
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
ComponentName componentInfo = taskInfo.get(0).topActivity;
if (componentInfo.getPackageName().equals(context.getPackageName())) {
isInBackground = false;
}
}
return isInBackground;
}
키캣미만에서는 RunningTaksInfo를 이용하고, 키캣이상에서는 RunningAppProcessInfo 를 이용하는 방식이다. 그런데 이 방색을 사용할때는 GET_TASKS 권한을 AndroidManifest.xml에 추가해야 하는데, GET_TASKS 권한이 deprecated 되었다.
그래서 다른 방식으로 사용하는것이 Activity의 onStart(), onStop() 함수를 오버라이드(override) 해서 count 하는 방식이다. 대략적인 코드는 아래와 같은 모습이다.
public class BaseActivity extends Activity {
public static int foregroundCount = 0; // 전역 count 변수
@Override
protected void onStart() {
super.onStart();
foregroundCount = foregroundCount+ 1;
}
@Override
protected void onStop() {
super.onStop();
foregroundCount = foregroundCount - 1;
}
}
Application에서 사용하는 모든 Activity가 BaseActivity를 상속받게 하고, foregroundCount 가 1이상이면 foreground로 볼 수 있는 것이다.
Activity가 많다면 은근히 작업이 많아 질 수도 있고, 나주에 추가되는 Activity에서 BaseActivity 로부터의 상속을 빼먹으면 버그가 발생하기 쉬운 방식이다.
그럼 좀 더 안전한 방법은 없을까?
앱에있는 Application 클래스를 이용하는 방법이 있는데,
먼저 background에 있는지 체크하는 방법을 알아보자
public class MyApplication extends Application {
// ...
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
if (level == TRIM_MEMORY_UI_HIDDEN) {
isBackground = true;
notifyBackground();
}
}
}
그런데, onTrimMemory 함수는 screen off 상태일때는 호출이 안되므로, 아래처럼 리시버를 등록해서 체크해야 한다. (screen off 상태는 전원버튼을 눌러서 화면을 끄는것을 말한다. )
public class MyApplication extends Application {
// ...
@Override
public void onCreate() {
super.onCreate();
// ...
IntentFilter screenOffFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (isBackground) {
isBackground = false;
notifyForeground();
}
}
}, screenOffFilter);
}
}
이렇게 하면 background 상태는 체크가 되는데, foreground 상태는 어떻게 알아 낼 수 있을까?
간단하게 ActivityLifecycleCallback() 함수를 이용하면 된다.
public class MyApplication extends Application {
// ...
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
// ...
@Override
public void onActivityResumed(Activity activity) {
if (isBackground) {
isBackground = false;
notifyForeground();
}
}
// ...
});
}
// ...
}
이상으로 App이 foreground에 있는지, background에 있는지 체크하는 방법에 대해서
1. ActivityManager를 이용하는 고전적인 방법
2. Activity의 onStart(), onStop() 을 활용한 방법
3. Application의 onTrimMemory(), registerActivityLifecycleCallbacks() 를 활용하는 방법
으로 알아 보았습니다.