Ön plan hizmetleri

Ön plan hizmetleri, kullanıcının fark edebileceği işlemleri gerçekleştirir.

Ön plan hizmetleri, uygulamanızın ön planda bir işlem gerçekleştirdiğini ve sistem kaynaklarını kullandığını bildirmek için bir durum çubuğu bildirimi gösterir.

Ön plan hizmetlerini kullanan uygulamalara örnek olarak şunlar verilebilir:

  • Ön plan hizmetinde müzik çalan bir müzik çalma uygulaması. Bildirimde, çalmakta olan şarkı gösterilebilir.
  • Kullanıcıdan izin aldıktan sonra kullanıcının koşusunu ön plan hizmetinde kaydeden bir fitness uygulaması. Bildirimde, kullanıcının mevcut fitness oturumu sırasında katettiği mesafe gösterilebilir.

Ön plan hizmetini yalnızca uygulamanızın kullanıcı tarafından fark edilebilir bir görevi gerçekleştirmesi gerektiğinde (kullanıcıyla doğrudan etkileşimde bulunmasa bile) kullanın. İşlem, minimum öncelikli bildirim kullanmak istemenize neden olacak kadar önemli değilse bunun yerine bir arka plan görevi oluşturun.

Bu dokümanda, ön plan hizmetlerini kullanmak için gereken izinler ve bir ön plan hizmetinin nasıl başlatılıp arka plandan kaldırılacağı açıklanmaktadır. Ayrıca belirli kullanım alanlarının ön plan hizmeti türleriyle nasıl ilişkilendirileceği ve arka planda çalışan bir uygulamadan ön plan hizmeti başlattığınızda geçerli olan erişim kısıtlamaları açıklanmaktadır.

Kullanıcı varsayılan olarak bildirimi kapatabilir

Android 13'ten (API düzeyi 33) itibaren, kullanıcılar bir ön plan hizmetiyle ilişkilendirilmiş bildirimi varsayılan olarak kapatabilir. Kullanıcılar bunun için bildirimde bir kaydırma hareketi gerçekleştirir. Genellikle, ön plan hizmeti durdurulmadığı veya ön plandan kaldırılmadığı sürece bildirim kapatılmaz.

Bildirimin kullanıcı tarafından kapatılmamasını istiyorsanız Notification.Builder kullanarak bildiriminizi oluştururken true öğesini setOngoing() yöntemine iletin.

Hemen bildirim gösteren hizmetler

Bir ön plan hizmetinde aşağıdaki özelliklerden en az biri varsa sistem, Android 12 veya sonraki sürümleri çalıştıran cihazlarda bile hizmet başladıktan hemen sonra ilgili bildirimi gösterir:

Android 13 (API düzeyi 33) veya sonraki sürümlerde kullanıcı bildirim iznini reddederse Görev Yöneticisi'nde ön plan hizmetleriyle ilgili bildirimleri görmeye devam ederler ancak bildirim çekmecesinde görmezler.

Manifest'inizde ön plan hizmetlerini bildirme

Uygulamanızın manifest dosyasında uygulamanızın her ön plan hizmetini bir <service> öğesiyle tanımlayın. Her hizmet için ne tür bir iş yaptığını açıklamak amacıyla bir android:foregroundServiceType özelliği kullanın.

Örneğin, uygulamanız müzik çalan bir ön plan hizmeti oluşturuyorsa hizmeti şu şekilde beyan edebilirsiniz:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>

    <service
        android:name=".MyMediaPlaybackService"
        android:foregroundServiceType="mediaPlayback"
        android:exported="false">
    </service>
</manifest>

Hizmetiniz için geçerli olan birden fazla tür varsa bunları | operatörüyle ayırın. Örneğin, kamera ve mikrofonu kullanan bir hizmet bunu şöyle bildirir:

android:foregroundServiceType="camera|microphone"

Ön plan hizmeti izinlerini isteme

