Прив’язати службу до активності в Android


90

Я намагаюся написати простий медіаплеєр, який відтворює потокове аудіо за допомогою RTSP. У мене є графічний інтерфейс та служба, яка виконує відтворення. Моє питання полягає в тому, як найкраще спілкуватися між діяльністю та службою (наприклад, оновлення графічного інтерфейсу на основі стану програвача).

Я знаю, що можу прив’язати службу до діяльності за допомогою onBind (), але якщо я правильно розумію, це зупинить службу, якщо активність буде вбито. Я хочу продовжити відтворення, навіть якщо користувач виходить із дії. Чи існує якийсь стандартний або кращий спосіб вирішення цієї проблеми?

Відповіді:


154

"Якщо ви запустите службу android з startService(..)цією службою, вона буде працювати, поки ви явно не запустите її stopService(..). Є дві причини, через яку система може запускати службу. Якщо хтось зателефонує, Context.startService()система отримає службу (створивши її та викликаючи її onCreate()метод, якщо потрібно), а потім викликати його onStartCommand(Intent, int, int)метод з аргументами, наданими клієнтом. На цьому етапі служба буде продовжувати працювати до Context.stopService()або не stopSelf()буде викликана. Зверніть увагу, що кілька викликів, Context.startService()які не слід вкладати (хоча вони призводять до декількох відповідних викликів до onStartCommand()), тому ні незалежно від того, скільки разів він запускався, послуга буде зупинена один раз Context.stopService()або stopSelf()викликана; однак служби можуть використовувати їхstopSelf(int) метод, щоб гарантувати, що служба не зупиняється, доки оброблені наміри не будуть оброблені.

Клієнти також можуть використовувати Context.bindService()постійне з'єднання з послугою. Це також створює службу, якщо вона ще не запущена (дзвонить onCreate()при цьому), але не викликає onStartCommand(). Клієнт отримає IBinderоб'єкт, який служба повертає від свого onBind(Intent)методу, що дозволяє клієнтові здійснювати зворотні дзвінки до служби. Послуга буде продовжувати працювати доти, доки встановлено підключення (незалежно від того, чи зберігає клієнт посилання на Службу IBinder). Зазвичай IBinderповертається для складного інтерфейсу, який був написаний в AIDL.

Послугу можна як запустити, так і мати підключення до неї. У такому випадку система буде підтримувати роботу служби до тих пір, поки вона буде запущена або до неї є одне або кілька з'єднань із Context.BIND_AUTO_CREATEпрапором. Як тільки жодна з цих ситуацій не виконується, onDestroy()викликається метод Служби, і послуга фактично припиняється. Усі очищення (зупинка потоків, скасування реєстрації приймачів) повинні бути завершені після повернення з onDestroy()".


1
невелика плутанина: Чи правда, що якщо діяльність буде знищена, служба буде також знищена? Або ця послуга не знищується, лише якщо я впроваджую свій власний AIDL? Я запитую, тому що коли я використовую startService (зокрема, на IntentService), служба зупиняється, коли її робота виконується, на відміну від того, коли діяльність вмирає. Тож чи правда, що якщо діяльність помирає, то і служба, яка пов’язана (виключно), також помирає?
Katedral Pillon

1
якщо ви використовуєте простий сервер за допомогою виклику startService, тоді служба не зупиниться, доки ви не зателефонуєте stopSelf () або stopService (). І наступне, якщо ви використовуєте bindService, тоді послуга yes помре, якщо всі підключені компоненти / компоненти прив'язки знищаться.
Асіф Муштак,

1
@UnKnown Якщо служба запущена за допомогою startService (), то незалежно від того, прив'язуєте ви її або відв'язуєте, вона буде продовжувати працювати і може бути знищена лише викликом stopService () або stopSelf (). Отже, навіть якщо діяльність, яка була обмежена службою, буде знищена, служба не буде знищена.
CopsOnRoad

Чи можете ви допомогти мені у цьому питанні stackoverflow.com/questions/51508046/…
Раджеш К

25

Перш за все, 2 речі, які ми повинні зрозуміти

Клієнт

  • він робить запит до певного сервера

    bindService(new 
        Intent("com.android.vending.billing.InAppBillingService.BIND"),
            mServiceConn, Context.BIND_AUTO_CREATE);`
    

ось mServiceConnекземпляр ServiceConnectionкласу (вбудований), насправді це інтерфейс, який нам потрібно реалізувати за допомогою двох (1-й для підключеної до мережі та 2-й мережі, що не підключений) методу контролю стану мережевого підключення.

Сервер

  • Він обробляє запит клієнта і робить його власну копію, яка є приватною лише для клієнта, який надсилає запит, і ця копія сервера працює в іншому потоці.

Тепер на стороні клієнта, як отримати доступ до всіх методів сервера?

  • відповідь сервера надсилає за допомогою IBind Object.so Об’єкт IBind - це наш обробник, який отримує доступ до всіх методів обслуговування за допомогою оператора (.).

    MyService myService;
    public ServiceConnection myConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder binder) {
            Log.d("ServiceConnection","connected");
            myService = binder;
        }
        //binder comes from server to communicate with method's of 
    
        public void onServiceDisconnected(ComponentName className) {
            Log.d("ServiceConnection","disconnected");
            myService = null;
        }
    }
    

тепер як викликати метод, який лежить в службі

myservice.serviceMethod();

ось myServiceоб'єкт і serviceMethodeє метод в обслуговуванні. І таким чином встановлюється зв'язок між клієнтом і сервером.



5

Існує метод, який називається unbindService який прийме ServiceConnection, який ви створили при виклику bindService. Це дозволить вам від’єднатися від послуги, залишаючи її працюючою.

Це може створити проблему при повторному підключенні до неї, оскільки ви, мабуть, не знаєте, запущена вона чи ні, коли ви знову починаєте діяльність, тому вам доведеться врахувати це в коді вашої діяльності.

Удачі!


-1

Це упереджена відповідь, але я написав бібліотеку, яка може спростити використання служб Android, якщо вони працюють локально в тому ж процесі, що і програма: https://github.com/germnix/acacia

В основному ви визначаєте інтерфейс, анотований @Service та його клас реалізації, а бібліотека створює та прив'язує службу, обробляє з'єднання та фоновий робочий потік:

@Service(ServiceImpl.class)
public interface MyService {
    void doProcessing(Foo aComplexParam);
}

public class ServiceImpl implements MyService {
    // your implementation
}

MyService service = Acacia.createService(context, MyService.class);
service.doProcessing(foo);

<application
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">
    ...
    <service android:name="com.gmr.acacia.AcaciaService"/>
    ...
</application>

Ви можете отримати екземпляр пов’язаного android.app.Service, щоб приховати / показати постійні сповіщення, використовувати свій власний android.app.Service та вручну обробляти потоки, якщо хочете.


-5

Якщо користувач відмовиться, onDestroy()буде викликаний метод. Цей метод полягає у зупинці будь-якої служби, яка використовується в додатку. Отже, якщо ви хочете продовжити роботу служби, навіть якщо користувач відмовився від програми, просто стерти onDestroy(). Сподіваюся, це допоможе.


Вам доведеться замінити функцію та видалити виклик за замовчуванням для суперкласу onDestroy (), якщо ваш IDE автоматично створює його. але чому ти коли-небудь захочеш це зробити?
Riptyde4
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.