안드로이드 응용 프로그램이 전경에 있는지 확인하십시오. [복제]
이 질문에 이미 답변이 있습니다.
이 질문에 대한 많은 답변을 봤는데, 단일 활동에 관한 것입니다. 전체 앱이 포 그라운드에서 실행 중인지 여부를 확인하는 방법은 무엇입니까?
원하는 것을 이해하지 못하지만 현재 포 그라운드 / 백그라운드 애플리케이션을 ActivityManager.getRunningAppProcesses()
호출로 감지 할 수 있습니다 .
같은 것,
class ForegroundCheckTask extends AsyncTask<Context, Void, Boolean> {
@Override
protected Boolean doInBackground(Context... params) {
final Context context = params[0].getApplicationContext();
return isAppOnForeground(context);
}
private boolean isAppOnForeground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
final String packageName = context.getPackageName();
for (RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}
}
// Use like this:
boolean foregroud = new ForegroundCheckTask().execute(context).get();
오해가 있으면 알려주세요 ..
업데이트 : 이 질문을보세요 . 백그라운드 작업 또는 서비스에서 현재 포 그라운드 애플리케이션 결정에 대한 자세한 정보 ..
감사..
@ user370305의 대답은 오류가 발생하기 쉬우 며 Android OS 개발자가 권장하지 않습니다 ( https://groups.google.com/forum/#!msg/android-developers/zH-2bovZSLg/L2YM8Z1N-HwJ 확인 ).
훨씬 더 간단한 접근 방식이 있습니다.
모든 활동이 확장 하는 BaseActivity에서 :
protected static boolean isVisible = false;
@Override
public void onResume() {
super.onResume();
setVisible(true);
}
@Override
public void onPause() {
super.onPause();
setVisible(false);
}
응용 프로그램 활동이 포 그라운드에 있는지 확인해야 할 때마다 확인하십시오. isVisible();
이 접근 방식을 이해하려면 side-by-side 활동 수명주기에 대한 답변을 확인하십시오. Activity side-by-side 수명주기
다음과 같이 지금까지 내가 찾은 가장 깔끔하고 더 이상 사용되지 않는 방법입니다.
@Override
public boolean foregrounded() {
ActivityManager.RunningAppProcessInfo appProcessInfo = new ActivityManager.RunningAppProcessInfo();
ActivityManager.getMyMemoryState(appProcessInfo);
return (appProcessInfo.importance == IMPORTANCE_FOREGROUND || appProcessInfo.importance == IMPORTANCE_VISIBLE)
}
SDK 16+에서만 작동합니다.
수정 :
솔루션에서 다음 코드를 제거했습니다.
KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
// App is foreground, but screen is locked, so show notification
return km.inKeyguardRestrictedInputMode();
화면이 잠긴 경우 알림을받지 못하기 때문입니다. 프레임 워크를 살펴 봤는데 그 목적이 명확하지 않습니다. 나는 그것을 제거 할 것이다. 프로세스 정보 상태를 확인하는 것으로 충분합니다 :-)
새로운 Android Architecture of Lifecycle 확장을 사용하면이를 최대한 쉽게 달성 할 수 있습니다.
build.gradle 파일에서이 종속성을 가져와야합니다.
dependencies {
implementation "android.arch.lifecycle:extensions:1.1.0"
}
그런 다음 Application 클래스에서 다음을 사용하십시오.
class ArchLifecycleApp : Application(), LifecycleObserver {
override fun onCreate() {
super.onCreate()
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onAppBackgrounded() {
Log.d("MyApp", "App in background")
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onAppForegrounded() {
Log.d("MyApp", "App in foreground")
}
}
마지막으로 AndroidManifest.xml 파일을 다음으로 업데이트하십시오.
<application
android:name=".ArchLifecycleApp"
//Your extra code
....>
</application>
이제 Application이 Foreground 또는 Background로 이동할 때마다 선언 된 두 메서드와 관련된 로그를 받게됩니다.
실행중인 프로세스에서 패키지 필터를 사용해 보았습니다. 그러나 그것은 매우 이상합니다. 그 대신 새로운 솔루션을 시도했으며 완벽하게 작동합니다. 이 모듈을 통해 여러 번 확인하고 완벽한 결과를 얻었습니다.
private int numRunningActivities = 0;
public void onCreate() {
super.onCreate();
this.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityStarted(Activity activity) {
numRunningActivities++;
if (numRunningActivities == 1) {
LogUtils.d("APPLICATION", "APP IN FOREGROUND");
}
}
@Override
public void onActivityStopped(Activity activity) {
numRunningActivities--;
if (numRunningActivities == 0) {
Log.e("", "App is in BACKGROUND")
}
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
});
}
앱이 백그라운드 또는 포 그라운드에 있는지 확인하십시오. 이 메서드는 앱이 백그라운드에 있으면 true를 반환합니다.
먼저 AndroidManifest.xml에 GET_TASKS 권한을 추가하십시오.
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;
}
Android 아키텍처 구성 요소 라이브러리는 ProcessLifecycleOwner를 사용하여 onStart 및 onStop 이벤트에 대한 전체 애플리케이션 프로세스에 대한 리스너를 설정할 수 있습니다. 이를 수행하려면 애플리케이션 클래스가 LifecycleObserver 인터페이스를 구현하도록하고 onStop 및 onStart에 대한 주석을 포 그라운드 및 백그라운드 메소드에 추가하십시오.
class ArchLifecycleApp : Application(), LifecycleObserver {
override fun onCreate() {
super.onCreate()
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onAppBackgrounded() {
Log.d("Awww", "App in background")
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onAppForegrounded() {
Log.d("Yeeey", "App in foreground")
}
}
기본 활동 클래스를 생성하여 이에 대한 간단한 해결책을 찾았습니다. u는 다음에서 모든 활동 클래스를 확장해야합니다.
public class BaseActivity extends ActionBarActivity {
@Override
protected void onResume() {
ApplicationStateChecker.view_resumed(this);
super.onResume();
}
@Override
protected void onStop() {
ApplicationStateChecker.view_stopped(this);
super.onStop();
}
@Override
protected void onPause() {
ApplicationStateChecker.view_paused(this);
super.onPause();
}
}
ApplicationStateChecker 클래스 :
public class ApplicationStateChecker {
private static final String _pause_string = "paused";
private static final String _resume_string = "resumed";
private static String _view_lastState;
private static boolean _from_background = true;
public static void view_paused(Activity activity){
_view_lastState = _pause_string;
}
public static void view_stopped(Activity activity){
if ( _view_lastState.equals(_pause_string) ){
//if stop called and last event was pause then app is brought to background
_from_background = true;
} //if
}
public static void view_resumed(Activity activity){
if ( _from_background ) {
//Do your stuff here , app is brought to foreground
} //if
_from_background = false;
_view_lastState = _resume_string;
}
cesards의 대답은 정확하지만 API> 15에만 해당됩니다. 낮은 API 버전의 경우 getRunningTasks()
방법 을 사용하기로 결정했습니다 .
private boolean isAppInForeground(Context context)
{
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
{
ActivityManager am = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
ActivityManager.RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0);
String foregroundTaskPackageName = foregroundTaskInfo.topActivity.getPackageName();
return foregroundTaskPackageName.toLowerCase().equals(context.getPackageName().toLowerCase());
}
else
{
ActivityManager.RunningAppProcessInfo appProcessInfo = new ActivityManager.RunningAppProcessInfo();
ActivityManager.getMyMemoryState(appProcessInfo);
if (appProcessInfo.importance == IMPORTANCE_FOREGROUND || appProcessInfo.importance == IMPORTANCE_VISIBLE)
{
return true;
}
KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
// App is foreground, but screen is locked, so show notification
return km.inKeyguardRestrictedInputMode();
}
}
모두에게 효과가 있는지 알려주세요.
이에 대한 전역 콜백은 없지만 각 활동에 대해 onStop ()입니다. 원자 정수를 엉망으로 만들 필요가 없습니다. 시작된 활동의 수와 함께 전역 정수를 가지고 모든 활동에서 onStart ()에서 증가시키고 onStop ()에서 감소시킵니다.
public class BaseActivity extends ActionBarActivity {
public static int count = 0;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void onStart() {
super.onStart();
count = count + 1;
Log.d(TAG, "onStart" + count);
if (count == 1) {
Toast.makeText(getApplicationContext(), "online", Toast.LENGTH_SHORT).show();
}
}
protected void onStop() {
super.onStop();
count = count - 1;
if (count == 0) {
Toast.makeText(getApplicationContext(), "offline", Toast.LENGTH_SHORT).show();
}
}
}
Application 클래스에서 ActivityLifecycleCallbacks를 사용해보십시오.
다음은 최신 Android SDK에 대한 업데이트 된 솔루션입니다.
String PackageName = context.getPackageName();
ActivityManager manager = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
ComponentName componentInfo;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
List<ActivityManager.AppTask> tasks = manager.getAppTasks();
componentInfo = tasks.get(0).getTaskInfo().topActivity;
}
else
{
List<ActivityManager.RunningTaskInfo> tasks = manager.getRunningTasks(1);
componentInfo = tasks.get(0).topActivity;
}
if (componentInfo.getPackageName().equals(PackageName))
return true;
return false;
도움이 되었기를 바랍니다. 감사합니다.
getRunningTasks () 의 솔루션 기반 은 최신 Android 버전에서 작동 하지 않으며 getRunningTasks () 는 API 레벨 21에서 지원 중단되었습니다. 여전히 사용 되더라도 앱이 포 그라운드에 있는지 확인하기에 충분한 정보를 반환하지 않습니다.
대신 Application 클래스를 확장하고 Application.ActivityLifecycleCallbacks를 사용하여 애플리케이션 가시성 상태를 추적하십시오.
public class MyApplication extends Application {
static final String APP_STATE_FOREGROUND = "com.xxx.appstate.FOREGROUND";
static final String APP_STATE_BACKGROUND = "com.xxx.appstate.BACKGROUND";
private static int m_foreground = -1;
private Handler m_handler = new Handler();
private Runnable m_guard;
public static boolean isForeground() {
return m_foreground == 1;
}
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle bundle) {
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
if(m_guard != null) {
m_handler.removeCallbacks(m_guard);
m_guard = null;
}
if(m_foreground == 1)
return;
m_foreground = 1;
sendBroadcast(new Intent(APP_STATE_FOREGROUND));
}
@Override
public void onActivityPaused(Activity activity) {
if(m_foreground == 0)
return;
/*
* Use a 400ms guard to protect against jitter
* when switching between two activities
* in the same app
*/
m_guard = new Runnable() {
@Override
public void run() {
if(m_foreground == 1) {
m_foreground = 0;
sendBroadcast(new Intent(APP_STATE_BACKGROUND));
}
}
};
m_handler.postDelayed(m_guard, 400);
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
});
}
}
400ms 가드 타이머를 사용하면 동일한 앱에서 활동을 전환 할 때 백그라운드 상태가 잘못 감지되지 않습니다. 배경 / 전경 상태는 다음을 사용하여 언제든지 쿼리 할 수 있습니다.
MyApplication.isForeground();
클래스는 상태 전환에 관심이있는 경우 브로드 캐스트 이벤트를 수신 할 수도 있습니다.
private static IntentFilter m_appStateFilter;
static {
m_appStateFilter = new IntentFilter();
m_appStateFilter.addAction(MyApplication.APP_STATE_FOREGROUND);
m_appStateFilter.addAction(MyApplication.APP_STATE_BACKGROUND);
}
private BroadcastReceiver m_appStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(MyApplication.APP_STATE_FOREGROUND)) {
/* application entered foreground */
} else if (action.equals(MyApplication.APP_STATE_BACKGROUND)) {
/* application entered background */
}
}
};
registerReceiver(m_appStateReceiver, m_appStateFilter);
아래 솔루션은 API 레벨 14 이상에서 작동합니다.
Backgrounding ComponentCallbacks2 — 문서를 보는 것은 이것을 어떻게 사용할 것인지 100 % 명확하지 않습니다. 그러나 자세히 살펴보면 onTrimMemory 메서드가 플래그로 전달되는 것을 알 수 있습니다. 이러한 플래그는 일반적으로 메모리 가용성과 관련이 있지만 우리가 관심을 갖는 것은 TRIM_MEMORY_UI_HIDDEN입니다. UI가 숨겨져 있는지 확인함으로써 앱이 현재 백그라운드에 있다고 가정 할 수 있습니다. 명확하지는 않지만 작동합니다.
Foregrounding ActivityLifecycleCallbacks — onActivityResumed를 재정의하고 현재 애플리케이션 상태 (Foreground / Background)를 추적하여이를 사용하여 전경을 감지 할 수 있습니다.
사용자 정의 Application 클래스에 의해 구현 될 인터페이스 생성
interface LifecycleDelegate {
fun onAppBackgrounded()
fun onAppForegrounded()
}
ActivityLifecycleCallbacks 및 ComponentCallbacks2를 구현하고 onActivityResumed 및 onTrimMemory 메서드를 재정의 할 클래스를 만듭니다.
// Take an instance of our lifecycleHandler as a constructor parameter
class AppLifecycleHandler(private val lifecycleDelegate: LifecycleDelegate)
: Application.ActivityLifecycleCallbacks, ComponentCallbacks2 // <-- Implement these
{
private var appInForeground = false
// Override from Application.ActivityLifecycleCallbacks
override fun onActivityResumed(p0: Activity?) {
if (!appInForeground) {
appInForeground = true
lifecycleDelegate.onAppForegrounded()
}
}
// Override from ComponentCallbacks2
override fun onTrimMemory(level: Int) {
if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
// lifecycleDelegate instance was passed in on the constructor
lifecycleDelegate.onAppBackgrounded()
}
}
}
이제 우리가해야 할 일은 사용자 정의 Application 클래스가 LifecycleDelegate 인터페이스를 구현하고 등록하는 것입니다.
class App : Application(), LifeCycleDelegate {
override fun onCreate() {
super.onCreate()
val lifeCycleHandler = AppLifecycleHandler(this)
registerLifecycleHandler(lifeCycleHandler)
}
override fun onAppBackgrounded() {
Log.d("Awww", "App in background")
}
override fun onAppForegrounded() {
Log.d("Yeeey", "App in foreground")
}
private fun registerLifecycleHandler(lifeCycleHandler: AppLifecycleHandler) {
registerActivityLifecycleCallbacks(lifeCycleHandler)
registerComponentCallbacks(lifeCycleHandler)
}
}
Manifest에서 CustomApplicationClass를 설정하십시오.
<application
android:name=".App"
Android 19에서 다음과 같이 Application 클래스의 onCreate ()에 앱 수명주기 콜백을 등록 할 수 있습니다.
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new AppLifecycleCallback());
}
AppLifecycleCallback은 다음과 같습니다.
class AppLifecycleCallback implements Application.ActivityLifecycleCallbacks {
private int numStarted = 0;
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
if (numStarted == 0) {
//app went to foreground
}
numStarted++;
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
numStarted--;
if (numStarted == 0) {
// app went to background
}
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
}
참고 URL : https://stackoverflow.com/questions/8489993/check-android-application-is-in-foreground-or-not
'Programming' 카테고리의 다른 글
Active Directory에서 사용자 목록을 얻으려면 어떻게해야합니까? (0) | 2020.08.18 |
---|---|
Arrays.asList (array)와 새로운 ArrayList의 차이점 (0) | 2020.08.18 |
split () 결과에 빈 문자열이 반환되는 이유는 무엇입니까? (0) | 2020.08.18 |
* 정적 일 수있는 * C # 메서드는 정적이어야합니까? (0) | 2020.08.17 |
참조 할당은 원자 적이므로 Interlocked.Exchange (ref Object, Object)가 필요한 이유는 무엇입니까? (0) | 2020.08.17 |