Android: bagaimana cara memeriksa apakah aktivitas sedang berjalan?

152

Adakah cara sederhana untuk menentukan apakah suatu kegiatan tertentu aktif atau tidak? Saya ingin melakukan hal-hal tertentu tergantung pada aktivitas mana yang aktif. misalnya:

if(activityrunning == activity1)
//do this
else if (activityrunning == activity2)
//do something else
pengguna560571
sumber
Untuk memeriksa apakah suatu Aktivitas sedang berjalan atau tidak, Anda dapat melewati jawaban ini: stackoverflow.com/a/39079627/4531507
Rahul Sharma

Jawaban:

227

Anda dapat menggunakan staticvariabel dalam aktivitas.

class MyActivity extends Activity {
     static boolean active = false;

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

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

Satu-satunya Gotcha adalah bahwa jika Anda menggunakannya dalam dua kegiatan yang menghubungkan satu sama lain maka onStoppada yang pertama kadang-kadang disebut setelah onStartdi kedua. Jadi keduanya mungkin benar secara singkat.

Bergantung pada apa yang Anda coba lakukan (perbarui aktivitas saat ini dari layanan?). Anda bisa mendaftarkan pendengar statis di layanan dalam onStartmetode aktivitas Anda maka pendengar yang benar akan tersedia ketika layanan Anda ingin memperbarui UI.

siliconeagle
sumber
5
Seseorang menunjukkan hal ini kepada saya bahwa ... Preferensi berbagi harus lebih disukai daripada variabel statis karena masalah kebocoran memori.
Ayush Goyal
13
Bagaimana jika ada kegiatan berbeda dari kelas yang sama berjalan? Bagaimana jika Anda memperpanjang MyActivitydengan MyChildactivitydan ingin memeriksa apakah anak tersebut aktif?
Tuan Smith
2
Bergantung pada definisi "menjalankan" Anda, Anda mungkin ingin mengubah status variabel di onResume dan onPause ....
G. Blake Meike
5
Solusi ini sama sekali bukan solusi yang baik. Katakanlah Aktivitas Anda memanggil Fragmen, misalnya, fragmen tersebut akan melebihi Aktivitas namun Aktivitas tidak akan memanggil pada Jeda, dan jika Anda menutup fragmen di Berhenti, di Mulai, atau metode siklus hidup lainnya tidak akan dipanggil juga. Solusi terbaik adalah memeriksa visibilitas di kelas Aplikasi Anda seperti dijelaskan di sini: stackoverflow.com/questions/18038399/…
portfoliobuilder
6
Jika Anda merekomendasikan statika, Anda mendapatkan -1 dari saya
Matei Suica
52

Saya menyadari masalah ini cukup lama, tetapi saya pikir masih ada baiknya membagikan solusi saya karena mungkin bermanfaat bagi orang lain.

Solusi ini tidak tersedia sebelum Komponen Arsitektur Android dirilis.

Aktivitas setidaknya terlihat sebagian

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

Aktivitas ada di latar depan

getLifecycle().getCurrentState().isAtLeast(RESUMED)
Malinjir
sumber
3
getLifecycle (). getCurrentState (). isAtLeast (Lifecycle.State.RESUMED)
Radhey
43

Saya pikir lebih jelas seperti itu:

  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;
    }
Xenione
sumber
2
Saya mencoba untuk menghindari membuat variabel sementara sebelum perulangan 'untuk'; untuk (tugas RunningTaskInfo: ActivityManager.getRunningTasks (Integer.MAX_VALUE)) {...
mikebabcock
Bagaimana saya bisa memanggil fungsi ini?
Behzad
1
seperti biasa, apakah metode yang dapat Anda panggil di dalam kelas Anda sebagai 'fungsi' apakah Anda memerlukan contoh?
Xenione
10
Dari developer.android.com/reference/android/app/… "Ini tidak boleh digunakan untuk logika inti dalam aplikasi, seperti memutuskan antara perilaku yang berbeda berdasarkan informasi yang ditemukan di sini. Penggunaan tersebut tidak didukung, dan kemungkinan akan pecah di masa depan."
joe_deniable
15
Pada tingkat API 21 (Android 5.0 Lollipop) metode ini sudah usang.
AxeEffect
30

Opsi tanpa menggunakan variabel bantu apa pun adalah:

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

di mana aktivitas adalah fe: this or getActivity ().

Nilai yang dikembalikan oleh ekspresi ini berubah di onStart () / onStop (), yang merupakan peristiwa yang mulai / berhenti menunjukkan tata letak aktivitas di telepon.

GaRRaPeTa
sumber
16
mengapa tidak hanya digunakan Activity#getWindow().getDecorView().isShown()?
Gianluca P.
24

Saya menggunakan metode MyActivity.class dan getCanonicalName dan saya mendapat jawaban.

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;
}
mahyar
sumber
1
Seperti disebutkan sebelumnya, ini mungkin bukan ide yang baik untuk digunakan getRunningTasks()karena sudah tidak digunakan lagi: androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/…
Vitalii Dmitriev
21

