AIDL — вызов BindService для динамического намерения возвращает null Binder

У меня есть набор приложений, которые я создал. Одно из этих приложений — это Activity, которое по сути является «домашним экраном», а все остальные приложения содержат набор сервисов, которые я создал.

В основном приложении Activity у меня есть ListView, который использует ArrayAdapter, который я использую для отображения списка имен классов и пакетов созданных мной пользовательских служб, установленных на телефоне. Каждая из показанных служб размещена в отдельном приложении, но все эти службы реализуют один и тот же простой интерфейс AIDL, который я создал.

interface IExService {
void execute(in Bundle parameters, in ICallback callback);
}

В основном приложении у меня есть связующее и служебное соединение, подобное этому:

private IExService _service=null;

private ServiceConnection _serviceConnection = new ServiceConnection() {
    public void onServiceConnected(ComponentName className, IBinder binder) {
        _service=IExService.Stub.asInterface(binder);
    }
    public void onServiceDisconnected(ComponentName className) {
        _service=null;
    }
};

Выбрав элемент в списке, я хотел бы выполнить привязку к выбранному сервису. Код для выбора элемента в списке выглядит следующим образом, где объект MyService представляет выбранный элемент службы:

private void executeService(MyService service) {

    boolean isBound = bindService(new Intent(service.getClassName()), _serviceConnection, Context.BIND_AUTO_CREATE);
_service.execute(params, callback);

В приведенном выше коде намерение будет сформировано из имени класса, содержащегося в выбранном элементе. Имя класса, например, может выглядеть как «com.example.exWidgetService.ExampleService». Эта служба будет определена в файле манифеста для этого приложения следующим образом:

    <service android:name="com.example.ExampleApplication.ExampleService">
        <intent-filter>
            <action android:name="com.test.HomeApplication.IExService"/>
        </intent-filter>
    </service>

Где ExampleApplication — это созданное мной приложение, в котором размещается служба, а HomeApplication — это приложение главного меню, в котором определяется фактический файл AIDL.

Вот моя проблема: при выполнении вызова BindService() вызов завершается успешно, и возвращается true, что служба была привязана. Однако объект _service всегда имеет значение NULL. Таким образом, даже если служба успешно связывается (или возвращается), я не могу выполнить какие-либо методы службы, потому что связыватель имеет значение null. DDMS, кажется, не показывает ничего полезного, и во время вызова BindService() не регистрируется никаких проблем.

Проблема в том, что у меня есть несколько приложений, реализующих один и тот же сервис AIDL? Если нет, есть ли правильный способ динамического вызова конкретной реализации службы во время выполнения?


person Patrick D    schedule 18.03.2011    source источник


Ответы (1)


Трудно сказать без полного кода и отладки ;), так что давайте шаг за шагом. Не могли бы вы проверить две вещи:

  • в методе onServiceConnected параметр связывания тоже имеет значение null или только _service имеет значение null? В случае, если связующее значение равно null:
  • в вашем сервисе вы можете переопределить метод onBind (не помню точное имя) и проверить, действительно ли вы получили запрос.
person Yuriy    schedule 18.03.2011
comment
Спасибо за ответ! onServiceConnected возвращает правильный параметр связывания, и _service устанавливается правильно. Это показало мне мою проблему: onServiceConnected — это обратный вызов. Когда я вызываю onBind, а затем НЕМЕДЛЕННО выполняю метод службы, обратный вызов еще не был вызван. Вот почему _service равен нулю. Похоже, что мое решение будет состоять в том, чтобы вставить какую-то задержку или что-то еще, чтобы гарантировать, что обратный вызов был достигнут и _service был правильно установлен, прежде чем делать какие-либо сервисные вызовы через него. Спасибо за помощь! - person Patrick D; 18.03.2011