Android : 활동이 실행 중인지 어떻게 확인합니까?


152

특정 활동이 활동 중인지 여부를 결정하는 간단한 방법이 있습니까? 활동중인 활동에 따라 특정 작업을 수행하고 싶습니다. 예 :

if(activityrunning == activity1)
//do this
else if (activityrunning == activity2)
//do something else

활동이 실행 중인지 여부를 확인하려면 다음 답변을 수행하십시오. stackoverflow.com/a/39079627/4531507
— Rahul Sharma

답변:


227

static활동 내에서 변수 를 사용할 수 있습니다 .

class MyActivity extends Activity {
     static boolean active = false;

      @Override
      public void onStart() {
         super.onStart();
         active = true;
      } 

      @Override
      public void onStop() {
         super.onStop();
         active = false;
      }
}

유일한 문제는 서로 연결되는 두 가지 활동에서 사용 onStop하면 첫 번째는 때로는 onStart두 번째로 호출 된다는 것 입니다. 따라서 둘 다 간단하게 사실 일 수 있습니다.

수행하려는 작업에 따라 (서비스에서 현재 활동을 업데이트 하시겠습니까?) 액티비티 onStart메소드 에서 서비스에 정적 리스너를 등록하면 서비스에서 UI를 업데이트하려고 할 때 올바른 리스너를 사용할 수 있습니다.


5
메모리 누수 문제로 인해 정적 변수보다 Sharedpreference가 선호되어야한다고 지적했습니다.
— Ayush Goyal

13
같은 수업에서 다른 활동이 진행되고 있다면 어떻게해야합니까? 자녀 MyActivity와 함께 연장 MyChildactivity하여 자녀가 활동 중인지 확인하려면 어떻게합니까?
— Mister Smith

2
"실행"의 당신의 정의에 따라 당신은 onResume과 onPause에서 변수의 상태 .... 변경할 수 있습니다
— G. 블레이크 마이 케

5
이 솔루션은 전혀 좋은 솔루션이 아닙니다. 예를 들어, Activity가 Fragment를 호출한다고 가정 해 봅시다. 예를 들어 조각은 Activity 위에 있지만 Activity는 onPause를 호출하지 않으며 조각을 닫으면 onStop, onStart 또는 다른 수명주기 메소드도 호출되지 않습니다. 최상의 솔루션은 여기에 설명 된대로 애플리케이션 클래스에서 가시성을 확인하는 것입니다. stackoverflow.com/questions/18038399/…
— Portfoliobuilder

6
스태틱을 추천하면 나에게서 -1을 얻습니다
— Matei Suica

52

이 문제는 상당히 오래되었다는 것을 알고 있지만 다른 사람들에게 유용 할 수 있으므로 여전히 솔루션을 공유 할 가치가 있다고 생각합니다.

이 솔루션은 Android Architecture Components가 출시되기 전에는 사용할 수 없었습니다.

활동이 적어도 부분적으로 보입니다

getLifecycle().getCurrentState().isAtLeast(STARTED)

활동은 전경에 있습니다

getLifecycle().getCurrentState().isAtLeast(RESUMED)

3
getLifecycle (). getCurrentState (). isAtLeast (Lifecycle.State.RESUMED)
— Radhey

43

나는 더 분명하게 생각합니다.

  public boolean isRunning(Context ctx) {
        ActivityManager activityManager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);

        for (RunningTaskInfo task : tasks) {
            if (ctx.getPackageName().equalsIgnoreCase(task.baseActivity.getPackageName())) 
                return true;                                  
        }

        return false;
    }

2
'for'루프 전에 임시 변수를 만들지 않으려 고합니다. for (RunningTaskInfo 작업 : ActivityManager.getRunningTasks (Integer.MAX_VALUE)) {...
— mikebabcock

이 함수를 어떻게 호출 할 수 있습니까?
— Behzad

1
평소와 같이 클래스 내부에서 '함수'로 호출 할 수있는 방법이 있습니까? 예가 필요합니까?
— Xenione

10
에서 developer.android.com/reference/android/app/... "이것은 이러한 사용은 지원되지 않습니다. 그러한 정보가 여기에 따라 다른 행동 사이의 결정으로, 응용 프로그램에서 핵심 로직에 사용되지 않을 및 휴식 가능성이 것입니다한다 앞으로. "
— joe_deniable

15
API 레벨 21 (Android 5.0 Lollipop)부터이 방법은 더 이상 사용되지 않습니다.
— AxeEffect 3

30

보조 변수를 사용하지 않는 옵션은 다음과 같습니다.

activity.getWindow().getDecorView().getRootView().isShown()

활동이 fe 인 경우 : this 또는 getActivity ().

이 표현식이 리턴 한 값은 onStart () / onStop ()에서 변경되며, 이는 전화기에서 활동의 레이아웃 표시를 시작 / 중지하는 이벤트입니다.


16
왜 사용하지 Activity#getWindow().getDecorView().isShown()않습니까?
— Gianluca P.

24

MyActivity.class 및 getCanonicalName 메서드를 사용하여 답변을 받았습니다.

protected Boolean isActivityRunning(Class activityClass)
{
        ActivityManager activityManager = (ActivityManager) getBaseContext().getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);

        for (ActivityManager.RunningTaskInfo task : tasks) {
            if (activityClass.getCanonicalName().equalsIgnoreCase(task.baseActivity.getClassName()))
                return true;
        }

        return false;
}