Android 9 (API düzeyi 28) veya sonraki sürümleri hedefleyen ve ön plan hizmetlerini kullanan uygulamaların, aşağıdaki kod snippet'inde gösterildiği gibi uygulama manifest dosyasında FOREGROUND_SERVICE isteğinde bulunması gerekir. Bu normal bir izin olduğu için sistem, izni istekte bulunan uygulamaya otomatik olarak verir.

Ayrıca, uygulama API düzeyi 34 veya üstünü hedefliyorsa ön plan hizmetinin yapacağı iş için uygun izin türünü istemelidir. Her ön plan hizmet türünün ilgili bir izin türü vardır. Örneğin, bir uygulama kamerayı kullanan bir ön plan hizmetini başlatırsa hem FOREGROUND_SERVICE hem de FOREGROUND_SERVICE_CAMERA izinlerini istemeniz gerekir. Bunların tümü normal izinler olduğu için manifest dosyasında listelenmeleri durumunda sistem bunları otomatik olarak verir.

<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA"/>

    <application ...>
        ...
    </application>
</manifest>

Ön plan hizmeti ön koşulları

Android 14'ten (API düzeyi 34) itibaren, bir ön plan hizmetini başlattığınızda sistem hizmet türüne göre belirli ön koşulları kontrol eder. Örneğin, location türünde bir ön plan hizmeti başlatmaya çalışırsanız sistem, uygulamanızın zaten ACCESS_COARSE_LOCATION veya ACCESS_FINE_LOCATION iznine sahip olduğundan emin olmak için kontrol eder. Aksi halde sistem SecurityException mesajını döndürür.

Bu nedenle, bir ön plan hizmetini başlatmadan önce gerekli ön koşulların karşılandığını onaylamanız gerekir. Ön plan hizmet türü belgelerinde, her ön plan hizmet türü için gerekli ön koşullar listelenmektedir.

Ön plan hizmeti başlatma

Sistemin bir hizmeti ön plan hizmeti olarak çalıştırmasını istemeden önce hizmetin kendisini başlatın:

Kotlin

val intent = Intent(...) // Build the intent for the service
context.startForegroundService(intent)

Java

Context context = getApplicationContext();
Intent intent = new Intent(...); // Build the intent for the service
context.startForegroundService(intent);

Hizmetin içinde (genellikle onStartCommand() konumunda) hizmetinizin ön planda çalışmasını isteyebilirsiniz. Bunu yapmak için ServiceCompat.startForeground() numaralı telefonu arayın (androidx-core 1.12 ve sonraki sürümlerde kullanılabilir). Bu yöntem aşağıdaki parametreleri alır:

  • Hizmet
  • Durum çubuğunda bildirimi benzersiz şekilde tanımlayan pozitif bir tam sayı
  • Notification nesnesinin kendisi
  • Hizmet tarafından yapılan işleri tanımlayan ön plan hizmeti türleri

Bu türler, belirli kullanım alanına bağlı olarak manifest'te belirtilen türlerin bir alt kümesi olabilir. Ardından, daha fazla hizmet türü eklemeniz gerekirse startForeground() yöntemini tekrar çağırabilirsiniz.

Örneğin, bir fitness uygulamasının, her zaman location bilgisine ihtiyacı olan, ancak medya oynatması gereken veya olmayan bir koşu takip hizmeti çalıştırdığını varsayalım. Manifest'te hem location hem de mediaPlayback öğesini beyan etmeniz gerekir. Bir kullanıcı koşu başlatırsa ve yalnızca konumunun izlenmesini isterse uygulamanız startForeground() yöntemini çağırmalı ve yalnızca ACCESS_FINE_LOCATION iznini iletmelidir. Ardından, kullanıcı ses çalmaya başlamak isterse startForeground() yöntemini tekrar çağırın ve tüm ön plan hizmet türlerinin bit tabanlı kombinasyonunu (bu örnekte ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK) iletin.

Burada, kamera ön plan hizmetini başlatan bir örnek verilmiştir:

Kotlin

class MyCameraService: Service() {

