Vra

Hoe kyk ek of 'n agtergronddiens loop?

Ek wil 'n Android-aktiwiteit hê wat die toestand van die diens verander - dit laat my dit aanskakel as dit af en af ​​is as dit aan is.

Was dit nuttig?

Oplossing

Ek het nie lank gelede dieselfde probleem gehad nie.Aangesien my diens plaaslik was, het ek uiteindelik bloot 'n statiese veld in die diensklas gebruik om toestand te wissel, soos beskryf deur hackbod hier

EDIT (vir die rekord):

Hier is die oplossing wat deur hackbod voorgestel word:

As u kliënt- en bedienerkode deel is van dieselfde .apk en u bind aan die diens met 'n konkrete opset (een wat die presiese diensklas spesifiseer), kan u eenvoudig 'n wêreldwye veranderlike stel wanneer dit bestuur U kliënt kan kyk.

Ons het doelbewus nie 'n API om na te gaan of 'n diens aan die gang is nie, want as u iets wil doen, eindig u met die renomstandighede in u kode.

Ander wenke

Ek gebruik die volgende van binne 'n aktiwiteit:

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

En ek noem dit gebruik:

isMyServiceRunning(MyService.class)

Dit werk betroubaar, want dit is gebaseer op die inligting oor die bestuur van dienste wat deur die Android-bedryfstelsel verskaf word Aktiwiteitbestuurder#getRunningServices.

Al die benaderings wat onDestroy of onSometing-gebeurtenisse of Binders of statiese veranderlikes gebruik, sal nie betroubaar werk nie, want as 'n ontwikkelaar weet jy nooit wanneer Android besluit om jou proses dood te maak of watter van die genoemde terugbelopings genoem word of nie.Let asseblief op die "doodmaakbare" kolom in die lewensiklusgebeurtenisse tabel in die Android-dokumentasie.

Het dit!

Jy MOET bel startService() vir jou diens om behoorlik geregistreer te wees en slaag BIND_AUTO_CREATE sal nie voldoende wees nie.

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

En nou die ServiceTools-klas:

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

'n Klein aanvulling is:

My doel is om te weet of 'n diens loop sonder om dit werklik te laat loop as dit nie loop nie.

Om bindService te bel of 'n voorneme te bel wat deur die diens gevang kan word, is nie 'n goeie idee nie, aangesien dit die diens sal begin as dit nie loop nie.

Dus, soos miracle2k voorgestel het, is die beste om 'n statiese veld in die diensklas te hê om te weet of die diens begin is of nie.

Om dit nog skoner te maak, stel ek voor om die diens in 'n enkelton te verander met 'n baie baie lui haal:dit wil sê, daar is geen instansiasie van die enkeling byvoorbeeld deur statiese metodes.Die statiese getInstance-metode van jou diens/singleton gee net die instansie van die singleton terug as dit geskep is.Maar dit begin of instansieer nie die singleton self nie.Die diens word slegs deur normale diensbeginmetodes begin.

Dit sal dan selfs skoner wees om die enkelton-ontwerppatroon te verander om die verwarrende getInstance-metode te hernoem na iets soos die isInstanceCreated() : boolean metode.

Die kode sal soos volg lyk:

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

Hierdie oplossing is elegant, maar dit is slegs relevant as jy toegang het tot die diensklas en slegs vir klasse buite die toepassing/pakket van die diens.As jou klasse buite die dienstoepassing/pakket is, kan jy navraag doen by die Aktiwiteitsbestuurder met beperkings wat deur Pieter-Jan Van Robays onderstreep is.

Jy kan dit gebruik (ek het dit nog nie probeer nie, maar ek hoop dit werk):

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

Die startService-metode gee 'n ComponentName-objek terug as daar 'n diens is wat reeds loop.Indien nie, sal nul teruggestuur word.

Sien publieke abstrakte ComponentName startService (Bedoelingsdiens).

Dit is nie soos om te kyk nie, dink ek, want dit begin die diens, sodat jy kan byvoeg stopService(someIntent); onder die kode.

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

Ek het een van die oplossings wat hierbo aangebied word effens gewysig, maar die klas in plaas van 'n generiese stringnaam geslaag om seker te maak dat ek stringe wat uit dieselfde metode kom vergelyk 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;
    }
}

en toe

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

'n Uittreksel uit Android dokumente:

Soos stuur Uitsaai (voorneme), maar as daar ontvangers is vir die opset, sal hierdie funksie dit blokkeer en onmiddellik versend voordat hulle terugkeer.