1
앞서 언급 한 바와 같이, 그것은 사용하기 좋은 아이디어하지 될 수 getRunningTasks()는 사용되지 않습니다 같이 androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/...
— Vitalii 드미트리

21

정적 변수를 사용하고 OOP를 따르는 것보다 훨씬 좋은 방법

Shared Preferencesactivities하나의 다른 서비스 및 서비스 와 변수를 공유하는 데 사용할 수 있습니다application

    public class example extends Activity {

    @Override
    protected void onStart() {
        super.onStart();

        // Store our shared preference
        SharedPreferences sp = getSharedPreferences("OURINFO", MODE_PRIVATE);
        Editor ed = sp.edit();
        ed.putBoolean("active", true);
        ed.commit();
    }

    @Override
    protected void onStop() {
        super.onStop();

        // Store our shared preference
        SharedPreferences sp = getSharedPreferences("OURINFO", MODE_PRIVATE);
        Editor ed = sp.edit();
        ed.putBoolean("active", false);
        ed.commit();

    }
}

공유 환경 설정을 사용하십시오. 가장 안정적인 상태 정보를 가지고 있으며 응용 프로그램 전환 / 파괴 문제가 적으며, 또 다른 권한을 요청하지 않아도되며 활동이 실제로 가장 최상위 인 시점을 결정할 수있는 제어 기능이 향상됩니다. 참조 자세한 내용은 여기 ABD를 여기


감사. 그러나 onResume도 형제가 필요합니까?

1
그것은 당신이 활동적으로 이해하는 것에 달려 있습니다. 내 코드에 따르면 Activity는 스택에 있고 활성화되어 있습니다. 그리고 당신이 보이는 것을 처리하고 싶거나 원하지 않는다면 onResume
— Zar E Ahmer를

19
전화하지 않고 활동이 종료되면 onStop()
— Marcel Bro

3
앱이 충돌하면 어떻게 되나요?
— ucMedia

1
이것은 매우 위험한 "솔루션"입니다.
— Firzen

9

특정 서비스가 실행 중인지 확인하기위한 코드입니다. getRunningAppProcesses () 또는 getRunningTasks ()를 사용하여 getRunningServices를 변경하는 한 활동에 대해서도 작동 할 수 있다고 확신합니다. 여기 http://developer.android.com/reference/android/app/ActivityManager.html#getRunningAppProcesses ()를 살펴보십시오.

이에 따라 Constants.PACKAGE 및 Constants.BACKGROUND_SERVICE_CLASS를 변경하십시오.

    public static boolean isServiceRunning(Context context) {

    Log.i(TAG, "Checking if service is running");

    ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);

    List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);

    boolean isServiceFound = false;

    for (int i = 0; i < services.size(); i++) {

        if (Constants.PACKAGE.equals(services.get(i).service.getPackageName())){

            if (Constants.BACKGROUND_SERVICE_CLASS.equals(services.get(i).service.getClassName())){
                isServiceFound = true;
            }
        }
    }

    Log.i(TAG, "Service was" + (isServiceFound ? "" : " not") + " running");

    return isServiceFound;

}

1
그러나 귀하가 제공하는 링크는 "이 방법은 사용자가 직면 한 프로세스 관리 UI를 디버깅하거나 구축하기위한 것입니다"라는 것을 명심하십시오.
— joe_deniable

getRunningTasks는 더 이상 사용되지 않습니다.
— Adi

5

