Hizmeti Android'deki etkinliğe bağlama


91

RTSP kullanarak akan ses çalan basit bir medya oynatıcı yazmaya çalışıyorum. Bir GUI etkinliğim ve kayıttan yürütmeyi gerçekleştiren bir hizmetim var. Sorum, etkinlik ve hizmet arasında en iyi nasıl iletişim kurulacağıdır (örneğin, GUI'nin oynatıcı durumuna göre güncellenmesi).

OnBind () kullanarak hizmeti etkinliğe bağlayabileceğimi biliyorum, ancak doğru anlarsam bu, etkinlik öldürülürse hizmeti durduracaktır. Kullanıcı etkinlikten çıksa bile oynatmaya devam etmek istiyorum. Bu problemle başa çıkmanın standart veya tercih edilen bir yolu var mı?

Yanıtlar:


155

"Bu Hizmetle bir Android Hizmeti başlatırsanız, startService(..)siz açıkça çağırana kadar çalışır durumda kalır stopService(..). Bir hizmetin sistem tarafından çalıştırılmasının iki nedeni vardır. Biri ararsa Context.startService(), sistem hizmeti alır ( onCreate()eğer onu oluşturur ve yöntemini çağırırsa) gerekir) ve ardından onStartCommand(Intent, int, int)istemci tarafından sağlanan bağımsız değişkenlerle yöntemini çağırın . Hizmet bu noktada Context.stopService()veya çağrılıncaya kadar çalışmaya devam edecektir. İç içe yerleştirilmeyecek stopSelf()birden çok çağrının Context.startService()(buna karşılık gelen birden çok çağrı ile sonuçlanmasına rağmen onStartCommand()) kaç kez başlatılırsa başlatılsın bir hizmet bir kez durdurulur Context.stopService()veya stopSelf()çağrılır; ancak hizmetlerstopSelf(int) hizmetin, başlatılan amaçlar işlenene kadar durdurulmamasını sağlamak için yöntem.

İstemciler ayrıca Context.bindService()bir hizmetle kalıcı bir bağlantı elde etmek için kullanabilir . Bu, hizmet zaten çalışmıyorsa ( onCreate()bunu yaparken arama ), ancak arama yapmıyorsa da aynı şekilde hizmeti oluşturur onStartCommand(). İstemci IBinder, hizmetin kendi onBind(Intent)yönteminden döndürdüğü nesneyi alacak ve müşterinin daha sonra hizmete geri arama yapmasına izin verecektir . Hizmet, bağlantı kurulduğu sürece çalışmaya devam edecektir (istemcinin Hizmetlere ilişkin bir referansı olsa da olmasa da IBinder). Genellikle IBinderdöndürülen, AIDL'de yazılmış karmaşık bir arabirim içindir.

Bir hizmet hem başlatılabilir hem de ona bağlı bağlantılar olabilir. Böyle bir durumda, sistem, hizmet başlatıldığı veya kendisine Context.BIND_AUTO_CREATEbayrakla bir veya daha fazla bağlantı olduğu sürece hizmetin çalışmaya devam etmesini sağlayacaktır . Bu durumların hiçbiri geçerli olmadığında, Hizmetin onDestroy()yöntemi çağrılır ve hizmet etkin bir şekilde sonlandırılır. Tüm temizleme (iş parçacığı durdurma, alıcıların kaydını silme) geri döndükten sonra tamamlanmalıdır onDestroy(). "


1
biraz kafa karışıklığı: Faaliyet yok edilirse hizmetin de yok edileceği doğru mu? Yoksa bu hizmet sadece kendi AIDL'mi uygularsam yok olmaz mı? Bunu soruyorum çünkü startService (özellikle IntentService üzerinde) kullandığımda hizmet, etkinlik bittiğinde değil, iş bittiğinde durur. Öyleyse, eğer faaliyet ölürse, bağlı olan hizmetin de (sadece) öleceği doğru mu?
Katedral Pillon

1
startService'i çağırarak basit bir sunucu kullanıyorsanız, stopSelf () veya stopService () çağırana kadar hizmet durmayacaktır. Ve sonraki, eğer bindService kullanırsanız, tüm bağlı / bind bileşeni bozulursa yes servisi ölecektir.
Asif Mushtaq

1
@UnKnown Hizmet startService () kullanılarak başlatılırsa, onu bağlasanız veya çözseniz de, çalışmaya devam eder ve yalnızca stopService () veya stopSelf () çağrılarak yok edilebilir. Dolayısıyla, hizmete bağlı olan etkinlik yok edilse bile hizmet yok edilmeyecektir.
CopsOnRoad

Lütfen bana bu soruyla ilgili yardım eder misin stackoverflow.com/questions/51508046/…
Rajesh K

25

Her şeyden önce anlamamız gereken 2 şey

Müşteri

  • belirli bir sunucuya talepte bulunur

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

burada sınıf mServiceConnörneği ServiceConnection(dahili), ağ bağlantı durumunu izlemek için iki yöntemle (1. ağa bağlı ve 2. ağ bağlı değil) uygulamamız gereken arayüzdür.

Sunucu

  • İstemcinin isteğini yerine getirir ve yalnızca istek gönderen istemciye özel olan kendi kopyasını oluşturur ve sunucunun bu kopyası farklı iş parçacığı üzerinde çalışır.

Şimdi istemci tarafında, tüm sunucu yöntemlerine nasıl erişilir?

  • sunucu IBind ile yanıt gönderir Object.so IBind nesnesi, (.) operatörünü kullanarak tüm hizmet yöntemlerine erişen bizim işleyicimizdir.

    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;
        }
    }
    

