Service
, arka planda uzun süreli işlemler yapabilen bir uygulama bileşenidir. Bir kullanıcı arayüzü sağlamaz. Bir hizmet, başlatıldıktan sonra kullanıcı başka bir uygulamaya geçtikten sonra bile bir süre daha çalışmaya devam edebilir. Ayrıca, bir bileşen etkileşimde bulunmak ve hatta işlemler arası iletişim (IPC) gerçekleştirmek için bir hizmete bağlanabilir. Örneğin, bir hizmet arka planda ağ işlemlerini gerçekleştirebilir, müzik çalabilir, dosya G/Ç'si gerçekleştirebilir veya bir içerik sağlayıcıyla etkileşim kurabilir.
Dikkat: Bir hizmet, barındırma işleminin ana iş parçacığında çalışır. Hizmet, kendi iş parçacığını oluşturmaz ve aksini belirtmediğiniz sürece ayrı bir süreçte çalışmaz. Uygulama Yanıt Vermiyor (ANR) hatalarını önlemek için engelleme işlemlerini hizmet içindeki ayrı bir iş parçacığında çalıştırmanız gerekir.
Hizmet Türleri
Bunlar üç farklı hizmet türüdür:
- Ön plan
-
Ön plan hizmeti, kullanıcının fark edebileceği bazı işlemleri gerçekleştirir. Örneğin, bir ses uygulaması, ses parçası çalmak için bir ön plan hizmetini kullanır. Ön plan hizmetlerinde Bildirim gösterilmelidir. Ön plan hizmetleri, kullanıcı uygulamayla etkileşim kurmasa bile çalışmaya devam eder.
Bir ön plan hizmeti kullandığınızda, kullanıcıların hizmetin çalıştığının aktif olarak farkında olması için bildirim görüntülemeniz gerekir. Hizmet durdurulmadığı veya ön plandan kaldırılmadığı sürece bu bildirim kapatılamaz.
Uygulamanızda ön plan hizmetlerini nasıl yapılandıracağınız hakkında daha fazla bilgi edinin.
Not: WorkManager API, görevleri planlamak için esnek bir yol sunar ve gerektiğinde bu işleri ön plan hizmeti olarak çalıştırabilir. Çoğu durumda, doğrudan ön plan hizmetlerinin kullanılması yerine WorkManager'ın kullanılması tercih edilir.
- Arka plan
- Arka plan hizmeti, kullanıcı tarafından doğrudan fark edilmeyen işlemler gerçekleştirir. Örneğin, bir uygulama, depolama alanını küçültmek için bir hizmet kullanmışsa bu hizmet genellikle bir arka plan hizmeti olur.
Not: Uygulamanız API düzeyi 26 veya üstünü hedefliyorsa uygulamanın kendisi ön planda değilken sistem, arka plan hizmetlerinin çalıştırılmasına kısıtlamalar uygular. Örneğin, çoğu durumda konum bilgilerine arka planda erişmemeniz gerekir. Bunun yerine, WorkManager kullanarak görevleri planlayın.
- Bağlı
- Bir uygulama bileşeni
bindService()
yöntemini çağırarak hizmete bağlandığında hizmet bağlanmış olur. Bağlanmış hizmet, bileşenlerin hizmetle etkileşim kurmasına, istek göndermesine, sonuç almasına ve hatta işlemler arası iletişim (IPC) ile işlemler genelinde yapmasına olanak tanıyan bir istemci-sunucu arayüzü sunar. Bağlı bir hizmet, yalnızca başka bir uygulama bileşeni ona bağlandığı sürece çalışır. Birden fazla bileşen hizmete aynı anda bağlanabilir ancak bu bileşenlerin tümü kaldırıldığında hizmet kaldırılır.
Bu belgede genellikle başlatılan ve bağlanan hizmetler ayrı ayrı ele alınsa da hizmetiniz her iki şekilde de çalışabilir. Başlatılabilir (süresiz olarak çalıştırılabilir) ve ayrıca bağlamaya izin verilebilir. Birkaç geri çağırma yöntemi uygulayıp uygulamamanız yeterlidir: Bileşenlerin başlatmasına izin vermek için onStartCommand()
, bağlamaya izin vermek için de onBind()
.
Hizmetinizin başlatılmış, bağlanmış veya her ikisi birden olmasına bakılmaksızın, herhangi bir uygulama bileşeni hizmeti (ayrı bir uygulamadan bile olsa) herhangi bir bileşenin bir Intent
ile başlatarak bir etkinliği kullanabileceği şekilde kullanabilir. Ancak, manifest dosyasında hizmeti gizli olarak beyan edebilir ve diğer uygulamalardan erişimi engelleyebilirsiniz.
Bu konu, Manifest'te hizmetin bildirilmesi hakkında daha ayrıntılı bir şekilde ele alınmaktadır.
Hizmet ve iş parçacığı arasında seçim yapma
Hizmet, kullanıcı uygulamanızla etkileşim kurmadığında bile arka planda çalışabilen bir bileşendir. Bu nedenle, bir hizmeti yalnızca ihtiyacınız olduğunda oluşturmalısınız.
Ana iş parçanızın dışında ancak yalnızca kullanıcı uygulamanızla etkileşimde bulunurken gerçekleştirmeniz gerekiyorsa bunun yerine başka bir uygulama bileşeni bağlamında yeni bir iş parçacığı oluşturmanız gerekir. Örneğin, yalnızca etkinliğiniz devam ederken bazı müzikler çalmak istiyorsanız onCreate()
ürününde bir ileti dizisi oluşturabilir, onu onStart()
ürününde çalıştırmaya başlayabilir ve onStop()
içinde durdurabilirsiniz.
Geleneksel Thread
sınıfı yerine java.util.concurrent
paketinden veya Kotlin eş yordamlarından iş parçacığı havuzlarını ve yürütücüleri de kullanabilirsiniz. Yürütmeyi arka plan iş parçacıklarına taşıma hakkında daha fazla bilgi için Android'de Threading dokümanına bakın.
Bir hizmet kullandığınızda bu hizmetin varsayılan olarak uygulamanızın ana iş parçacığında çalışmaya devam ettiğini unutmayın. Bu nedenle, hizmet yoğun veya engelleme gerektiren işlemler gerçekleştiriyorsa hizmet içinde yeni bir iş parçacığı oluşturmanız gerekir.
Temel bilgiler
Hizmet oluşturmak için Service
alt sınıfı oluşturmanız veya mevcut alt sınıflarından birini kullanmanız gerekir. Uygulamanızda, hizmet yaşam döngüsünün temel unsurlarını işleyen bazı geri çağırma yöntemlerini geçersiz kılmanız ve uygun durumlarda bileşenlerin hizmete bağlanmasını sağlayan bir mekanizma sağlamanız gerekir. Bunlar, geçersiz kılmanız gereken en önemli geri çağırma yöntemleridir:
onStartCommand()
- Başka bir bileşen (ör. bir etkinlik) hizmetin başlatılmasını istediğinde sistem bu yöntemi
startService()
yöntemini çağırarak çağırır. Bu yöntem yürütüldüğünde hizmet başlatılır ve süresiz olarak arka planda çalışabilir. Bunu uygularsanız çalışması tamamlandığındastopSelf()
veyastopService()
yöntemini çağırarak hizmeti durdurmak sizin sorumluluğunuzdadır. Yalnızca bağlama sağlamak isterseniz bu yöntemi uygulamanız gerekmez. onBind()
- Başka bir bileşen hizmete bağlanmak (ör. TBG gerçekleştirmek) istediğinde sistem bu yöntemi
bindService()
yöntemini çağırarak çağırır. Bu yöntemi uygulamanızda, istemcilerinIBinder
döndürerek hizmetle iletişim kurmak için kullandığı bir arayüz sağlamanız gerekir. Bu yöntemi her zaman uygulamanız gerekir. Ancak, bağlamaya izin vermek istemiyorsanız null değerini döndürmeniz gerekir. onCreate()
- Sistem bu yöntemi, hizmet ilk oluşturulduğunda (
onStartCommand()
veyaonBind()
çağrılmadan önce) tek seferlik kurulum prosedürleri gerçekleştirmek için çağırır. Hizmet zaten çalışıyorsa bu yöntem çağrılmaz. onDestroy()
- Hizmet artık kullanılmadığında ve kaldırılırken sistem bu yöntemi çağırır. İş parçacıkları, kayıtlı dinleyiciler veya alıcılar gibi kaynakları temizlemek için hizmetiniz bunu uygulamalıdır. Bu, hizmetin aldığı son çağrıdır.
Bir bileşen startService()
yöntemini çağırarak hizmeti başlatırsa (bu durumda onStartCommand()
çağrılır) hizmet, stopSelf()
ile kendiliğinden durdurulana veya başka bir bileşen stopService()
çağrısı yaparak çalışmayı durdurana kadar çalışmaya devam eder.
Bir bileşen hizmeti oluşturmak için bindService()
çağırırsa ve onStartCommand()
çağrılanmazsa çağrılmazsa hizmet, yalnızca bileşen kendisine bağlı olduğu sürece çalışır. Sistem, tüm istemcilerinin bağlantısı kaldırıldıktan sonra hizmeti yok eder.
Android sistemi, bir hizmeti yalnızca bellek az olduğunda durdurur ve kullanıcı odağı olan etkinlik için sistem kaynaklarını kurtarmalıdır. Hizmet, kullanıcı odağı olan bir etkinliğe bağlıysa sonlandırılma olasılığı daha düşüktür; hizmetin ön planda çalıştığı beyan edilmişse nadiren sonlandırılır.
Hizmet başlatılırsa ve uzun süredir çalışıyorsa sistem zamanla arka plan görevleri listesindeki konumunu düşürür ve hizmeti devre dışı bırakmaya daha elverişli hale getirir. Hizmetiniz başlatıldıysa sistem tarafından yapılan yeniden başlatma işlemlerini sorunsuz şekilde gerçekleştirecek şekilde tasarlamanız gerekir. Sistem, hizmetinizi sonlandırırsa kaynaklar kullanılabilir hale gelir gelmez yeniden başlatır ancak bu durum, onStartCommand()
kaynağından döndürdüğünüz değere de bağlıdır. Sistemin bir hizmeti ne zaman kaldırabileceği hakkında daha fazla bilgi edinmek için Processes and Threading (İşlemler ve İş Parçacığı) dokümanına bakın.
Aşağıdaki bölümlerde startService()
ve bindService()
hizmet yöntemlerini nasıl oluşturacağınızı ve diğer uygulama bileşenlerinden nasıl kullanacağınızı öğreneceksiniz.
Manifest'te bir hizmeti tanımlama
Etkinliklerde ve diğer bileşenlerde olduğu gibi, tüm hizmetleri uygulamanızın manifest dosyasında beyan etmeniz gerekir.
Hizmetinizi tanımlamak için <application>
öğesinin alt öğesi olarak bir <service>
öğesi ekleyin. Örnek:
<manifest ... > ... <application ... > <service android:name=".ExampleService" /> ... </application> </manifest>
Hizmetinizi manifest dosyasında tanımlama hakkında daha fazla bilgi edinmek için <service>
öğe referansına bakın.
Hizmeti başlatmak için gereken izinler ve hizmetin çalışması gereken süreç gibi özellikleri tanımlamak amacıyla <service>
öğesine ekleyebileceğiniz başka özellikler de vardır. android:name
özelliği zorunlu tek özelliktir ve hizmetin sınıf adını belirtir. Uygulamanızı yayınladıktan sonra, hizmeti başlatma veya bağlamayla ilgili açık amaçlara bağlı olarak kod kırma riskini önlemek amacıyla bu adı değiştirmeyin (Değiştirilemeyen Şeyler blog yayınını okuyun).
Dikkat: Uygulamanızın güvenli olduğundan emin olmak için Service
başlatırken her zaman açık bir intent kullanın ve hizmetleriniz için intent filtreleri bildirmeyin. Bir hizmeti başlatmak için dolaylı intent'lerin kullanılması güvenlik açısından risk oluşturur. Çünkü amaca yanıt veren hizmetten emin olamazsınız ve kullanıcı hangi hizmetin başladığını göremez. Android 5.0 (API düzeyi 21) sürümünden itibaren, dolaylı bir niyetle bindService()
yöntemini çağırırsanız sistem bir istisna atar.
android:exported
özelliğini dahil edip false
olarak ayarlayarak hizmetinizin yalnızca uygulamanızın kullanımına sunulduğundan emin olabilirsiniz. Bu işlem, açık bir niyet kullanılsa bile diğer uygulamaların hizmetinizi başlatmasını etkili bir şekilde durdurur.
Not:
Kullanıcılar, cihazlarında hangi hizmetlerin çalıştığını görebilir. Tanımadığı veya güvenmediği bir hizmet görürlerse hizmeti durdurabilirler. Hizmetinizin kullanıcılar tarafından yanlışlıkla durdurulmasını önlemek için uygulama manifestinizdeki <service>
öğesine android:description
özelliğini eklemeniz gerekir. Açıklama kısmına hizmetin işlevini ve sunduğu avantajları açıklayan kısa bir cümle ekleyin.
Başlatılmış hizmet oluşturma
Başlatılan hizmet, başka bir bileşenin startService()
yöntemini çağırarak başlattığı bir hizmettir. Bu çağrı, hizmetin onStartCommand()
yöntemine çağrıyla sonuçlanır.
Bir hizmet başlatıldığında, onu başlatan bileşenden bağımsız bir yaşam döngüsüne sahiptir. Hizmet, hizmeti başlatan bileşen yok edilmiş olsa bile arka planda süresiz olarak çalışabilir. Bu nedenle, işi tamamlandığında hizmet stopSelf()
çağrısı yaparak kendini durdurmalıdır. Başka bir bileşen ise stopService()
yöntemini çağırarak hizmeti durdurabilir.
Etkinlik gibi bir uygulama bileşeni, startService()
yöntemini çağırıp hizmeti belirten ve hizmetin kullanacağı verileri içeren bir Intent
ileterek hizmeti başlatabilir. Hizmet, bu Intent
değerini onStartCommand()
yönteminde alır.
Örneğin, bir etkinliğin online bir veritabanına bazı veriler kaydetmesi gerektiğini varsayalım. Etkinlik, bir tamamlayıcı hizmet başlatabilir ve startService()
işlevine bir amaç ileterek bu hizmetin verilerini kaydedecek verileri sunabilir. Hizmet, amacı onStartCommand()
ürününde alır, internete bağlanır ve veritabanı işlemini gerçekleştirir. İşlem tamamlandığında hizmet kendini durdurur ve kaldırılır.
Dikkat: Bir hizmet, varsayılan olarak bildirildiği uygulamayla aynı işlemde ve uygulamanın ana iş parçacığında çalışır. Kullanıcı, aynı uygulamadaki bir etkinlikle etkileşimde bulunurken yoğun işlemler veya engelleme işlemleri gerçekleştirirse hizmet, etkinlik performansını yavaşlatır. Uygulama performansının etkilenmemesi için hizmet içinde yeni bir iş parçacığı başlatın.
Service
sınıfı, tüm hizmetler için temel sınıftır. Bu sınıfı genişlettiğinizde, hizmetin tüm çalışmalarını tamamlayabileceği yeni bir iş parçacığı oluşturmanız önemlidir. Hizmet, varsayılan olarak uygulamanızın ana iş parçacığını kullanır. Bu da uygulamanızın çalıştığı tüm etkinliklerin performansını yavaşlatabilir.
Android çerçevesi, tüm başlatma isteklerini tek tek işlemek için bir çalışan iş parçacığı kullanan Service
IntentService
alt sınıfını da sağlar. Bu sınıfın kullanılması, Arka planda yürütme sınırlarının uygulanması nedeniyle Android 8 Oreo'dan itibaren iyi çalışmayacağından yeni uygulamalarda iyi çalışmayacağı için önerilmez.
Ayrıca, Android 11'den itibaren kullanımdan kaldırılmıştır.
Android'in yeni sürümleriyle uyumlu olan JobIntentService'i, IntentService
için bir yedek olarak kullanabilirsiniz.
Aşağıdaki bölümlerde, kendi özel hizmetinizi nasıl uygulayabileceğiniz açıklanmıştır. Ancak çoğu kullanım durumu için bunun yerine WorkManager'ı kullanmanız önemle tavsiye edilir. İhtiyaçlarınıza uygun bir çözüm olup olmadığını görmek için Android'de arka planda işleme kılavuzuna bakın.
Hizmet sınıfını genişletme
Service
sınıfını her gelen niyeti işleyecek şekilde genişletebilirsiniz. Temel bir uygulama aşağıdaki gibi görünebilir:
Kotlin
class HelloService : Service() { private var serviceLooper: Looper? = null private var serviceHandler: ServiceHandler? = null // Handler that receives messages from the thread private inner class ServiceHandler(looper: Looper) : Handler(looper) { override fun handleMessage(msg: Message) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. try { Thread.sleep(5000) } catch (e: InterruptedException) { // Restore interrupt status. Thread.currentThread().interrupt() } // Stop the service using the startId, so that we don't stop // the service in the middle of handling another job stopSelf(msg.arg1) } } override fun onCreate() { // Start up the thread running the service. Note that we create a // separate thread because the service normally runs in the process's // main thread, which we don't want to block. We also make it // background priority so CPU-intensive work will not disrupt our UI. HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND).apply { start() // Get the HandlerThread's Looper and use it for our Handler serviceLooper = looper serviceHandler = ServiceHandler(looper) } } override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show() // For each start request, send a message to start a job and deliver the // start ID so we know which request we're stopping when we finish the job serviceHandler?.obtainMessage()?.also { msg -> msg.arg1 = startId serviceHandler?.sendMessage(msg) } // If we get killed, after returning from here, restart return START_STICKY } override fun onBind(intent: Intent): IBinder? { // We don't provide binding, so return null return null } override fun onDestroy() { Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show() } }
Java
public class HelloService extends Service { private Looper serviceLooper; private ServiceHandler serviceHandler; // Handler that receives messages from the thread private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. try { Thread.sleep(5000); } catch (InterruptedException e) { // Restore interrupt status. Thread.currentThread().interrupt(); } // Stop the service using the startId, so that we don't stop // the service in the middle of handling another job stopSelf(msg.arg1); } } @Override public void onCreate() { // Start up the thread running the service. Note that we create a // separate thread because the service normally runs in the process's // main thread, which we don't want to block. We also make it // background priority so CPU-intensive work doesn't disrupt our UI. HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); // Get the HandlerThread's Looper and use it for our Handler serviceLooper = thread.getLooper(); serviceHandler = new ServiceHandler(serviceLooper); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); // For each start request, send a message to start a job and deliver the // start ID so we know which request we're stopping when we finish the job Message msg = serviceHandler.obtainMessage(); msg.arg1 = startId; serviceHandler.sendMessage(msg); // If we get killed, after returning from here, restart return START_STICKY; } @Override public IBinder onBind(Intent intent) { // We don't provide binding, so return null return null; } @Override public void onDestroy() { Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); } }
Örnek kod, onStartCommand()
içindeki tüm gelen aramaları işler ve çalışmayı arka plandaki bir ileti dizisinde çalışan bir Handler
üzerinde yayınlar. IntentService
ile aynı şekilde çalışır ve tüm istekleri sırayla işler.
Örneğin, aynı anda birden fazla istek çalıştırmak istiyorsanız, kodu bir iş parçacığı havuzunda çalıştıracak şekilde değiştirebilirsiniz.
onStartCommand()
yönteminin bir tam sayı döndürmesi gerektiğini unutmayın. Tam sayı, sistemin hizmeti sonlandırması durumunda sistemin hizmeti nasıl devam ettireceğini açıklayan bir değerdir. onStartCommand()
işlevinin döndürdüğü değer aşağıdaki sabit değerlerden biri olmalıdır:
START_NOT_STICKY
onStartCommand()
döndürüldükten sonra sistem hizmeti sonlandırırsa beklemede olan yayınlama niyetleri olmadığı sürece hizmeti yeniden oluşturmayın. Bu, gerekli olmadığında hizmetinizi çalıştırmaktan kaçınmak için ve uygulamanız henüz tamamlanmamış işleri yeniden başlatabiliyorsa onu çalıştırmaktan kaçınmak için en güvenli seçenektir.START_STICKY
onStartCommand()
geri döndükten sonra sistem hizmeti sonlandırırsa hizmeti yeniden oluşturuponStartCommand()
yöntemini çağırın ancak son amacı yeniden teslim etmeyin. Bunun yerine, hizmeti başlatmak için bekleyen amaçlar yoksa sistemonStartCommand()
hizmetini null intent ile çağırır. Bu durumda bu amaçlar teslim edilir. Bu, komut çalıştırmayan ancak süresiz olarak çalışan ve iş bekleyen medya oynatıcılar (veya benzer hizmetler) için uygundur.START_REDELIVER_INTENT
onStartCommand()
geri döndükten sonra sistem hizmeti sonlandırırsa hizmeti yeniden oluşturun ve hizmete teslim edilen son niyetleonStartCommand()
yöntemini çağırın. Beklemedeki tüm amaçlar sırayla teslim edilir. Bu, dosya indirme gibi hemen devam ettirilmesi gereken bir işi etkin olarak yürüten hizmetler için uygundur.
Bu dönüş değerleri hakkında daha fazla bilgi için her bir sabit değer için bağlantılı referans belgelerine bakın.
Hizmet başlatma
Intent
öğesini startService()
veya startForegroundService()
öğesine geçirerek bir etkinlik veya başka bir uygulama bileşeninden hizmet başlatabilirsiniz. Android sistemi, hizmetin onStartCommand()
yöntemini çağırır ve bunu, hangi hizmetin başlatılacağını belirten Intent
yöntemini iletir.
Not: Uygulamanız API düzeyi 26 veya üstünü hedefliyorsa sistem, uygulamanın kendisi ön planda olmadığı sürece arka plan hizmetlerinin kullanımı veya oluşturulmasıyla ilgili kısıtlamalar uygular. Bir uygulamanın bir ön plan hizmeti oluşturması gerekiyorsa uygulama, startForegroundService()
işlevini çağırmalıdır. Bu yöntem bir arka plan hizmeti oluşturur ancak yöntem, sisteme hizmetin kendisini ön plana yükselteceğini bildirir. Hizmet oluşturulduktan sonra, hizmet beş saniye içinde startForeground()
yöntemini çağırmalıdır.
Örneğin, bir etkinlik, önceki bölümde (HelloService
) startService()
ile açık bir amaç kullanarak örnek hizmeti burada gösterildiği gibi başlatabilir:
Kotlin
startService(Intent(this, HelloService::class.java))
Java
startService(new Intent(this, HelloService.class));
startService()
yöntemi hemen geri döner ve Android sistemi, hizmetin onStartCommand()
yöntemini çağırır. Hizmet zaten çalışmıyorsa sistem önce onCreate()
yöntemini, ardından onStartCommand()
yöntemini çağırır.
Hizmet aynı zamanda bağlama da sağlamıyorsa uygulama bileşeni ile hizmet arasındaki tek iletişim modu startService()
ile sunulan amaç olur. Ancak hizmetin bir sonucu geri göndermesini isterseniz hizmeti başlatan istemci, getBroadcast()
ile bir yayın için PendingIntent
oluşturup bunu hizmeti başlatan Intent
içindeki hizmete gönderebilir. Ardından hizmet, yayını kullanarak
bir sonuç elde edebilir.
Hizmeti başlatmaya yönelik birden fazla istek, hizmetin onStartCommand()
öğesine karşılık gelen birden çok çağrıyla sonuçlanır. Ancak hizmeti durdurmak için tek bir istek (stopSelf()
veya stopService()
ile) gerekir.
Bir hizmeti durdurma
Başlatılan bir hizmet kendi yaşam döngüsünü yönetmelidir. Yani sistem, sistem belleğini kurtarması gerekmediği ve onStartCommand()
geri döndükten sonra hizmet çalışmaya devam etmediği sürece sistem, hizmeti durdurmaz veya kaldırmaz. Hizmetin stopSelf()
yöntemini çağırarak kendisini durdurması gerekir. Aksi takdirde başka bir bileşen stopService()
yöntemini çağırarak hizmeti durdurabilir.
stopSelf()
veya stopService()
ile durdurma istendiğinde sistem, hizmeti mümkün olan en kısa sürede kaldırır.
Hizmetiniz aynı anda onStartCommand()
için birden fazla isteği gerçekleştiriyorsa yeni bir başlatma isteği almış olabileceğinizden, bir başlatma isteğini işlemeyi bitirdiğinizde hizmeti durdurmamanız gerekir (ilk isteğin sonunda durdurmak ikinci isteği de sonlandırır). Bu sorunu önlemek için stopSelf(int)
kullanarak hizmeti durdurma isteğinizin her zaman en son başlatma isteğine dayalı olmasını sağlayabilirsiniz. Yani stopSelf(int)
yöntemini çağırdığınızda durdurma isteğinizin karşılık geldiği başlatma isteğinin (onStartCommand()
'a gönderilen startId
) kimliğini iletirsiniz. Bu durumda hizmet, stopSelf(int)
çağrısını gerçekleştirmeden önce yeni bir başlatma isteği alırsa kimlik eşleşmez ve hizmet durmaz.
Dikkat: Sistem kaynaklarını boşa harcamamak ve pil gücü tüketmemek için uygulamanızın çalışması bittiğinde hizmetlerini durdurduğundan emin olun.
Gerekirse diğer bileşenler stopService()
yöntemini çağırarak hizmeti durdurabilir. Hizmet için bağlamayı etkinleştirseniz bile, onStartCommand()
bir çağrı alırsa hizmeti her zaman kendiniz durdurmanız gerekir.
Bir hizmetin yaşam döngüsü hakkında daha fazla bilgi edinmek için aşağıdaki Hizmet Yaşam Döngüsünü Yönetme bölümüne bakın.
Bağlı hizmet oluşturma
Bağlı hizmet, uzun süreli bağlantı oluşturmak için bindService()
yöntemini çağırarak uygulama bileşenlerinin ona bağlanmasına izin veren hizmettir.
Genellikle bileşenlerin startService()
yöntemini çağırarak başlatmasına izin vermez.
Uygulamanızdaki etkinliklerden ve diğer bileşenlerden hizmetle etkileşimde bulunmak veya uygulamanızın işlevlerinden bazılarını işlemler arası iletişim (IPC) üzerinden diğer uygulamalara sunmak istediğinizde bağlı bir hizmet oluşturun.
Bağlanmış hizmet oluşturmak için onBind()
geri çağırma yöntemini uygulayarak hizmetle iletişimde kullanılacak arayüzü tanımlayan bir IBinder
döndürülmesini sağlayın. Diğer uygulama bileşenleri, arayüzü almak ve hizmette yöntemler çağırmaya başlamak için bindService()
yöntemini çağırabilir. Hizmet yalnızca kendisine bağlı uygulama bileşenini sunmak için çalışır. Bu nedenle, hizmete bağlı herhangi bir bileşen olmadığında sistem hizmeti yok eder.
Bağlı bir hizmeti, hizmet onStartCommand()
tarihine kadar başlatıldığında yaptığınız gibi durdurmanız gerekmez.
Bağlanmış hizmet oluşturmak için istemcinin hizmetle nasıl iletişim kurabileceğini belirten arayüzü tanımlamanız gerekir. Hizmet ile istemci arasındaki bu arayüz, IBinder
uygulamasının bir uygulaması olmalıdır ve hizmetinizin onBind()
geri çağırma yönteminden döndürdüğü arayüzdür. İstemci IBinder
aldıktan sonra bu arayüz üzerinden hizmetle etkileşimde bulunmaya başlayabilir.
Hizmete aynı anda birden fazla istemci bağlanabilir. Bir istemci hizmetle etkileşimi tamamladığında bağlantıyı kesmek için unbindService()
çağırır.
Hizmete bağlı hiçbir istemci olmadığında sistem, hizmeti yok eder.
Bağlı bir hizmeti uygulamanın birden fazla yolu vardır ve uygulama, başlatılan bir hizmetten daha karmaşıktır. Bu nedenlerle, bağlı hizmet görüşmesi Sınır Hizmetleri ile ilgili ayrı bir belgede görünür.
Kullanıcıya bildirim gönderme
Bir hizmet çalışırken atıştırma çubuğu bildirimlerini veya durum çubuğu bildirimlerini kullanarak kullanıcıya etkinlikleri bildirebilir.
Snackbar bildirimi, mevcut pencerenin yüzeyinde, kaybolmadan önce yalnızca bir an için görünen mesajdır. Durum çubuğu bildirimi, durum çubuğunda bir mesaj içeren simge sağlar. Kullanıcı, bu simgeyi seçerek bir işlem (ör. etkinlik başlatma) gerçekleştirebilir.
Dosya indirme gibi arka planda bir çalışma tamamlandığında durum çubuğu bildirimi genellikle kullanılan en iyi tekniktir ve kullanıcı artık bununla ilgili işlem yapabilir. Kullanıcı, genişletilmiş görünümden bildirimi seçtiğinde, bildirim bir etkinlik başlatabilir (ör. indirilen dosyayı görüntülemek).
Bir hizmetin yaşam döngüsünü yönetme
Bir hizmetin yaşam döngüsü, bir etkinliğin yaşam döngüsünden çok daha basittir. Ancak hizmetler, kullanıcının farkında olmadan arka planda çalışabileceğinden hizmetinizin nasıl oluşturulduğuna ve yok edildiğine dikkat etmeniz daha da önemlidir.
Hizmet yaşam döngüsü (oluşturulmasından yok edildiği ana kadar) şu iki yoldan birini takip edebilir:
- Başlatılmış bir hizmet
Başka bir bileşen
startService()
çağırdığında hizmet oluşturulur. Bu durumda hizmet süresiz olarak çalışır vestopSelf()
yöntemini çağırarak kendisini durdurması gerekir. Başka bir bileşen destopService()
çağrısı yaparak hizmeti durdurabilir. Hizmet durdurulduğunda, sistem hizmeti imha eder. - Bağlı hizmet
Başka bir bileşen (bir istemci)
bindService()
çağırdığında hizmet oluşturulur. Ardından istemci, birIBinder
arayüzü üzerinden hizmetle iletişim kurar. İstemci,unbindService()
çağrısı yaparak bağlantıyı kapatabilir. Birden çok istemci aynı hizmete bağlanabilir ve tüm istemciler bağlantıyı kaldırdığınızda sistem hizmeti yok eder. Hizmetin kendini durdurması gerekmez.
Bu iki yol birbirinden tamamen ayrı değildir. startService()
ile başlatılmış bir hizmete bağlanabilirsiniz. Örneğin, çalınacak müziği tanımlayan bir Intent
ile startService()
işlevini çağırarak bir arka plan müziği hizmeti başlatabilirsiniz. Daha sonra, muhtemelen kullanıcı oynatıcı üzerinde bir miktar kontrole sahip olmak veya mevcut şarkı hakkında bilgi almak istediğinde etkinlik, bindService()
yöntemini çağırarak hizmete bağlanabilir. Bu gibi durumlarda, tüm istemcilerin bağlantısı kaldırılana kadar stopService()
veya stopSelf()
hizmeti gerçekten durdurmaz.
Yaşam döngüsü geri çağırmalarını uygulama
Bir hizmette olduğu gibi, hizmetin durumundaki değişiklikleri izlemek ve uygun zamanlarda iş gerçekleştirmek için uygulayabileceğiniz yaşam döngüsü geri çağırma yöntemleri vardır. Aşağıdaki iskelet hizmet, yaşam döngüsü yöntemlerinin her birini göstermektedir:
Kotlin
class ExampleService : Service() { private var startMode: Int = 0 // indicates how to behave if the service is killed private var binder: IBinder? = null // interface for clients that bind private var allowRebind: Boolean = false // indicates whether onRebind should be used override funonCreate
() { // The service is being created } override funonStartCommand
(intent: Intent?, flags: Int, startId: Int): Int { // The service is starting, due to a call to startService() return startMode } override funonBind
(intent: Intent): IBinder? { // A client is binding to the service with bindService() return binder } override funonUnbind
(intent: Intent): Boolean { // All clients have unbound with unbindService() return allowRebind } override funonRebind
(intent: Intent) { // A client is binding to the service with bindService(), // after onUnbind() has already been called } override funonDestroy
() { // The service is no longer used and is being destroyed } }
Java
public class ExampleService extends Service { int startMode; // indicates how to behave if the service is killed IBinder binder; // interface for clients that bind boolean allowRebind; // indicates whether onRebind should be used @Override public voidonCreate
() { // The service is being created } @Override public intonStartCommand
(Intent intent, int flags, int startId) { // The service is starting, due to a call tostartService()
return startMode; } @Override public IBinderonBind
(Intent intent) { // A client is binding to the service withbindService()
return binder; } @Override public booleanonUnbind
(Intent intent) { // All clients have unbound withunbindService()
return allowRebind; } @Override public voidonRebind
(Intent intent) { // A client is binding to the service withbindService()
, // after onUnbind() has already been called } @Override public voidonDestroy
() { // The service is no longer used and is being destroyed } }
Not: Etkinlik yaşam döngüsü geri çağırma yöntemlerinin aksine, bu geri çağırma yöntemlerinin üst sınıf uygulamasını çağırmanız gerekmez.

2. Şekil. Hizmet yaşam döngüsü. Soldaki diyagramda hizmet startService()
ile oluşturulduğunda yaşam döngüsü; sağdaki şemada ise hizmetin bindService()
ile oluşturulduğu andaki yaşam döngüsü gösterilmektedir.
Şekil 2'de bir hizmet için tipik geri çağırma yöntemleri gösterilmektedir. Bu şekilde, startService()
tarafından oluşturulan hizmetler ile bindService()
tarafından oluşturulan hizmetler birbirinden ayrılsa da herhangi bir hizmetin, nasıl başlatılmış olursa olsun istemcilerin bağlanmasına izin verebileceğini unutmayın.
Başlangıçta onStartCommand()
ile başlatılan bir hizmet (startService()
numaralı telefonu arayan bir istemci tarafından) yine de onBind()
numaralı telefonu alabilir (bir istemci bindService()
araması yaptığında).
Bu yöntemleri uygulayarak hizmetin yaşam döngüsündeki şu iki iç içe geçmiş döngüsünü izleyebilirsiniz:
- Bir hizmetin tüm kullanım ömrü,
onCreate()
çağrısının yapıldığı zaman ileonDestroy()
ürününün döndürdüğü zaman arasında gerçekleşir. Tıpkı etkinliklerde olduğu gibi, bir hizmet de ilk kurulumunuonCreate()
ürününde yapar ve kalan tüm kaynaklarıonDestroy()
ürününde serbest bırakır. Örneğin, bir müzik çalma hizmeti, müziğinonCreate()
içinde çalındığı ileti dizisini oluşturabilir ve ardındanonDestroy()
içindeki ileti dizisini durdurabilir.Not:
onCreate()
veonDestroy()
yöntemleri,startService()
veyabindService()
tarafından oluşturulmuş olmalarına bakılmaksızın tüm hizmetler için çağrılır. - Bir hizmetin etkin ömrü
onStartCommand()
veyaonBind()
çağrısıyla başlar. Her yönteme,startService()
veyabindService()
öğesine geçirilenIntent
verilir.Hizmet başlatılırsa etkin kullanım ömrü, tüm kullanım ömrü boyunca sona erdiği anda sona erer (hizmet,
onStartCommand()
iade edildikten sonra bile etkin olmaya devam eder). Hizmet bağlıysaonUnbind()
döndüğünde etkin kullanım süresi sona erer.
Not: Başlatılan bir hizmet, stopSelf()
veya stopService()
çağrısıyla durdurulsa da hizmet için ilgili bir geri çağırma yoktur (onStop()
geri çağırma yapılmaz). Hizmet bir istemciye bağlı değilse hizmet durdurulduğunda sistem tarafından kaldırılır. Alınan tek geri arama onDestroy()
olur.
Bağlama sağlayan bir hizmet oluşturma hakkında daha fazla bilgi edinmek için Bağlı bir hizmetin yaşam döngüsünü yönetme bölümündeki onRebind()
geri çağırma yöntemi hakkında daha fazla bilginin yer aldığı Sınır Hizmetleri belgesine bakın.