위의 모든 것보다 훨씬 쉬운 방법이 있으며이 방법 android.permission.GET_TASKS은 매니페스트에서 사용을 요구하지 않거나 허용되는 답변에서 경쟁 조건 또는 메모리 누수 문제가 지적되었습니다.

  1. 기본 활동에서 STATIC 변수를 작성하십시오. 정적은 다른 활동이 다른 활동으로부터 데이터를 수신 할 수있게합니다. onPause()이 변수를 설정 거짓을 , onResume그리고 onCreate()이 변수로 설정 사실을 .

    private static boolean mainActivityIsOpen;
  2. 이 변수의 getter 및 setter를 지정하십시오.

    public static boolean mainActivityIsOpen() {
        return mainActivityIsOpen;
    }
    
    public static void mainActivityIsOpen(boolean mainActivityIsOpen) {
        DayView.mainActivityIsOpen = mainActivityIsOpen;
    }
  3. 그리고 다른 활동이나 서비스에서

    if (MainActivity.mainActivityIsOpen() == false)
    {
                    //do something
    }
    else if(MainActivity.mainActivityIsOpen() == true)
    {//or just else. . . ( or else if, does't matter)
            //do something
    }

3
원시 공용 정적 변수를 사용하는 것보다 접근 자 메서드를 사용하는 것이 낫다는 말입니까?
— IgorGanapolsky 2013

1
Java에서는 변수를 비공개로 유지하기 위해 setter 및 getter를 사용하는 것이 좋습니다. 그러나 안드로이드에서는 공개 변수에 직접 액세스하는 것이 일반적이라고 생각합니다.
— Stephen

11
활동 상태는 활동 자체에 의해서만 처리되어야하므로 공개 세터를 갖는 것은 의미가 없습니다. Java 명명 규칙을 준수해야합니다. isActivityOpen은 올바른 getter 메소드입니다. 또한 부울 == true 인 경우에도 중복이 사용됩니다. 게다가, 활동에 상태 관리를 위임하는 것이 최선의 방법입니다.
— Lisandro 12

8
이것이 여러분의 강의에 더 부지런히 참석해야하는 이유입니다. @coolcool;)
— Jerec TheSith

1
그리고 여러 개의 활동 인스턴스가 실행 중이면 어떻게해야합니까?
— nickmartens1980

5
if(!activity.isFinishing() && !activity.isDestroyed())

공식 문서에서 :

활동 #isFinishing ()

finish ()를 호출했거나 다른 사람이 완료를 요청했기 때문에이 활동이 완료 중인지 확인하십시오. 이것은 종종 onPause ()에서 활동이 단순히 일시 중지되었는지 또는 완전히 마무리되는지를 결정하는 데 사용됩니다.

활동 # isDestroyed ()

Activity에서 최종 onDestroy () 호출이 수행되었으므로이 인스턴스가 현재 종료 된 경우 true를 리턴합니다.


4

고마워 kkudi! 활동을 위해 귀하의 답변을 조정할 수있었습니다 ... 여기 내 앱에서 작동 한 것이 있습니다 ..

public boolean isServiceRunning() { 

ActivityManager activityManager = (ActivityManager)Monitor.this.getSystemService (Context.ACTIVITY_SERVICE); 
    List<RunningTaskInfo> services = activityManager.getRunningTasks(Integer.MAX_VALUE); 
    isServiceFound = false; 
    for (int i = 0; i < services.size(); i++) { 
        if (services.get(i).topActivity.toString().equalsIgnoreCase("ComponentInfo{com.lyo.AutoMessage/com.lyo.AutoMessage.TextLogList}")) {
            isServiceFound = true;
        }
    } 
    return isServiceFound; 
} 

이 예제는 topActivity가 사용자의 작업과 일치하는 경우 true 또는 false를 제공합니다. 따라서 확인한 활동이 표시되지 않는 경우 (즉, onPause 인 경우) 일치하지 않습니다. 또한 이렇게하려면 매니페스트에 권한을 추가해야합니다.

<uses-permission  android:name="android.permission.GET_TASKS"/>

도움이 되었기를 바랍니다.


1
이 사용-권한은 API 레벨 21에 사용되지 않습니다 developer.android.com/reference/android/...
— 가이 웨스트

2
Annswer becuase를 하향 조정하여 API 레벨 Q를 최상위 활동 (services [i] .topActivity)에 액세스하십시오. 아래에서 작동하지 않습니다.
— Debasish Ghosh

4

나는 수용 된 대답이 이것을 처리하는 끔찍한 방법이라고 생각합니다.

유스 케이스가 무엇인지 모르지만 기본 클래스의 보호 된 메소드를 고려하십시오

@protected
void doSomething() {
}

파생 클래스에서 재정의합니다.

이벤트가 발생하면 기본 클래스에서이 메소드를 호출하십시오. 올바른 'active'클래스가 처리합니다. 그런 다음 클래스 자체가 아닌지 확인할 수 있습니다 Paused().

