привязка простого использования без автоматического создания - см. Пс. и обновить ...
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);
пример:
Intent bindIntent = new Intent(context, Class<Service>);
boolean bindResult = context.bindService(bindIntent, ServiceConnection, 0);
почему бы не использовать? getRunningServices ()
List<ActivityManager.RunningServiceInfo> getRunningServices (int maxNum)
Return a list of the services that are currently running.
Примечание: этот метод предназначен только для отладки или реализации пользовательских интерфейсов типа управления услугами.
пс. Документация Android вводит в заблуждение. Я открыл проблему на трекере Google, чтобы устранить любые сомнения:
https://issuetracker.google.com/issues/68908332
как мы видим, служба связывания фактически вызывает транзакцию через привязку ActivityManager через привязки кеша службы - я отслеживаю, какая служба отвечает за привязку, но, как мы видим, результат для привязки:
int res = ActivityManagerNative.getDefault().bindService(...);
return res != 0;
транзакция совершается через связыватель:
ServiceManager.getService("activity");
следующая:
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
это устанавливается в ActivityThread через:
public final void bindApplication(...) {
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
это вызывается в ActivityManagerService в методе:
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
...
thread.bindApplication(... , getCommonServicesLocked(),...)
затем:
private HashMap<String, IBinder> getCommonServicesLocked() {
но нет "активности", только пакет окон и будильник ..
поэтому нам нужно вернуться к звонку:
return getIServiceManager().getService(name);
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
это делает вызов через:
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
, что приводит к:
BinderInternal.getContextObject()
и это нативный метод ....
/**
* 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();
У меня сейчас нет времени копаться в c, поэтому, пока я не проанализирую перерыв, я приостановлю свой ответ.
но лучший способ проверить, работает ли служба , - создать привязку (если привязка не создана, служба не существует) - и запросить службу о ее состоянии через привязку (используя сохраненный внутренний флаг на ней) состояние).
обновление 23.06.2018
Я нашел эти интересные:
/**
* 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;
}
короче :)
"Предоставить связыватель для уже связанной службы. Этот метод является синхронным и не запускает целевую службу, если она отсутствует."
public IBinder peekService (Служба намерений, String resolvedType,
Строка callPackage) выдает 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;
}
*