Pertanyaan Bagaimana cara memeriksa apakah layanan berjalan di Android?


Bagaimana cara memeriksa apakah layanan latar belakang (di Android) berjalan?

Saya ingin aktivitas Android yang mengubah status layanan - itu memungkinkan saya mengaktifkannya jika mati dan hidup jika aktif.


794
2018-03-01 18:09


asal


Jawaban:


Saya memiliki masalah yang sama belum lama ini. Karena layanan saya bersifat lokal, saya akhirnya hanya menggunakan bidang statis di kelas layanan untuk beralih keadaan, seperti yang dijelaskan oleh hackbod sini

EDIT (untuk catatan):

Berikut ini solusi yang diajukan oleh hackbod:

Jika klien Anda dan kode server adalah bagian dari .apk yang sama dan Anda   mengikat ke layanan dengan maksud konkret (yang menentukan   kelas layanan tepat), maka Anda dapat mengatur layanan Anda   variabel global saat berjalan yang dapat diperiksa klien Anda.

Kami sengaja tidak memiliki API untuk memeriksa apakah layanan itu   berlari karena, hampir tanpa gagal, ketika Anda ingin melakukan sesuatu   seperti itu Anda berakhir dengan kondisi balapan di kode Anda.


248
2018-03-03 22:58



Saya menggunakan yang berikut ini dari dalam suatu kegiatan:

private boolean isMyServiceRunning(Class<?> serviceClass) {
    ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}

Dan saya menyebutnya menggunakan:

isMyServiceRunning(MyService.class)

Ini bekerja dengan andal, karena didasarkan pada informasi tentang menjalankan layanan yang disediakan oleh sistem operasi Android melalui ActivityManager # getRunningServices.

Semua pendekatan menggunakan onDestroy atau onSometing events atau Binder atau variabel statis tidak akan berfungsi dengan baik karena sebagai pengembang Anda tidak pernah tahu, ketika Android memutuskan untuk membunuh proses Anda atau panggilan balik mana yang disebut atau tidak. Harap perhatikan kolom "terbunuh" di tabel kejadian siklus hidup dalam dokumentasi Android.


1518
2018-05-07 12:54



Mengerti!

Kamu HARUS panggilan startService() agar layanan Anda terdaftar dan lulus dengan benar BIND_AUTO_CREATE tidak akan cukup.

Intent bindIntent = new Intent(this,ServiceTask.class);
startService(bindIntent);
bindService(bindIntent,mConnection,0);

Dan sekarang kelas ServiceTools:

public class ServiceTools {
    private static String LOG_TAG = ServiceTools.class.getName();

    public static boolean isServiceRunning(String serviceClassName){
        final ActivityManager activityManager = (ActivityManager)Application.getContext().getSystemService(Context.ACTIVITY_SERVICE);
        final List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);

        for (RunningServiceInfo runningServiceInfo : services) {
            if (runningServiceInfo.service.getClassName().equals(serviceClassName)){
                return true;
            }
        }
        return false;
     }
}

67
2018-02-12 04:42



Komplemen kecil adalah:

Tujuan saya adalah untuk mengetahui apakah suatu layanan berjalan tanpa benar-benar menjalankannya jika tidak berjalan.

Memanggil bindService atau memanggil maksud yang dapat ditangkap oleh layanan bukanlah ide yang bagus, karena layanan akan dimulai jika tidak berjalan.

Jadi, seperti yang disarankan miracle2k, yang terbaik adalah memiliki bidang statis di kelas layanan untuk mengetahui apakah layanan telah dimulai atau tidak.

Untuk membuatnya lebih bersih, saya sarankan untuk mengubah layanan di tunggal dengan sangat sangat malas mengambil: yaitu, tidak ada Instansiasi di semua tunggal contoh melalui metode statis. Metode getInstance statis layanan Anda / singleton hanya mengembalikan contoh tunggal jika telah dibuat. Tapi itu tidak benar-benar memulai atau melembagakan orang itu sendiri. Layanan ini hanya dimulai melalui metode awal layanan normal.

