Android: etkinliğin çalışıp çalışmadığını nasıl kontrol ederim?


152

Belirli bir etkinliğin etkin olup olmadığını belirlemenin basit bir yolu var mı? Hangi etkinliğin etkin olduğuna bağlı olarak bazı şeyler yapmak istiyorum. Örneğin:

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

Bir Etkinliğin çalışıp çalışmadığını kontrol etmek için şu yanıtı
uygulayabilirsiniz

Yanıtlar:


227

staticEtkinlik içinde bir değişken kullanabilirsiniz .

class MyActivity extends Activity {
     static boolean active = false;

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

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

Tek sorun, birbirine bağlanan iki aktivitede kullanırsanız onStop, ilkinde bazen onStartikinci olarak çağrılır . Yani her ikisi de kısaca doğru olabilir.

Ne yapmaya çalıştığınıza bağlı olarak (bir hizmetten geçerli etkinliği güncellensin mi?). Etkinlik onStartyönteminizdeki hizmette statik bir dinleyici kaydedebilirsiniz, ardından hizmetiniz kullanıcı arayüzünü güncellemek istediğinde doğru dinleyici kullanılabilir olacaktır.


5
Bazıları bana şunu söyledi ki, bellek sızıntısı problemleri nedeniyle statik bir değişken yerine paylaşımlı tercih tercih edilmelidir.
Ayush Goyal

13
Aynı sınıftan farklı aktiviteler varsa ne olur? Ne uzatmak eğer MyActivityile MyChildactivityve çocuk aktif olup olmadığını kontrol etmek istiyor?
Mister Smith

2
"Koşu" tanımınıza bağlı olarak, onResume ve onPause değişkeninin durumunu değiştirmek isteyebilirsiniz ....
G. Blake Meike

5
Bu çözüm hiç de iyi bir çözüm değil. Etkinliğinizin bir Parçayı çağırdığını söyleyelim, örneğin, parçanın Aktivite üzerinde olacağını, ancak Aktivite onPause'u çağırmayacağını ve parçayı kapattığınızda onStop, onStart veya başka herhangi bir yaşam döngüsü yöntemi çağrılmayacak. En iyi çözüm, Uygulama sınıfınızda burada açıklandığı gibi görünürlük kontrol etmektir: stackoverflow.com/questions/18038399/…
portföy oluşturucu

6
Statik tavsiye ederseniz, benden -1 alırsınız
Matei Suica

52

Bu sorunun oldukça eski olduğunun farkındayım, ancak yine de başkaları için yararlı olabileceğinden çözümümü paylaşmaya değer olduğunu düşünüyorum.

Bu çözüm, Android Mimari Bileşenleri yayınlanmadan önce mevcut değildi.

Etkinlik en azından kısmen görülebilir

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

Etkinlik ön planda

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

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

43

Daha net düşünüyorum:

  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
Bir 'for' döngüsü önce geçici değişkenler yapmaktan kaçınmaya çalışın; for (RunningTaskInfo görevi: ActivityManager.getRunningTasks (Integer.MAX_VALUE)) {...
mikebabcock

Bu işlevi nasıl adlandırabilirim?
Behzad

1
her zamanki gibi, sınıfınızın içinde 'işlev' olarak adlandırabileceğiniz bir metod mu örnek olmalı?
Xenione

10
Gönderen developer.android.com/reference/android/app/... "Bu tür kullanımlar desteklenmez. Böyle bilgiyi burada dayalı farklı davranışlar arasında karar olarak, bir uygulamada temel mantığı için kullanılacak, asla ve kırılma olasılığı olacak gerektiğini gelecekte."
joe_deniable

15
API düzey 21'den (Android 5.0 Lollipop) itibaren bu yöntem kullanımdan kaldırılmıştır.
AxeEffect

30

Herhangi bir yardımcı değişken kullanmadan bir seçenek:

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

Burada etkinlik fe: this veya getActivity () şeklindedir.

Bu ifade tarafından döndürülen değer onStart () / onStop () biçiminde değişir; bunlar, telefondaki etkinliğin düzenini gösteren başlatma / durdurma olaylarıdır.


16
jsut neden kullanılmıyor Activity#getWindow().getDecorView().isShown()?
Gianluca P.

24

MyActivity.class ve getCanonicalName yöntemini kullandım ve yanıt aldım.

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
Daha önce de belirtildiği getRunningTasks()gibi, kullanımdan kaldırıldığı gibi kullanmak iyi bir fikir olmayabilir : androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/…
Vitalii Dmitriev

21

Statik değişken kullanmaktan ve OOP'yi takip etmekten çok daha iyi bir yol

Shared Preferencesdeğişkenleri bir diğeri activitiesve diğer servislerle paylaşmak için kullanılabilirapplication

    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();

    }
}

Paylaşılan tercihleri ​​kullanın. En güvenilir durum bilgisine sahiptir, daha az uygulama değiştirme / yok etme sorunları, başka bir izin istememizi sağlar ve faaliyetimizin aslında en üstte olup olmadığına karar vermemiz için daha fazla kontrol sağlar. ayrıntılara buradan bakın abd burada da