şimdi hizmette yatan yöntem nasıl çağırılır

myservice.serviceMethod();

burada myServicenesne ve serviceMethodehizmette yöntemdir. Bu şekilde istemci ve sunucu arasında iletişim kurulur.


10

aramayı denedim

startService(oIntent);
bindService(oIntent, mConnection, Context.BIND_AUTO_CREATE);

sonuç olarak yapışkan bir servis oluşturabilir ve ona bağlanabilirdim. Bound Service Example için ayrıntılı eğitim .


5

BindService çağrıldıktan sonra oluşturacağınız bir ServiceConnection alacak unbindService adında bir yöntem vardır . Bu, hizmetiniz çalışmaya devam ederken hizmetten bağlantınızı kesmenize izin verecektir.

Bu, tekrar bağlandığınızda bir sorun oluşturabilir, çünkü muhtemelen aktiviteyi yeniden başlattığınızda çalışıp çalışmadığını bilmiyorsunuzdur, bu yüzden bunu aktivite kodunuzda dikkate almanız gerekir.

İyi şanslar!


-1

Bu önyargılı bir cevap, ancak yerel olarak uygulamayla aynı süreçte çalışırlarsa Android Hizmetlerinin kullanımını basitleştirebilecek bir kitaplık yazdım: https://github.com/germnix/acacia

Temel olarak, @Service ve uygulama sınıfıyla açıklanmış bir arabirim tanımlarsınız ve kitaplık hizmeti oluşturur ve bağlar, bağlantıyı ve arka plan çalışan iş parçacığını işler:

@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>

Kalıcı bildirimleri gizlemek / göstermek, kendi android.app.Service hizmetinizi kullanmak ve isterseniz iş parçacığını manuel olarak işlemek için ilişkili android.app.Service'in bir örneğini alabilirsiniz.


-5

Kullanıcı geri çekilirse, onDestroy()yöntem çağrılacaktır. Bu yöntem, uygulamada kullanılan herhangi bir hizmeti durdurmak içindir. Bu nedenle, kullanıcı uygulamadan çıksa bile hizmete devam etmek istiyorsanız, silin onDestroy(). Umarım bu yardımcı olur.


Eğer IDE'niz otomatik olarak bir tane oluşturuyorsa, işlevi geçersiz kılmanız ve üst sınıfın onDestroy () çağrısını silmeniz gerekir. ama neden bunu yapmak isteyesin ki?
Riptyde4
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.