Kemudian akan lebih bersih untuk memodifikasi pola desain tunggal untuk mengubah nama metode getInstance yang membingungkan menjadi sesuatu seperti isInstanceCreated() : boolean metode.

Kode akan terlihat seperti:

public class MyService extends Service
{
   private static MyService instance = null;

   public static boolean isInstanceCreated() {
      return instance != null;
   }//met

   @Override
   public void onCreate()
   {
      instance = this;
      ....
   }//met

   @Override
   public void onDestroy()
   {
      instance = null;
      ...
   }//met
}//class

Solusi ini elegan, tetapi ini hanya relevan jika Anda memiliki akses ke kelas layanan dan hanya untuk kelas yang merupakan aplikasi / paket layanan. Jika kelas Anda berada di luar aplikasi / paket layanan, Anda dapat menanyakan ActivityManager dengan batasan yang digarisbawahi oleh Pieter-Jan Van Robays.


51
2018-05-20 10:58



Anda dapat menggunakan ini (saya belum mencoba ini, tapi saya harap ini berfungsi):

if(startService(someIntent) != null) {
    Toast.makeText(getBaseContext(), "Service is already running", Toast.LENGTH_SHORT).show();
}
else {
    Toast.makeText(getBaseContext(), "There is no service running, starting service..", Toast.LENGTH_SHORT).show();
}

Metode startService mengembalikan objek ComponentName jika sudah ada layanan yang berjalan. Jika tidak, null akan dikembalikan.

Lihat abstrak publik ComponentName startService (layanan Intent).

Ini tidak seperti memeriksa saya pikir, karena ini memulai layanan, jadi Anda dapat menambahkan stopService(someIntent); di bawah kode.


22
2017-09-23 17:01



    public boolean checkServiceRunning(){
         ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) 
                {
                    if ("com.example.yourpackagename.YourServiceName"
                            .equals(service.service.getClassName())) 
                    {
                        return true;
                    }
                }
             return false;
    }

13
2017-07-14 03:23



Saya telah sedikit memodifikasi salah satu solusi yang disajikan di atas, tetapi meneruskan kelas alih-alih nama string generik, untuk memastikan membandingkan string yang keluar dari metode yang sama class.getName()

public class ServiceTools {
    private static String LOG_TAG = ServiceTools.class.getName();

    public static boolean isServiceRunning(Context context,Class<?> serviceClass){
        final ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
        final List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);

        for (RunningServiceInfo runningServiceInfo : services) {
            Log.d(Constants.TAG, String.format("Service:%s", runningServiceInfo.service.getClassName()));
            if (runningServiceInfo.service.getClassName().equals(serviceClass.getName())){
                return true;
            }
        }
        return false;
    }
}

lalu

Boolean isServiceRunning = ServiceTools.isServiceRunning(
                    MainActivity.this.getApplicationContext(),
                    BackgroundIntentService.class);

11
2017-07-13 14:26



Saya hanya ingin menambahkan catatan untuk jawaban oleh @Snicolas. Langkah-langkah berikut dapat digunakan untuk memeriksa layanan berhenti dengan / tanpa panggilan onDestroy().

  1. onDestroy() disebut: Buka Pengaturan -> Aplikasi -> Layanan Lari -> Pilih dan hentikan layanan Anda.

  2. onDestroy() Tidak Dipanggil: Buka Pengaturan -> Aplikasi -> Kelola Aplikasi -> Pilih dan "Paksa Berhenti" aplikasi Anda di mana layanan Anda berjalan. Namun, karena aplikasi Anda dihentikan di sini, jadi pasti contoh layanan juga akan dihentikan.

Akhirnya, saya ingin menyebutkan bahwa pendekatan yang disebutkan di sana menggunakan variabel statis di kelas tunggal bekerja untuk saya.


7
2017-09-16 16:54