Получение уведомлений, когда клиенты подключаются и отключаются от службы Android - PullRequest
3 голосов
/ 27 октября 2011

У меня есть служба Android, которая экспортирует интерфейс RPC через AIDL. Интерфейс ориентирован на соединение, где клиент подключается к нему, проводит с ним операции, а затем отключается при выходе.

К сожалению, клиент ненормально завершает работу, например, система будет убита, у нее никогда не будет возможности сообщить интерфейсу RPC, что соединение закрыто. Это вызывает проблемы.

Есть ли возможность для службы автоматически получать уведомления, когда новый клиент подключается и отключается от интерфейса? Я нашел onBind() и onUnbind(), но это не одно и то же; они говорят мне, используется ли интерфейс или нет. onUnbind() вызывается только когда последний клиент отсоединяется.

Есть идеи? (А дизайн сервиса контролируется внешними требованиями и не может быть изменен ...)

Обновление: Я совершенно забыл упомянуть, что смотрел на linkToDeath(), который почти делает именно то, что я хочу, но кажется, что он работает наоборот --- это позволяет клиенту получать уведомления, когда Служба умирает. Когда я попробовал, ничего не произошло. Документация немного неоднородна; Кто-нибудь знает наверняка, работает ли это так, как я хочу? И если так, как заставить его сказать мне , какой клиент умер?

Обновление обновления: Я решил эту проблему, но только путем обмана. Я переопределил это. Мое приложение на самом деле написано в основном на C с использованием NDK, отсюда и странный дизайн сервиса; Итак, я перенес проблему в мир C и создал крошечный вспомогательный процесс, который напрямую взаимодействует с нативными частями моего приложения, используя доменные сокеты Unix. Это быстро, очень мало и почти пуленепробиваемо - но все равно обманывает. Поэтому, хотя моя проблема теперь решена, я все же хотел бы знать, каков на самом деле ответ.

Ответы [ 2 ]

2 голосов
/ 15 июля 2016

Используйте linkToDeath() (но делайте это наоборот), инициализируя новый объект Binder на стороне клиента и отправляя его через AIDL в службу.
Затем вы можете зарегистрироваться на вашего клиента.DeathRecipient внутри вашего сервиса и получает уведомление от фреймворка о ненормальном выходе из процесса клиента.

Пример кода -

Внутри вашего .AIDL file - Создать метод для передачи объекта Binder от клиента в службу

void registerProcessDeath(in IBinder clientDeathListener);

На стороне клиента - Инициализироватьновый объект и передать его вашему сервису через интерфейс AIDL.

public void onServiceConnected(ComponentName className, IBinder service) {
    mIMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
    //Call the registerProcessDeath method from the AIDL file and pass 
    //the new Binder object
    mIMyAidlInterface.registerProcessDeath(new Binder());
}

на стороне сервиса - получить клиенту Binder и зарегистрироваться на его linkToDeath().

private IBinder mBinder; //Instance variable

private final IMyAidlInterface.Stub mStub = new IMyAidlInterface.Stub() {

    @Override
    public void registerProcessDeath(IBinder clientDeathListener) {
        mBinder = clientDeathListener;
        //Create new anonymous class of IBinder.DeathRecipient()
        clientDeathListener.linkToDeath(new IBinder.DeathRecipient() {
               @Override
               public void binderDied() {
               //Do your stuff when process exits abnormally here.
               //Unregister from client death recipient
               mBinder.unlinkToDeath(this,0);
               }
        },0);
    }
};

Дополнительное чтение - Этот механизм очень распространен внутри фреймворка для предотвращения утечек памяти при смерти процессов - Очень хороший урок Алекса Локвуда по теме здесь .

2 голосов
/ 28 октября 2011

Может быть linkToDeath () может помочь здесь.

...