Cara yang jauh lebih baik daripada menggunakan variabel statis dan mengikuti OOP

Shared Preferencesdapat digunakan untuk berbagi variabel dengan lainnya activitiesdan layanan dari satuapplication

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

    }
}

Gunakan preferensi bersama. Ia memiliki informasi keadaan paling dapat diandalkan, lebih sedikit masalah peralihan / penghancuran aplikasi, menyelamatkan kami untuk meminta izin lagi dan memberi kami lebih banyak kontrol untuk memutuskan kapan aktivitas kami sebenarnya paling atas. melihat rincian di sini abd sini juga

Zar E Ahmer
sumber
Terima kasih. Tapi apakah onResume juga butuh bro?
1
Itu tergantung pada apa yang Anda pahami secara aktif. Menurut kode saya, Aktivitas dalam tumpukan kemudian aktif. Dan jika Anda ingin menangani yang terlihat atau tidak, Anda dapat menggunakan onResume
Zar E Ahmer
19
Ini rusak ketika aktivitas terbunuh tanpa menelepon onStop()
Marcel Bro
3
Apa yang terjadi jika Aplikasi macet?
ucMedia
1
Ini adalah "solusi" yang sangat berbahaya.
Firzen
9

Ini adalah kode untuk memeriksa apakah suatu layanan tertentu sedang berjalan. Saya cukup yakin itu dapat bekerja untuk suatu aktivitas juga selama Anda mengubah getRunningServices dengan getRunningAppProcesses () atau getRunningTasks (). Lihat di sini http://developer.android.com/reference/android/app/ActivityManager.html#getRunningAppProcesses ()

Ubah Constants.PACKAGE dan Constants.BACKGROUND_SERVICE_CLASS sesuai

    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;

}
kkudi
sumber
1
Tetapi ingatlah bahwa tautan yang Anda berikan menyatakan "metode ini hanya dimaksudkan untuk debugging atau membangun UI manajemen proses yang menghadap pengguna."
joe_deniable
getRunningTasks sekarang sudah tidak digunakan lagi.
Adi
5

Ada cara yang jauh lebih mudah daripada segala sesuatu di atas dan pendekatan ini tidak memerlukan penggunaan android.permission.GET_TASKSdalam manifes, atau memiliki masalah kondisi balapan atau kebocoran memori yang ditunjukkan dalam jawaban yang diterima.

  1. Buat variabel STATIC dalam Kegiatan utama. Statis memungkinkan kegiatan lain untuk menerima data dari kegiatan lain. onPause()setel variabel ini salah ,onResume dan onCreate()setel variabel ini benar .

    private static boolean mainActivityIsOpen;
  2. Tetapkan getter dan setter dari variabel ini.

    public static boolean mainActivityIsOpen() {
        return mainActivityIsOpen;
    }
    
    public static void mainActivityIsOpen(boolean mainActivityIsOpen) {
        DayView.mainActivityIsOpen = mainActivityIsOpen;
    }
  3. Dan kemudian dari aktivitas atau Layanan lain

    if (MainActivity.mainActivityIsOpen() == false)
    {
                    //do something
    }
    else if(MainActivity.mainActivityIsOpen() == true)
    {//or just else. . . ( or else if, does't matter)
            //do something
    }