더 나은 방법은 GreenRobot 's , Square ' s 와 같은 이벤트 버스를 사용하는 것입니다.하지만 더 이상 사용되지 않으며 RxJava 사용을 제안합니다


2

나는 수표를 사용했고 if (!a.isFinishing())내가 필요한 것을하는 것처럼 보인다. a활동 인스턴스입니다. 이것이 맞지 않습니까? 아무도 이것을 시도하지 않은 이유는 무엇입니까?



2

ActivityLifecycleCallbacks는 앱의 모든 활동을 추적하는 좋은 방법입니다.

public class BaseActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {

private ActivityState homeState, contentState;

@Override
public void onActivityCreated(Activity activity, Bundle bundle) {
    if (activity instanceof HomeActivityv2) {
        homeState = ActivityState.CREATED;
    } else if (activity instanceof ContentDisplayActivity) {
        contentState = ActivityState.CREATED;
    }
}

@Override
public void onActivityStarted(Activity activity) {
    if (activity instanceof HomeActivityv2) {
        homeState = ActivityState.STARTED;
    } else if (activity instanceof ContentDisplayActivity) {
        contentState = ActivityState.STARTED;
    }
}

@Override
public void onActivityResumed(Activity activity) {
    if (activity instanceof HomeActivityv2) {
        homeState = ActivityState.RESUMED;
    } else if (activity instanceof ContentDisplayActivity) {
        contentState = ActivityState.RESUMED;
    }
}

@Override
public void onActivityPaused(Activity activity) {
    if (activity instanceof HomeActivityv2) {
        homeState = ActivityState.PAUSED;
    } else if (activity instanceof ContentDisplayActivity) {
        contentState = ActivityState.PAUSED;
    }
}

@Override
public void onActivityStopped(Activity activity) {
    if (activity instanceof HomeActivityv2) {
        homeState = ActivityState.STOPPED;
    } else if (activity instanceof ContentDisplayActivity) {
        contentState = ActivityState.STOPPED;
    }
}

@Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}

@Override
public void onActivityDestroyed(Activity activity) {
    if (activity instanceof HomeActivityv2) {
        homeState = ActivityState.DESTROYED;
    } else if (activity instanceof ContentDisplayActivity) {
        contentState = ActivityState.DESTROYED;
    }
}

public ActivityState getHomeState() {
    return homeState;
}

public ActivityState getContentState() {
    return contentState;
}
}

ActivityState :

public enum ActivityState {
    CREATED, STARTED, RESUMED, PAUSED, STOPPED, DESTROYED;
}

Application 클래스를 확장하고 Android Manifest 파일에서 해당 참조를 제공하십시오.

import android.app.Application;

public final class BaseApplication extends Application {
private BaseActivityLifecycleCallbacks baseALC;

@Override
public void onCreate() {
    super.onCreate();
    baseALC = new BaseActivityLifecycleCallbacks();
    this.registerActivityLifecycleCallbacks(baseALC);

}

public BaseActivityLifecycleCallbacks getBaseALC() {
    return baseALC;
}
}

다른 활동 상태에 대한 활동 어디에서나 Ckeck :

private void checkAndLaunchHomeScreen() {
    Application application = getApplication();
    if (application instanceof BaseApplication) {
        BaseApplication baseApplication = (BaseApplication) application;
        if (baseApplication.getBaseALC().getHomeState() == null || baseApplication.getBaseALC().getHomeState() == ActivityState.DESTROYED) {
            //Do anything you want
        }
    }
}

https://developer.android.com/reference/android/app/Application.ActivityLifecycleCallbacks.html


1