  private fun startForeground() {
    // Before starting the service as foreground check that the app has the
    // appropriate runtime permissions. In this case, verify that the user has
    // granted the CAMERA permission.
    val cameraPermission =
            ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
    if (cameraPermission == PackageManager.PERMISSION_DENIED) {
        // Without camera permissions the service cannot run in the foreground
        // Consider informing user or updating your app UI if visible.
        stopSelf()
        return
    }

    try {
        val notification = NotificationCompat.Builder(this, "CHANNEL_ID")
            // Create the notification to display while the service is running
            .build()
        ServiceCompat.startForeground(
            /* service = */ this,
            /* id = */ 100, // Cannot be 0
            /* notification = */ notification,
            /* foregroundServiceType = */
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA
            } else {
                0
            },
        )
    } catch (e: Exception) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
                && e is ForegroundServiceStartNotAllowedException) {
            // App not in a valid state to start foreground service
            // (e.g. started from bg)
        }
        // ...
    }
  }
}

Java

public class MyCameraService extends Service {

    private void startForeground() {
        // Before starting the service as foreground check that the app has the
        // appropriate runtime permissions. In this case, verify that the user
        // has granted the CAMERA permission.
        int cameraPermission =
            ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
        if (cameraPermission == PackageManager.PERMISSION_DENIED) {
            // Without camera permissions the service cannot run in the
            // foreground. Consider informing user or updating your app UI if
            // visible.
            stopSelf();
            return;
        }

        try {
            Notification notification =
                new NotificationCompat.Builder(this, "CHANNEL_ID")
                    // Create the notification to display while the service
                    // is running
                    .build();
            int type = 0;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                type = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
            }
            ServiceCompat.startForeground(
                    /* service = */ this,
                    /* id = */ 100, // Cannot be 0
                    /* notification = */ notification,
                    /* foregroundServiceType = */ type
            );
        } catch (Exception e) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S &&
                    e instanceof ForegroundServiceStartNotAllowedException
            ) {
                // App not in a valid state to start foreground service
                // (e.g started from bg)
            }
            // ...
        }
    }

    //...
}

Bir hizmeti ön plandan kaldırma

Hizmeti ön plandan kaldırmak için stopForeground() numaralı telefonu arayın. Bu yöntemde, durum çubuğu bildiriminin kaldırılıp kaldırılmayacağını belirten bir boole kullanılır. Hizmetin çalışmaya devam ettiğini unutmayın.

Ön planda çalışırken hizmeti durdurursanız hizmetin bildirimi kaldırılır.

Ön plan hizmetleri çalıştıran uygulamaların kullanıcı tarafından durdurulmasını ele alma

Bildirim çekmecesinin alt kısmında, arka planda çalışan uygulamaların sayısını gösteren bir düğme bulunur. Bu düğmeye bastığınızda farklı uygulamaların adlarını listeleyen bir iletişim kutusu görüntülenir. Durdur düğmesi, her uygulamanın sağındadır
Şekil 1. Android 13 veya sonraki sürümleri çalıştıran cihazlarda Görev Yöneticisi iş akışı.

Android 13'ten (API düzeyi 33) itibaren, kullanıcılar devam eden ön plan hizmetleri olan bir uygulamayı durdurmak için uygulamanın hedef SDK sürümünden bağımsız olarak, bildirim çekmecesinden bir iş akışını tamamlayabilirler. Görev Yöneticisi adı verilen bu olanak, şu anda bir ön plan hizmetini çalıştırmakta olan uygulamaların listesini gösterir.

Bu liste Etkin uygulamalar olarak etiketlenir. Her uygulamanın yanında bir Durdur düğmesi bulunur. Şekil 1'de Android 13 çalıştıran bir cihazdaki Görev Yöneticisi iş akışı gösterilmektedir.

Kullanıcı, Görev Yöneticisi'nde uygulamanızın yanındaki Durdur düğmesine bastığında aşağıdaki işlemler gerçekleşir:

  • Sistem, uygulamanızı bellekten kaldırır. Dolayısıyla, yalnızca ön plan hizmeti değil, uygulamanızın tamamı durur.
  • Sistem, uygulamanızın etkinlik geri yığınını kaldırır.
  • Medya oynatma işlemi durur.
  • Ön plan hizmetiyle ilişkili bildirim kaldırılır.
  • Uygulamanız geçmişte kalır.
  • Planlanmış görevler, planlanan zamanda yürütülür.
  • Alarmlar programlanan zamanda veya zaman aralığında çalar.