coolcool1994
sumber
3
Apakah Anda mengatakan bahwa menggunakan metode accessor lebih baik daripada menggunakan variabel statis publik mentah?
IgorGanapolsky
1
Di Jawa lebih baik menggunakan setter dan getter untuk menjaga agar variabel Anda tetap pribadi. Namun, saya percaya bahwa di Android adalah umum untuk mengakses variabel publik secara langsung ...
Stephen
11
Tidak masuk akal untuk memiliki setter publik karena keadaan aktivitas harus ditangani hanya oleh aktivitas itu sendiri. Anda harus tetap menggunakan konvensi penamaan java: isActivityOpen akan menjadi metode pengambil yang benar. Juga menggunakan jika boolean == true redundan. Selain itu, mendelegasikan manajemen negara ke kegiatan adalah pendekatan terbaik.
Lisandro
8
ini sebabnya kamu harus lebih rajin mengikuti kursusmu @coolcool;)
Jerec TheSith
1
Dan bagaimana jika Anda memiliki beberapa contoh aktivitas berjalan?
nickmartens1980
5
if(!activity.isFinishing() && !activity.isDestroyed())

Dari dokumen resmi:

Activity # isFinishing ()

Periksa untuk melihat apakah kegiatan ini sedang dalam proses penyelesaian, baik karena Anda memanggil selesai () di atasnya atau orang lain telah meminta agar kegiatan tersebut selesai. Ini sering digunakan di onPause () untuk menentukan apakah aktivitas hanya berhenti atau selesai sepenuhnya.

Activity # isDestroyed ()

Mengembalikan nilai true jika panggilan onDestroy () terakhir telah dibuat pada Activity, jadi instance ini sekarang mati.

Codelicious
sumber
4

terima kasih kkudi! Saya dapat menyesuaikan jawaban Anda untuk bekerja untuk suatu kegiatan ... inilah yang bekerja di aplikasi saya ..

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

contoh ini akan memberi Anda benar atau salah jika topActivity cocok dengan apa yang dilakukan pengguna. Jadi, jika aktivitas yang Anda periksa tidak ditampilkan (yaitu onPause) maka Anda tidak akan mendapatkan kecocokan. Juga, untuk melakukan ini, Anda perlu menambahkan izin ke manifes Anda ..

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

Saya harap ini membantu!

alyon2002
sumber
1
Izin penggunaan ini tidak lagi digunakan di API level 21. developer.android.com/reference/android/…
Guy West
2
Turunkan pengumuman itu karena mengakses aktivitas teratas (layanan [i] .topActivity) kami min tingkat API Q. Di bawah ini tidak akan berfungsi.
Debasish Ghosh
4

Saya pikir jawaban yang diterima adalah cara yang buruk untuk menangani ini.

Saya tidak tahu apa itu use case, tapi tolong pertimbangkan metode yang dilindungi di kelas dasar

@protected
void doSomething() {
}

dan menimpanya di kelas turunan.

Ketika acara tersebut terjadi, panggil saja metode ini di kelas dasar. Kelas 'aktif' yang benar akan menanganinya kemudian. Kelas itu sendiri kemudian dapat memeriksa apakah tidakPaused() .

Lebih baik lagi, gunakan bus acara seperti GreenRobot's , Square's , tetapi yang sudah usang dan menyarankan menggunakan RxJava

Anak laki-laki
sumber
2

Saya menggunakan cek if (!a.isFinishing())dan sepertinya melakukan apa yang saya butuhkan. aadalah contoh aktivitas. Apakah ini salah? Kenapa tidak ada yang mencoba ini?

lxknvlk
sumber
2

bagaimana dengan activity.isFinishing()

Ambareesh B
sumber
Ini bukan solusi yang baik karena isFinishing menunjukkan jika ada aktivitas dalam proses pembunuhan.
VelocityPulse
2

ActivityLifecycleCallbacks adalah cara yang bagus untuk melacak semua aktivitas di App:

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

Status Kegiatan:

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

Perpanjang kelas Aplikasi dan berikan rujukannya dalam file 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;
}
}

Klik di mana saja dari Aktivitas untuk status aktivitas lain:

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

Suyash Gupta
sumber
1