Dink aan hierdie hack as "pinging" die Service aangesien ons sinchronies kan uitsaai, kan ons uitsaai en 'n resultaat kry -- sinchronies -- op die UI-draad.

Service

@Override
public void onCreate() {
   LocalBroadcastManager
     .getInstance(this)
     .registerReceiver(new ServiceEchoReceiver(), new IntentFilter("ping"));
}

private class ServiceEchoReceiver extends BroadcastReceiver {
    public void onReceive (Context context, Intent intent) {
      LocalBroadcastManager
         .getInstance(this)
         .sendBroadcastSync(new Intent("pong"));
    }
}

Activity

    bool serviceRunning = false;

    protected void onCreate (Bundle savedInstanceState){
        LocalBroadcastManager.getInstance(this).registerReceiver(pong, new IntentFilter("pong"));
        LocalBroadcastManager.getInstance(this).sendBroadcastSync(new Intent("ping"));
        if(!serviceRunning){
           //run the service
        }
    }

    private BroadcastReceiver pong = new BroadcastReceiver(){
        public void onReceive (Context context, Intent intent) {
          serviceRunning = true;   
        }
    }

Ek wil net 'n nota by die antwoord deur @Snicolas voeg.Die volgende stappe kan gebruik word om stopdiens te kontroleer met/sonder om te bel onDestroy().

  1. onDestroy() genoem:Gaan na Instellings -> Toepassing -> Loop dienste -> Kies en stop jou diens.

  2. onDestroy() nie genoem nie:Gaan na Instellings -> Toepassing -> Bestuur toepassings -> Kies en "Forseer stop" jou toepassing waarin jou diens loop.Aangesien u aansoek egter hier gestop word, sal die diensgevalle beslis ook gestop word.

Ten slotte wil ek noem dat die benadering wat daar genoem word met behulp van 'n statiese veranderlike in enkeltonklas vir my werk.

onDestroy word nie altyd in die diens geroep nie, so dit is nutteloos!

Byvoorbeeld:Begin net die toepassing weer met een verandering vanaf Eclipse.Die toepassing word kragtig verlaat met behulp van SIG:9.

Die regte manier om te kyk of 'n diens loop, is om dit eenvoudig te vra.Implementeer 'n uitsaai-ontvanger in jou diens wat reageer op pings van jou aktiwiteite.Registreer die uitsaaiontvanger wanneer die diens begin, en deregistreer dit wanneer die diens vernietig word.Van jou aktiwiteit (of enige komponent), stuur 'n plaaslike uitsending bedoeling vir die diens en as dit reageer, weet jy dat dit aan die gang is.Let op die subtiele verskil tussen ACTION_PING en ACTION_PONG in die kode hieronder.

public class PingableService extends Service
{
    public static final String ACTION_PING = PingableService.class.getName() + ".PING";
    public static final String ACTION_PONG = PingableService.class.getName() + ".PONG";

    public int onStartCommand (Intent intent, int flags, int startId)
    {
        LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, new IntentFilter(ACTION_PING));
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy ()
    {
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
        super.onDestroy();
    }

    private BroadcastReceiver mReceiver = new BroadcastReceiver()
    {
        @Override
        public void onReceive (Context context, Intent intent)
        {
            if (intent.getAction().equals(ACTION_PING))
            {
                LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getApplicationContext());
                manager.sendBroadcast(new Intent(ACTION_PONG));
            }
        }
    };
}


public class MyActivity extends Activity
{
    private boolean isSvcRunning = false;

    @Override
    protected void onStart()
    {
        LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getApplicationContext());
        manager.registerReceiver(mReceiver, new IntentFilter(PingableService.ACTION_PONG));
        // the service will respond to this broadcast only if it's running
        manager.sendBroadcast(new Intent(PingableService.ACTION_PING));
        super.onStart();
    }

    @Override
    protected void onStop()
    {
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
        super.onStop();
    }

    protected BroadcastReceiver mReceiver = new BroadcastReceiver()
    {
        @Override
        public void onReceive (Context context, Intent intent)
        {
            // here you receive the response from the service
            if (intent.getAction().equals(PingableService.ACTION_PONG))
            {
                isSvcRunning = true;
            }
        }
    };
}

Eerstens moet jy nie probeer om die diens te bereik deur die ActivityManager te gebruik nie.(Bespreek hier)