Kullanıcı uygulamanızı durdurduğunda ve durdurduktan sonra uygulamanızın beklendiği gibi davranıp davranmadığını test etmek için bir terminal penceresinde aşağıdaki ADB komutunu çalıştırın:

adb shell cmd activity stop-app PACKAGE_NAME

Muafiyetler

Sistem, belirli uygulama türleri için çeşitli muafiyet düzeyleri sağlar. Bunlar, aşağıdaki bölümlerde açıklanmıştır.

Muafiyetler işlem başına değil, uygulama başına yapılır. Sistem, bir uygulamadaki bir işlemi muaf tutarsa bu uygulamadaki diğer tüm işlemler de muaf olur.

Görev Yöneticisi'nde görüntülenmeyecek muaf tutmalar

Aşağıdaki uygulamalar bir ön plan hizmetini çalıştırabilir ve Görev Yöneticisi'nde hiç görünmeyebilir:

Kullanıcıların durdurulabilirliğinden muaf tutma

Aşağıdaki türlerde uygulamalar ön plan hizmeti çalıştırdığında, bu uygulamalar Görev Yöneticisi'nde görünür, ancak kullanıcının dokunması için uygulama adının yanında Durdur düğmesi yoktur:

Ön plan hizmetleri yerine amaca yönelik API'ler kullanın

Çoğu kullanım alanında, ön plan hizmetini kullanmak için kullanabileceğiniz platform veya Jetpack API'leri mevcuttur. Amaca yönelik uygun bir API varsa bir ön plan hizmeti yerine neredeyse her zaman onu kullanmalısınız. Amaca özel API'ler genellikle, normalde kendi başınıza oluşturmanız gereken kullanım alanına özel ek yetenekler sağlar. Örneğin Bubbles API, sohbet balonu özelliklerini uygulaması gereken mesajlaşma uygulamalarına yönelik karmaşık kullanıcı arayüzü mantığını işler.

Ön plan hizmet türleri belgelerinde, ön plan hizmetleri yerine kullanılabilecek iyi alternatifler listelenmiştir.

Arka plandan ön plan hizmeti başlatmayla ilgili kısıtlamalar

Android 12 veya sonraki sürümleri hedefleyen uygulamalar, birkaç özel durum dışında arka planda çalışırken ön plan hizmetlerini başlatamaz. Bir uygulama, arka planda çalışırken bir ön plan hizmeti başlatmaya çalışırsa ve ön plan hizmeti istisnai durumlardan birini karşılayamazsa sistem bir ForegroundServiceStartNotAllowedException gönderir.

Ayrıca bir uygulama, kullanım sırasında izinlerine (örneğin, vücut sensörü, kamera, mikrofon veya konum izinleri) ihtiyaç duyan bir ön plan hizmetini başlatmak istiyorsa uygulama arka planda başlatma kısıtlamalarının muafiyetlerinden birine dahil olsa bile, hizmeti oluşturamaz. Bunun nedeni, Kullanım sırasında izin verilmesi gereken ön plan hizmetlerini başlatmayla ilgili kısıtlamalar bölümünde açıklanmıştır.

Arka planda başlatma kısıtlamalarından muaf tutma

Aşağıdaki durumlarda uygulamanız arka planda çalışırken bile ön plan hizmetlerini başlatabilir:

Kullanım sırasında izin gerektiren ön plan hizmetlerinin başlatılmasıyla ilgili kısıtlamalar

Android 14 (API düzeyi 34) veya sonraki sürümlerde, kullanım sırasında izin gerektiren bir ön plan hizmeti başlatırken dikkat etmeniz gereken özel durumlar vardır.

