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.