Dienste kan op hul eie loop, gebonde wees aan 'n aktiwiteit of albei.Die manier om 'n aktiwiteit in te check of jou Diens loop of nie, is deur 'n koppelvlak (wat Binder uitbrei) te maak waar jy metodes verklaar wat beide, die Aktiwiteit en die Diens, verstaan.Jy kan dit doen deur jou eie Interface te maak waar jy byvoorbeeld "isServiceRunning()" verklaar.Jy kan dan jou aktiwiteit aan jou diens bind, die metode isServiceRunning() laat loop, die diens sal self kyk of dit loop of nie en gee 'n boolean terug na jou aktiwiteit.

U kan ook hierdie metode gebruik om u Diens te stop of op 'n ander manier daarmee te kommunikeer.

Ek het dit gebruik tutoriaal om te leer hoe om hierdie scenario in my aansoek te implementeer.

Xamarin C# weergawe:

private bool isMyServiceRunning(System.Type cls)
{
    ActivityManager manager = (ActivityManager)GetSystemService(Context.ActivityService);

    foreach (var service in manager.GetRunningServices(int.MaxValue)) {
        if (service.Service.ClassName.Equals(Java.Lang.Class.FromType(cls).CanonicalName)) {
            return true;
        }
    }
    return false;
}

Vir die gebruiksgeval wat hier gegee word, kan ons eenvoudig gebruik maak van die stopService() metode se terugkeerwaarde.Dit keer terug true as daar die gespesifiseerde diens bestaan ​​en dit word doodgemaak.Anders keer dit terug false.U kan dus die diens herbegin as die resultaat is false anders is dit verseker dat die huidige diens gestaak is.:) Dit sal beter wees as jy 'n blik op hierdie.

Weereens, nog 'n alternatief wat mense skoner kan vind as hulle hangende voornemens gebruik (byvoorbeeld met die AlarmManager:

public static boolean isRunning(Class<? extends Service> serviceClass) {
    final Intent intent = new Intent(context, serviceClass);
    return (PendingIntent.getService(context, CODE, intent, PendingIntent.FLAG_NO_CREATE) != null);
}

Waar CODE is 'n konstante wat jy privaat in jou klas definieer om die hangende bedoelings wat met jou diens verband hou, te identifiseer.

Hieronder is 'n elegante hack wat al die dek Ifs.Dit is slegs vir plaaslike dienste.

    public final class AService extends Service {

        private static AService mInstance = null;

        public static boolean isServiceCreated() {
            try {
                // If instance was not cleared but the service was destroyed an Exception will be thrown
                return mInstance != null && mInstance.ping();
            } catch (NullPointerException e) {
                // destroyed/not-started
                return false;
            }
        }

        /**
         * Simply returns true. If the service is still active, this method will be accessible.
         * @return
         */
        private boolean ping() {
            return true;
        }

        @Override
        public void onCreate() {
            mInstance = this;
        }

        @Override
        public void onDestroy() {
            mInstance = null;
        }
    }

En dan later:

    if(AService.isServiceCreated()){
        ...
    }else{
        startService(...);
    }

Die reaksie van geekQ maar in Kotlin-klas.Dankie geekQ

fun isMyServiceRunning(serviceClass : Class<*> ) : Boolean{
    var manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.name.equals(service.service.className)) {
            return true
        }
    }
    return false
}

Die oproep

isMyServiceRunning(NewService::class.java)

Daar kan verskeie dienste met dieselfde klasnaam wees.

Ek het sopas twee toepassings geskep.Die pakketnaam van die eerste toepassing is com.example.mock.Ek het 'n subpakket genaamd lorem in die toepassing en 'n diens genoem Mock2Service.So sy ten volle gekwalifiseerde naam is com.example.mock.lorem.Mock2Service.

Toe het ek die tweede toepassing geskep en 'n diens genoem Mock2Service.Die pakketnaam van die tweede toepassing is com.example.mock.lorem.Die volledig gekwalifiseerde naam van die diens is com.example.mock.lorem.Mock2Service, ook.

Hier is my logcat-uitset.

03-27 12:02:19.985: D/TAG(32155): Mock-01: com.example.mock.lorem.Mock2Service
03-27 12:02:33.755: D/TAG(32277): Mock-02: com.example.mock.lorem.Mock2Service

'n Beter idee is om te vergelyk ComponentName gevalle omdat equals() van ComponentName vergelyk beide pakketname en klasname.En daar kan nie twee toepassings met dieselfde pakketnaam op 'n toestel geïnstalleer wees nie.

Die gelyk () metode van ComponentName.

@Override
public boolean equals(Object obj) {
    try {
        if (obj != null) {
            ComponentName other = (ComponentName)obj;
            // Note: no null checks, because mPackage and mClass can
            // never be null.
            return mPackage.equals(other.mPackage)
                    && mClass.equals(other.mClass);
        }
    } catch (ClassCastException e) {
    }
    return false;
}