Teşekkürler. Ama onResume'e de ihtiyaç var mı kardeşim?

1
Aktif olarak ne anladığınıza bağlıdır. Koduma göre Etkinlik yığın halindeyken aktif durumda. Ve görünür veya işlemek istemiyorsanız onResume
Zar E Ahmer

19
Etkinlik aramadan öldürüldüğünde kırılıronStop()
Marcel Bro

3
Uygulama çökerse ne olur?
ucMedia

1
Bu çok tehlikeli bir "çözüm".
Firzen

9

Bu, belirli bir hizmetin çalışıp çalışmadığını kontrol etmek için kullanılan koddur. GetRunningAppProcesses () veya getRunningTasks () ile getRunningServices değiştirdiğiniz sürece bir etkinlik için çalışabilir oldukça eminim. Buraya bir bak http://developer.android.com/reference/android/app/ActivityManager.html#getRunningAppProcesses ()

Sabiti Değiştir.PACKAGE ve Sabitler.BACKGROUND_SERVICE_CLASS buna göre

    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
Ancak, sağladığınız bağlantının "bu yöntemin yalnızca kullanıcıyla karşılaşan bir süreç yönetimi kullanıcı arayüzünde hata ayıklamak veya oluşturmak için tasarlandığını" unutmayın.
joe_deniable

getRunningTasks artık kullanımdan kaldırıldı.
Adi

5

Yukarıdaki her şeyden çok daha kolay bir yol var ve bu yaklaşım android.permission.GET_TASKS, manifest'te kullanılmasını gerektirmiyor veya yarış koşulları veya hafıza sızıntıları sorununu kabul edilen cevapta belirtiyor.

  1. Ana Etkinlikte bir STATIC değişkeni yapın. Statik, diğer etkinliklerin başka bir etkinlikten veri almasına izin verir. onPause()Bu değişken set = false , onResumeve onCreate()bu değişken set doğrudur .

    private static boolean mainActivityIsOpen;
  2. Bu değişkenin alıcılarını ve ayarlayıcılarını atayın.

    public static boolean mainActivityIsOpen() {
        return mainActivityIsOpen;
    }
    
    public static void mainActivityIsOpen(boolean mainActivityIsOpen) {
        DayView.mainActivityIsOpen = mainActivityIsOpen;
    }
  3. Ve sonra başka bir faaliyet veya Hizmetten

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

3
Erişimci yöntemlerini kullanmanın ham genel statik değişkenleri kullanmaktan daha iyi olduğunu mu söylüyorsunuz?
IgorGanapolsky

1
Java'da değişkenlerinizi gizli tutmak için ayarlayıcıları ve alıcıları kullanmak daha iyidir. Ancak, Android'de genel değişkenlere doğrudan erişmek yaygın olduğuna inanıyorum ...
Stephen

11
Faaliyet durumunun yalnızca faaliyetin kendisi tarafından ele alınması gerektiğinden, halka açık bir belirleyici olması mantıklı değildir. Java adlandırma kurallarına uymalısınız: isActivityOpen doğru bir alıcı yöntemi olacaktır. Ayrıca eğer boolean == true gereksiz ise kullanmak. Bunun yanı sıra, devlet yönetimini etkinliğe devretmek en iyi yaklaşımdır.
Lisandro

8
u kurslarına daha özenle @coolcool;) katılmış olmanızın nedeni budur.)
Jerec TheSith

1
Peki ya faaliyetin birden fazla örneği varsa?
nickmartens1980

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

Resmi dokümanlardan:

Etkinlik # isFinishing ()

Bu etkinliğin bitirme sürecinde olup olmadığını kontrol edin, çünkü üzerinde finish () öğesini çağırdınız veya başka biri bitmesini istedi. Bu, etkinliğin basitçe duraklatıldığını veya tamamen bitip bitmediğini belirlemek için genellikle onPause () öğesinde kullanılır.

Etkinlik # isDestroyed ()

Etkinlik üzerinde son onDestroy () çağrısı yapılmışsa true değerini döndürür, bu nedenle bu örnek artık ölmüştür.


4

teşekkürler kkudi! Cevabınızı bir etkinlik için işe uyarlayabildim ... İşte uygulamamda işe yarayan şey buydu ..

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 kullanıcının yaptığıyla eşleşirse bu örnek size doğru veya yanlış verir. Bu nedenle, kontrol ettiğiniz etkinlik görüntülenmiyorsa (örn. OnPause), bir eşleşme elde edemezsiniz. Ayrıca, bunu yapmak için manifestinize izin eklemeniz gerekir.

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

Umarım bu yardımcı olmuştur!


1
Bu kullanım izni API düzey 21'de kullanımdan kaldırıldı. Developer.android.com/reference/android/…
Guy West

2
En yüksek aktiviteye (services [i] .topActivity) erişmek için anonim kullanıcıyı aşağıya indiririz API düzeyi Q'yu min. Çalışmaz.
Debasish Ghosh

4

