einfache Verwendung binden mit nicht automatisch erstellen - siehe ps. und aktualisieren ...
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);
Beispiel:
Intent bindIntent = new Intent(context, Class<Service>);
boolean bindResult = context.bindService(bindIntent, ServiceConnection, 0);
warum nicht verwenden? getRunningServices ()
List<ActivityManager.RunningServiceInfo> getRunningServices (int maxNum)
Return a list of the services that are currently running.
Hinweis: Diese Methode ist nur zum Debuggen oder Implementieren von Benutzeroberflächen vom Typ Service Management vorgesehen.
ps. Android-Dokumentation ist irreführend Ich habe ein Problem auf Google Tracker geöffnet, um alle Zweifel zu beseitigen:
https://issuetracker.google.com/issues/68908332
Wie wir sehen können, ruft der Bindedienst tatsächlich eine Transaktion über den ActivityManager-Ordner über die Service-Cache-Ordner auf. Ich verfolge nicht, welcher Dienst für die Bindung verantwortlich ist, aber wie wir sehen können, lautet das Ergebnis für die Bindung:
int res = ActivityManagerNative.getDefault().bindService(...);
return res != 0;
Transaktion erfolgt über Ordner:
ServiceManager.getService("activity");
Nächster:
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
Dies wird in ActivityThread festgelegt über:
public final void bindApplication(...) {
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
Dies wird in ActivityManagerService in der Methode aufgerufen:
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
...
thread.bindApplication(... , getCommonServicesLocked(),...)
dann:
private HashMap<String, IBinder> getCommonServicesLocked() {
aber es gibt keine "Aktivität" nur Fensterpaket und Alarm ..
Also müssen wir zurückrufen, um anzurufen:
return getIServiceManager().getService(name);
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
Dies macht Anruf durch:
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
was dazu führt :
BinderInternal.getContextObject()
und das ist native Methode ....
/**
* 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();
Ich habe jetzt keine Zeit, mich in c zu vertiefen. Bis ich den Restanruf seziere, setze ich meine Antwort aus.
Der beste Weg, um zu überprüfen, ob der Dienst ausgeführt wird, besteht darin, eine Bindung zu erstellen (wenn die Bindung nicht erstellt wurde, existiert kein Dienst) - und den Dienst über die Bindung nach seinem Status abzufragen (unter Verwendung des gespeicherten internen Flags für den Status).
Update 23.06.2018
Ich fand die interessant:
/**
* 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;
}
Zusamenfassend :)
"Stellen Sie einen Ordner für einen bereits gebundenen Dienst bereit. Diese Methode ist synchron und startet den Zieldienst nicht, wenn er nicht vorhanden ist."
public IBinder peekService (Intent Service, String ResolutionedType, String Calling Package) löst eine RemoteException aus.
* *
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;
}
* *