Tidak yakin itu adalah cara yang "tepat" untuk "melakukan sesuatu".
Jika tidak ada cara API untuk menyelesaikan (atau a) pertanyaan daripada yang seharusnya Anda pikirkan sedikit, mungkin Anda melakukan sesuatu yang salah dan membaca lebih banyak dokumen, dll.
(Seperti yang saya pahami variabel statis adalah cara yang umumnya salah di android. Penyebabnya itu bisa bekerja, tetapi pasti akan ada kasus ketika itu tidak akan berhasil [misalnya, dalam produksi, pada jutaan perangkat]).
Tepat dalam kasus Anda, saya sarankan untuk berpikir mengapa Anda perlu tahu apakah ada aktivitas lain yang masih hidup? .. Anda dapat memulai aktivitas lain untuk mendapatkan fungsionalitasnya. Atau Anda dapat menurunkan kelas untuk mendapatkan fungsionalitasnya dan sebagainya.
Salam Hormat.

pengguna2399321
sumber
1

Jika Anda tertarik pada siklus hidup dari instance spesifik aktivitas, solusi siliconeagle terlihat benar kecuali bahwa variabel "aktif" yang baru harus menjadi variabel instan, bukan statis.

Jonathan Taylor
sumber
1

Gunakan siaran yang dipesan. Lihat http://android-developers.blogspot.nl/2011/01/processing-ordered-broadcasts.html

Dalam aktivitas Anda, daftarkan penerima di onStart, batalkan pendaftaran di onStop. Sekarang ketika misalnya suatu layanan perlu menangani sesuatu yang aktivitasnya mungkin dapat melakukan lebih baik, mengirim siaran yang dipesan dari layanan (dengan penangan default di layanan itu sendiri). Anda sekarang dapat merespons dalam aktivitas saat sedang berjalan. Layanan dapat memeriksa data hasil untuk melihat apakah siaran ditangani, dan jika tidak mengambil tindakan yang sesuai.

nickmartens1980
sumber
1

Selain jawaban yang diterima , jika Anda memiliki beberapa contoh aktivitas, Anda dapat menggunakan penghitung sebagai gantinya:

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--;
      }
}
james_alvarez
sumber
hilang "s" dan "; (titik dua)" di baris kembali.
Ali_dev
1

Sudahkah Anda mencoba ..

    if (getActivity() instanceof NameOfYourActivity){
        //Do something
    }
E.Mathew
sumber
0

Menemukan solusi yang mudah dengan kode berikut

@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(); 
            } 
    }
Varun Bhatia
sumber
0

Gunakan variabel isActivity untuk memeriksa apakah aktivitas hidup atau tidak.

private boolean activityState = true;

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

Lalu periksa

if(activityState){
//add your code
}
Faran Tariq
sumber
0

Jika Anda ingin memeriksa apakah aktivitas di tumpukan belakang ikuti saja langkah selanjutnya. 1. Mengumumkan ArrayList di kelas Aplikasi Anda [Kelas aplikasi didefinisikan dalam file mainfest Anda di tag aplikasi]

private ArrayList<Class> runningActivities = new ArrayList<>();
  1. Dan tambahkan metode publik berikut untuk mengakses dan memodifikasi daftar ini.

    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. Di BaseActivity Anda, tempat semua aktivitas memperluasnya, timpa metode onCreate dan onDestroy sehingga Anda bisa menambah dan menghapus aktivitas dari back stack sebagai berikut.

    @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. Akhirnya jika Anda ingin memeriksa apakah aktivitas ada di tumpukan belakang atau tidak, panggil saja fungsi ini isActivityInBackStack.

Mis: Saya ingin memeriksa apakah HomeActivityis ada di tumpukan belakang atau tidak:

if (((MyApplicationClass) 
getApplication()).isActivityInBackStack(HomeActivity.class)) {
       // Activity is in the back stack
    } else {
       // Activity is not in the back stack
    }
Hagar Magdy
sumber
0
public static boolean isActivityActive(Activity activity) {
    return !activity.isFinishing() &&
            (SDK_INT < JELLY_BEAN_MR1 || !activity.isDestroyed());
}
Ahamadullah Saikat
sumber
-1

Ini berfungsi jika Anda tidak memiliki aktivitas yang sama di latar depan. Jika Anda buka dari notifikasi tidak berfungsi saya membuat beberapa penyesuaian dan datang dengan ini:

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

Itu bekerja untuk saya dengan beberapa kegiatan terbuka pada saat yang sama.

Simao Coutinho
sumber