Komponent Naam

Dit is meer van toepassing op Intent Service-ontfouting, aangesien dit 'n draad skep, maar kan ook vir gereelde dienste werk.Ek het hierdie draad gevind danksy Binging

In my geval het ek met die debugger rondgespeel en die draadaansig gevind.Dit lyk soos die kolpunt-ikoon in MS Word.In elk geval, jy hoef nie in debugger-modus te wees om dit te gebruik nie.Klik op die proses en klik op daardie knoppie.Enige voornemedienste sal verskyn terwyl hulle loop, ten minste op die emulator.

As die diens aan 'n ander proses of APK behoort, gebruik die oplossing gebaseer op die ActivityManager.

As jy toegang tot sy bron het, gebruik net die oplossing gebaseer op 'n statiese veld.Maar in plaas daarvan om 'n boolean te gebruik, sou ek voorstel om 'n Date-voorwerp te gebruik.Terwyl die diens aan die gang is, werk net die waarde daarvan op na 'nou' en stel dit op nul wanneer dit klaar is.Van die aktiwiteit kan jy kyk of sy nul is of die datum te oud is, wat sal beteken dat dit nie loop nie.

Jy kan ook uitsaaikennisgewing vanaf jou diens stuur wat aandui dat dit saam met verdere inligting soos vordering loop.

Binne TheServiceClass definieer:

 public static Boolean serviceRunning = false;

Dan in onStartCommand(...)

 public int onStartCommand(Intent intent, int flags, int startId) {

    serviceRunning = true;
    ...
}

 @Override
public void onDestroy()
{
    serviceRunning = false;

} 

Dan, bel if(TheServiceClass.serviceRunning == true) uit enige klas.

eenvoudige gebruik bind met moenie outomaties skep nie - kyk ps.en werk op...

public abstract class Context {

 ... 

  /*
  * @return {true} If you have successfully bound to the service, 
  *  {false} is returned if the connection is not made 
  *  so you will not receive the service object.
  */
  public abstract boolean bindService(@RequiresPermission Intent service,
        @NonNull ServiceConnection conn, @BindServiceFlags int flags);

voorbeeld:

    Intent bindIntent = new Intent(context, Class<Service>);
    boolean bindResult = context.bindService(bindIntent, ServiceConnection, 0);

hoekom nie gebruik nie? getRunningServices()

List<ActivityManager.RunningServiceInfo> getRunningServices (int maxNum)
Return a list of the services that are currently running.

Let wel:hierdie metode is slegs bedoel vir die ontfouting of implementering van diensbestuurtipe gebruikerskoppelvlakke.


ps.Android-dokumentasie is misleidend, ek het 'n probleem op Google Tracker oopgemaak om enige twyfel uit te skakel:

https://issuetracker.google.com/issues/68908332

soos ons kan sien, roep bind diens eintlik 'n transaksie aan via ActivityManager binder deur Service cache binders - ek kan nie dop watter diens verantwoordelik is vir binding nie, maar soos ons kan sien is die resultaat vir bind:

int res = ActivityManagerNative.getDefault().bindService(...);
return res != 0;

transaksie geskied deur middel van bindmiddel:

ServiceManager.getService("activity");

volgende:

  public static IBinder getService(String name) {
    try {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return getIServiceManager().getService(name);

dit word in ActivityThread gestel via:

 public final void bindApplication(...) {

        if (services != null) {
            // Setup the service cache in the ServiceManager
            ServiceManager.initServiceCache(services);
        }

dit word genoem in ActivityManagerService in metode:

 private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
    ...
    thread.bindApplication(... , getCommonServicesLocked(),...)

dan:

 private HashMap<String, IBinder> getCommonServicesLocked() {

maar daar is geen "aktiwiteit" net venster pakket en alarm..

so ons moet terugkom om te bel:

 return getIServiceManager().getService(name);

    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());

dit maak oproep deur:

    mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);

wat lei tot:

BinderInternal.getContextObject()

en dit is inheemse metode ....

  /**
     * Return the global "context object" of the system.  This is usually
     * an implementation of IServiceManager, which you can use to find
     * other services.
     */
    public static final native IBinder getContextObject();

ek het nie nou tyd om in te grawe nie so totdat ek rusoproep dissekteer skort ek my antwoord op.

maar die beste manier om te kyk of diens loop is om bind te skep (as bind nie geskep is nie bestaan ​​nie diens nie) - en navraag oor die diens oor sy toestand deur die bind (met behulp van gestoorde interne vlag op dit staat).

Opdateer 23.06.2018

Ek het dit interessant gevind:

/**
 * Provide a binder to an already-bound service.  This method is synchronous
 * and will not start the target service if it is not present, so it is safe
 * to call from {@link #onReceive}.
 *
 * For peekService() to return a non null {@link android.os.IBinder} interface
 * the service must have published it before. In other words some component
 * must have called {@link android.content.Context#bindService(Intent, ServiceConnection, int)} on it.
 *
 * @param myContext The Context that had been passed to {@link #onReceive(Context, Intent)}
 * @param service Identifies the already-bound service you wish to use. See
 * {@link android.content.Context#bindService(Intent, ServiceConnection, int)}
 * for more information.
 */
public IBinder peekService(Context myContext, Intent service) {
    IActivityManager am = ActivityManager.getService();
    IBinder binder = null;
    try {
        service.prepareToLeaveProcess(myContext);
        binder = am.peekService(service, service.resolveTypeIfNeeded(
                myContext.getContentResolver()), myContext.getOpPackageName());
    } catch (RemoteException e) {
    }
    return binder;
}

in kort :)

"Verskaf 'n bindmiddel vir 'n reeds gebonde diens.Hierdie metode is sinchronies en sal nie die teikendiens begin as dit nie teenwoordig is nie."

openbare Ibinder PeekService (Intent Service, String ResoledType, String CallingPackage) gooi RemoteException;

*

public static IBinder peekService(IBinder remote, Intent service, String resolvedType)
             throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken("android.app.IActivityManager");
    service.writeToParcel(data, 0);
    data.writeString(resolvedType);
    remote.transact(android.os.IBinder.FIRST_CALL_TRANSACTION+84, data, reply, 0);
    reply.readException();
    IBinder binder = reply.readStrongBinder();
    reply.recycle();
    data.recycle();
    return binder;
}

*

In jou Dienssubklas Gebruik 'n Statiese Boolean om die toestand van die Diens te kry soos hieronder gedemonstreer.

MyService.kt

class MyService : Service() {
    override fun onCreate() {
        super.onCreate()
        isServiceStarted = true
    }
    override fun onDestroy() {
        super.onDestroy()
        isServiceStarted = false
    }
    companion object {
        var isServiceStarted = false
    }
}

MainActivity.kt

class MainActivity : AppCompatActivity(){
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val serviceStarted = FileObserverService.isServiceStarted
        if (!serviceStarted) {
            val startFileObserverService = Intent(this, FileObserverService::class.java)
            ContextCompat.startForegroundService(this, startFileObserverService)
        }
    }
}

My kotlin omskakeling van die ActivityManager::getRunningServices gebaseerde antwoorde.Plaas hierdie funksie in 'n aktiwiteit-

private fun isMyServiceRunning(serviceClass: Class<out Service>) =
    (getSystemService(ACTIVITY_SERVICE) as ActivityManager)
        .getRunningServices(Int.MAX_VALUE)
        ?.map { it.service.className }
        ?.contains(serviceClass.name) ?: false

Gebruik asseblief hierdie kode.

if (isMyServiceRunning(MainActivity.this, xyzService.class)) { // Service class name
    // Service running
} else {
    // Service Stop
}


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

Vat dit rustig ouens...:)

Ek dink die mees geskikte oplossing is om 'n sleutel-waarde-paar in te hou SharedPreferences oor of die diens loop of nie.

Logika is baie reguit;by enige verlangde posisie in jou diensklas;plaas 'n Boolese waarde wat as 'n vlag vir jou sal dien oor of die diens loop of nie.Lees dan hierdie waarde waar jy wil in jou aansoek.

'n Voorbeeldkode wat ek in my toepassing gebruik, is hieronder:

In my diensklas ('n diens vir oudiostroom) voer ek die volgende kode uit wanneer die diens op is;

private void updatePlayerStatus(boolean isRadioPlaying)
{
        SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.str_shared_file_name), Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPref.edit();
        editor.putBoolean(getString(R.string.str_shared_file_radio_status_key), isRadioPlaying);
        editor.commit();
}

Dan, in enige aktiwiteit van my aansoek, gaan ek die status van die diens na met behulp van die volgende kode;

private boolean isRadioRunning() {
        SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.str_shared_file_name), Context.MODE_PRIVATE);

        return sharedPref.getBoolean(getString(R.string.str_shared_file_radio_status_key), false);
}

Geen spesiale toestemmings, geen lusse ...Maklike manier, skoon oplossing :)

As jy ekstra inligting benodig, verwys asseblief na die skakel

Hoop dit help.

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top