"일을하는" "적절한"방법인지 확실하지 않습니다.
조금 생각 해야하는 것보다 (또는 a) 질문을 해결하는 API 방법이 없다면, 뭔가 잘못하고 있거나 더 많은 문서를 대신 읽을
수 있습니다 (정적 변수는 안드로이드에서 일반적으로 잘못된 방법입니다. 작동 할 수는 있지만 (예 : 프로덕션, 백만 장치에서) 작동하지 않는 경우가 있습니다.
정확히 귀하의 경우에 다른 활동이 살아 있는지 여부를 알아야 하는 이유 를 생각하는 것이 좋습니다 . 또는 클래스를 파생하여 기능 등을 얻을 수 있습니다.
친애하는.


1

특정 활동 인스턴스의 수명주기 상태에 관심이있는 경우, 새로운 "활성"변수가 정적이 아닌 인스턴스 변수 여야한다는 점을 제외하고는 실리콘 이글 솔루션이 올바르게 보입니다.


1

주문 된 방송을 사용하십시오. http://android-developers.blogspot.nl/2011/01/processing-order-broadcasts.html을 참조하십시오

활동에서 onStart에 수신자를 등록하고 onStop에서 등록을 취소하십시오. 예를 들어 서비스가 활동이 더 잘 수행 할 수있는 작업을 처리해야하는 경우 서비스 자체에서 기본 처리기를 사용하여 서비스에서 주문 된 브로드 캐스트를 보냅니다. 이제 활동이 실행 중일 때 응답 할 수 있습니다. 서비스는 결과 데이터를 확인하여 브로드 캐스트가 처리되었는지와 적절한 조치를 취하지 않았는지 확인할 수 있습니다.


1

허용되는 답변 외에도 활동의 인스턴스가 여러 개인 경우 대신 카운터를 사용할 수 있습니다.

class MyActivity extends Activity {

     static int activeInstances = 0;

     static boolean isActive() {
        return (activeInstance > 0)
     }

      @Override
      public void onStart() {
         super.onStart();
         activeInstances++;
      } 

      @Override
      public void onStop() {
         super.onStop();
         activeInstances--;
      }
}

리턴 라인에 "s"와 "; (세미 콜론)"이 없습니다.
— Ali_dev

1

당신이 시도 ..

    if (getActivity() instanceof NameOfYourActivity){
        //Do something
    }

0

다음 코드로 쉬운 해결 방법을 찾았습니다.

@Override 
protected void onCreate(Bundle savedInstanceState) { 
            super.onCreate(savedInstanceState); 
            if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { 
                // Activity is being brought to front and not being  created again, 
                // Thus finishing this activity will bring the last viewed activity to foreground
                finish(); 
            } 
    }

0

활동이 활성인지 여부를 확인하려면 isActivity 변수를 사용하십시오.

private boolean activityState = true;

 @Override
protected void onDestroy() {
    super.onDestroy();
    activityState = false;
}

그런 다음 확인

if(activityState){
//add your code
}

0

액티비티가 백 스택에 있는지 확인하려면 다음 단계를 따르십시오. 1. 응용 프로그램 클래스에서 ArrayList 선언 [응용 프로그램 클래스는 응용 프로그램 태그의 mainfest 파일에 정의 됨]

private ArrayList<Class> runningActivities = new ArrayList<>();
  1. 이 목록에 액세스하고 수정하려면 다음 공용 메소드를 추가하십시오.

    public void addActivityToRunningActivityies (Class cls) {
    if (!runningActivities.contains(cls)) runningActivities.add(cls);
    }
    
    public void removeActivityFromRunningActivities (Class cls) {
    if (runningActivities.contains(cls)) runningActivities.remove(cls);
    }
    
    public boolean isActivityInBackStack (Class cls) {
    return runningActivities.contains(cls);
    }
  2. 모든 활동이이를 확장하는 BaseActivity에서 onCreate 및 onDestroy 메소드를 대체하여 다음과 같이 백 스택에서 활동을 추가 및 제거 할 수 있습니다.

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    ((MyApplicationClass)getApplication()).addActivityToRunningActivityies
    (this.getClass());
    }
    
    @Override
    protected void onDestroy() {
    super.onDestroy();
    
    ((MyApplicationClass)getApplication()).removeActivityFromRunningActivities
    (this.getClass());
    }
  3. 마지막으로 활동이 백 스택에 있는지 여부를 확인하려면이 함수 isActivityInBackStack을 호출하지 마십시오.

예 : HomeActivity가 백 스택에 있는지 확인하고 싶습니다.

if (((MyApplicationClass) 
getApplication()).isActivityInBackStack(HomeActivity.class)) {
       // Activity is in the back stack
    } else {
       // Activity is not in the back stack
    }

0
public static boolean isActivityActive(Activity activity) {
    return !activity.isFinishing() &&
            (SDK_INT < JELLY_BEAN_MR1 || !activity.isDestroyed());
}

-1

전경에서 동일한 활동이없는 경우 작동합니다. 알림에서 열면 작동하지 않습니다. 조정하고 다음과 같이 제공했습니다.

public static boolean ativo = false;
public static int counter = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    counter++;
}

@Override
protected void onStart() {
    super.onStart();
    ativo = true;
}

@Override
protected void onStop() {
    super.onStop();
    if (counter==1) ativo = false;
}

@Override
protected void onDestroy() {
    counter--;
    super.onDestroy();
}

그것은 동시에 여러 활동을 열어서 나를 위해 일합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.