Kabul edilen cevabın bunu ele almanın korkunç bir yolu olduğunu düşünüyorum.

Kullanım durumunun ne olduğunu bilmiyorum, ancak lütfen temel sınıfta korumalı bir yöntem düşünün

@protected
void doSomething() {
}

ve türetilmiş sınıfta geçersiz kılar.

Olay oluştuğunda, bu yöntemi temel sınıfta çağırmanız yeterlidir. Doğru 'aktif' sınıf o zaman onu idare edecektir. Daha sonra sınıfın kendisi olup olmadığını kontrol edebilir Paused().

Daha da iyisi, GreenRobot's , Square's gibi bir olay otobüsü kullanın , ancak bu kullanımdan kaldırıldı ve RxJava kullanmanızı önerir


2

Bir çek kullandım if (!a.isFinishing())ve ihtiyacım olanı yapıyor gibi görünüyor. aetkinlik örneğidir. Bu yanlış mı? Neden kimse bunu denemedi?


2

ne dersin activity.isFinishing()


İyi bir çözüm nedeni değilBitirme, bir öldürme sürecinde olup olmadığını gösterir.
VelocityPulse

2

ActivityLifecycleCallbacks, Uygulamadaki tüm etkinlikleri takip etmenin harika bir yoludur:

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;
}

Uygulama sınıfını genişletin ve referansını Android Manifest dosyasında sağlayın:

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;
}
}

Diğer etkinliğin durumu için Etkinlik'ten istediğiniz yere işaretleyin:

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

Emin değilim "şeyler" yapmak için "uygun" bir yoludur.
Eğer (veya bir) soruyu biraz düşünmenizden daha fazla çözmek için bir API yolu yoksa, belki yanlış bir şey yapıyorsunuz ve bunun yerine daha fazla dokümanı okuyorsunuzdur
. işe yarayabilir, ancak kesinlikle çalışmadığı durumlar olacaktır [örneğin üretimde, milyon cihazda].
Tam olarak sizin durumunuzda, neden başka bir etkinliğin canlı olup olmadığını bilmeniz gerektiğini düşünmenizi öneririm . Ya da işlevselliğini ve benzerlerini elde etmek için sınıfı türetebilirsiniz.
Saygılarımla.


1

Etkinliğin belirli bir örneğinin yaşam döngüsü durumuyla ilgileniyorsanız, siliconeagle'ın çözümü, yeni "etkin" değişkenin statik yerine bir örnek değişkeni olması dışında doğru görünüyor.


1

Sıralı bir yayın kullanın. Bkz. Http://android-developers.blogspot.nl/2011/01/processing-ordered-broadcasts.html

Etkinliğinizde, bir alıcıyı onStart'a kaydedin, onStop'a kaydını silin. Şimdi örneğin bir hizmetin, etkinliğin daha iyi yapabileceği bir şeyi işlemesi gerektiğinde, hizmetten düzenli bir yayın gönderin (hizmetin kendisinde varsayılan bir işleyici ile). Artık etkinlikte çalışırken yanıtlayabilirsiniz. Hizmet, yayının işlenip işlenmediğini görmek için sonuç verilerini kontrol edebilir ve uygun değilse önlem alabilir.


1

Kabul edilen cevaba ek olarak , etkinliğin birden fazla örneğine sahipseniz, bunun yerine bir sayaç kullanabilirsiniz:

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--;
      }
}

dönüş satırında "s" ve "; (noktalı virgül)" eksik.
Ali_dev

1

Denedin mi..

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

0

Aşağıdaki kodla kolay bir çözüm bulundu

@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

Etkinliğin canlı olup olmadığını kontrol etmek için isActivity değişkenini kullanın.

private boolean activityState = true;

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

Sonra kontrol et

if(activityState){
//add your code
}

0

Etkinliğin arka yığınta olup olmadığını kontrol etmek istiyorsanız, sonraki adımları takip edin. 1. Uygulama sınıfınızda bir ArrayList bildirildi [Uygulama sınıfı, uygulama etiketinde ana sınıf dosyanızda tanımlanır]

private ArrayList<Class> runningActivities = new ArrayList<>();
  1. Ve bu listeye erişmek ve listeyi değiştirmek için aşağıdaki genel yöntemleri ekleyin.

    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. Tüm etkinliklerin genişlettiği BaseActivity'nizde, onCreate ve onDestroy yöntemlerini geçersiz kılın, böylece aşağıdaki şekilde arka yığıntan etkinlik ekleyebilir ve kaldırabilirsiniz.

    @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. Son olarak, aktivitenin arka yığınta olup olmadığını kontrol etmek istiyorsanız, sadece bu fonksiyonu çağırmak için isActivityInBackStack.

Örn: HomeActivity'nin arka yığın içinde olup olmadığını kontrol etmek istiyorum:

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

Ön planda aynı etkinliğe sahip değilseniz bu iş. Bildirimden açmazsanız, bazı ayarlamalar yaptım ve bununla birlikte geldim:

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();
}

Bu benim için aynı anda açık birkaç etkinlikle işe yarıyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.