Uygulamanız Android 14 veya sonraki bir sürümü hedefliyorsa işletim sistemi, bir ön plan hizmeti oluşturduğunuzda uygulamanızın bu hizmet türü için uygun tüm izinlere sahip olduğundan emin olmak amacıyla kontrol eder. Örneğin, mikrofon türünde bir ön plan hizmeti oluşturduğunuzda işletim sistemi uygulamanızın şu anda RECORD_AUDIO iznine sahip olduğunu doğrular. Bu izne sahip değilseniz sistem bir SecurityException gönderir.

Kullanımdaki izinler için bu durum potansiyel bir soruna neden olur. Uygulamanızın kullanım sırasında izni varsa bu izni yalnızca ön plandayken alabilir. Diğer bir deyişle, uygulamanız arka plandaysa ve kamera, konum veya mikrofon türünde bir ön plan hizmeti oluşturmaya çalışırsa sistem, uygulamanızın şu anda gerekli izinlere sahip olmadığını tespit eder ve bir SecurityException gönderir.

Benzer şekilde, uygulamanız arka planda çalışıyorsa ve BODY_SENSORS_BACKGROUND iznini gerektiren bir sağlık hizmeti oluşturuyorsa uygulama şu anda bu izne sahip değildir ve sistem bir istisna uygular. (ACTIVITY_RECOGNITION gibi farklı izinlere ihtiyacı olan bir sağlık hizmeti söz konusuysa bu durum geçerli değildir.) ContextCompat.checkSelfPermission() yöntemini çağırmak bu sorunu önlemez. Uygulamanızın kullanım sırasında izni varsa ve bu izne sahip olup olmadığını kontrol etmek için checkSelfPermission() yöntemini çağırırsa yöntem, uygulama arka planda olsa bile PERMISSION_GRANTED değerini döndürür. Yöntem PERMISSION_GRANTED değerini döndürdüğünde, "uygulama kullanımdayken uygulamanız bu izne sahip olur" ifadesini içerir.

Bu nedenle, ön plan hizmetiniz kullanım sırasında izne ihtiyaç duyuyorsa hizmet tanımlanmış muafiyetlerden birine girmiyorsa uygulamanızın görünür bir etkinliği varken Context.startForegroundService() veya Context.bindService() çağırmanız gerekir.

Kullanımdaki izinlerle ilgili kısıtlamalardan muaf tutma

Bazı durumlarda, bir ön plan hizmeti arka planda çalışırken başlatılsa bile, uygulama ön planda çalışırken ("kullanımdayken") konum, kamera ve mikrofon bilgilerine erişmeye devam edebilir.

Aynı durumlarda, hizmet ön plan hizmeti türünü location olarak beyan ederse ve ACCESS_BACKGROUND_LOCATION iznine sahip bir uygulama tarafından başlatılırsa bu hizmet, uygulama arka planda çalışsa bile konum bilgilerine her zaman erişebilir.

Aşağıdaki listede şu durumlar yer almaktadır:

  • Bir sistem bileşeni hizmeti başlatır.
  • Hizmet, uygulama widget'larıyla etkileşimde bulunarak başlar.
  • Hizmet, bir bildirimle etkileşimde bulunarak başlar.
  • Hizmet, farklı ve görünür bir uygulamadan gönderilen PendingIntent ile başlar.
  • Hizmet, cihaz sahibi modunda çalışan bir cihaz politikası denetleyici uygulama tarafından başlatılır.
  • Hizmet, VoiceInteractionService bilgisini sağlayan bir uygulama tarafından başlatılır.
  • Hizmet, START_ACTIVITIES_FROM_BACKGROUND ayrıcalıklı izne sahip bir uygulama tarafından başlatılır.
Uygulamanızda hangi hizmetlerin etkilendiğini belirleme

Uygulamanızı test ederken ön plan hizmetlerini başlatın. Başlatılan bir hizmet konum, mikrofon ve kameraya erişimi kısıtladıysa Logcat'te aşağıdaki mesaj görünür:

Foreground service started from background can not have \
location/camera/microphone access: service SERVICE_NAME