utilisation simple bind avec Don't create auto - voir ps. et mettre à jour ...
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);
exemple :
Intent bindIntent = new Intent(context, Class<Service>);
boolean bindResult = context.bindService(bindIntent, ServiceConnection, 0);
pourquoi ne pas utiliser? getRunningServices ()
List<ActivityManager.RunningServiceInfo> getRunningServices (int maxNum)
Return a list of the services that are currently running.
Remarque: cette méthode est uniquement destinée au débogage ou à la mise en œuvre d'interfaces utilisateur de type gestion de service.
ps. la documentation Android est trompeuse j'ai ouvert un problème sur google tracker pour éliminer les doutes:
https://issuetracker.google.com/issues/68908332
comme nous pouvons le voir, le service de liaison appelle réellement une transaction via le classeur ActivityManager via les liants de cache de service - je vérifie quel service est responsable de la liaison, mais comme nous pouvons le voir, le résultat de la liaison est:
int res = ActivityManagerNative.getDefault().bindService(...);
return res != 0;
la transaction se fait via un classeur:
ServiceManager.getService("activity");
suivant:
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
cela est défini dans ActivityThread via:
public final void bindApplication(...) {
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
ceci est appelé dans ActivityManagerService dans la méthode:
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
...
thread.bindApplication(... , getCommonServicesLocked(),...)
puis:
private HashMap<String, IBinder> getCommonServicesLocked() {
mais il n'y a pas de "fenêtre" d'activité et d'alarme seulement.
nous devons donc revenir pour appeler:
return getIServiceManager().getService(name);
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
cela fait appel à travers:
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
qui conduit à :
BinderInternal.getContextObject()
et c'est une méthode native ....
/**
* 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();
je n'ai pas le temps maintenant de creuser en c donc jusqu'à ce que je dissèque l'appel reste je suspends ma réponse.
mais le meilleur moyen de vérifier si le service est en cours d'exécution est de créer une liaison (si la liaison n'est pas créée, le service n'existe pas) - et d'interroger le service sur son état via la liaison (en utilisant un indicateur interne stocké sur son état).
mise à jour 23.06.2018
j'ai trouvé ceux intéressants:
/**
* 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;
}
en bref :)
"Fournir un classeur à un service déjà lié. Cette méthode est synchrone et ne démarre pas le service cible s'il n'est pas présent."
public IBinder peekService (service Intent, StringolvedType, String callingPackage) lève 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;
}
*