Ö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ı belirtmek için durum çubuğu bildirimi gösterir.

Ön plan hizmetlerini kullanan uygulamalara örnek olarak aşağıdakiler 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, mevcut fitness oturumu sırasında kullanıcının katettiği mesafe gösterilebilir.

Uygulamanızın, kullanıcı tarafından fark edilebilecek bir işlemi gerçekleştirmesi gerektiğinde (uygulamayla doğrudan etkileşimde bulunmadığında bile) yalnızca ön plan hizmetini kullanın. İşlemin önem düzeyi, minimum öncelikli bildirim kullanmanızı gerektirecek kadar düşükse bunun yerine bir arka plan görevi oluşturun.

Bu belgede, ön plan hizmetlerinin kullanımı için gereken izin ve bir ön plan hizmetinin başlatılıp arka plandan nasıl 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ı da açıklanmaktadır.

Kullanıcı bildirimi varsayılan olarak 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 bunu yapmak için bildirimde kaydırma hareketi yapar. Geleneksel olarak, ön plan hizmeti durdurulmadığı veya ön plandan kaldırılmadığı sürece bildirim kapatılmaz.

Bildirimin kullanıcı tarafından kapatılamayacağını istiyorsanız bildiriminizi Notification.Builder ile oluştururken setOngoing() yöntemine true ekleyin.

Hemen bildirim gösteren hizmetler

Bir ön plan hizmeti aşağıdaki özelliklerden en az birine sahipse sistem, ilişkili bildirimi Android 12 veya sonraki sürümleri çalıştıran cihazlarda bile hizmet başlatıldıktan hemen sonra 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 bildirimler görmeye devam eder ancak bunları bildirim çekmecesinde görmez.

Manifest'inizde ön plan hizmetlerini beyan edin

Uygulamanızın manifest dosyasında, uygulamanızın ön plan hizmetlerinin her birini <service> öğesi ile tanımlayın. Her hizmet için hizmetin ne tür bir çalışma yaptığını belirtmek üzere bir android:foregroundServiceType özelliği kullanın.

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

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

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

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

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 manifestinde FOREGROUND_SERVICE isteğinde bulunması gerekir. Bu normal bir izin olduğundan sistem, izni istekte bulunan uygulamaya otomatik olarak verir.

Ayrıca, API düzeyi 34 veya sonraki sürümleri hedefleyen uygulamalar, ön plan hizmetinin yapacağı çalışma için uygun izin türünü istemelidir. Her ön plan hizmet türünün karşılık gelen 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ğundan, manifest dosyasında listelenirlerse 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 kullanıma sunduğunuzda 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 olup olmadığını kontrol eder. Bağlanmıyorsa sistem SecurityException komutunu atar.

Bu nedenle, ö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 listelenir.

Ön plan hizmeti başlatma

Sistemden bir hizmeti ön plan hizmeti olarak çalıştırmasını istemeden önce hizmeti 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()) hizmetinizin ön planda çalışmasını isteyebilirsiniz. Bunu yapmak için ServiceCompat.startForeground() (androidxcore 1.12 ve sonraki sürümlerde mevcuttur) numaralı telefonu arayın. Bu yöntem aşağıdaki parametreleri alır:

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

Bu türler, belirli kullanım alanına bağlı olarak manifest dosyasında tanımlanan türlerin alt kümesi olabilir. Sonra, daha fazla hizmet türü eklemeniz gerekirse startForeground() hizmetini tekrar çağırabilirsiniz.

Örneğin, bir fitness uygulamasının her zaman location bilgisine ihtiyaç duyan ancak medya oynatması gerekebilecek ya da gerekmeyebilecek bir koşu takip aracı 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 sadece konumunun izlenmesini isterse uygulamanız startForeground() işlevini ç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.

Aşağıda, bir kamera ön plan hizmetini başlatan bir örnek gösterilmektedir:

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 =
            PermissionChecker.checkSelfPermission(this, Manifest.permission.CAMERA)
    if (cameraPermission != PermissionChecker.PERMISSION_GRANTED) {
        // 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() yöntemini çağırın. Bu yöntem, durum çubuğu bildiriminin de kaldırılıp kaldırılmayacağını belirten bir boole değeri alır. Hizmetin çalışmaya devam ettiğini unutmayın.

Hizmeti ön planda çalışırken durdurursanız bildirimi kaldırılır.

Ön plan hizmetlerini çalıştıran uygulamaların kullanıcı tarafından başlatılan durdurulmasını yönetme

Bildirim çekmecesinin alt kısmında, arka planda o anda çalışan uygulamaların sayısını gösteren bir düğme bulunur. Bu düğmeye bastığınızda, farklı uygulamaların adlarının listelendiği bir iletişim kutusu görünür. 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ü ne olursa olsun bildirim çekmecesinden bir iş akışı tamamlayabilir. Görev Yöneticisi adı verilen bu olanak, şu anda bir ön plan hizmeti çalıştıran 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. Bu nedenle, sadece çalışan ön plan hizmeti değil, uygulamanızın tamamı durdurulur.
  • Sistem, uygulamanızın etkinlik geri yığınını kaldırır.
  • Her medya oynatma işlemi durur.
  • Ön plan hizmetiyle ilişkili bildirim kaldırılır.
  • Uygulamanız geçmişte gösterilmeye devam ediyor.
  • Planlanan işler, programlanan zamanda yürütülür.
  • Alarmlar programlanan zamanda veya zaman aralığında çalar.

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

adb shell cmd activity stop-app PACKAGE_NAME

Muafiyetler

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

Muafiyetler işlem başına değil, uygulama başına geçerlidir. Sistem, bir uygulamadaki bir işlemi muaf tutarsa söz konusu uygulamadaki diğer tüm işlemler de muaf olur.

Görev Yöneticisi'nde görüntülenmekten hiç muaf tutma

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

Kullanıcıların durdurmasına engel olan muafiyetler

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

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

Birçok kullanım alanında, başka bir durumda ön plan hizmetini kullanabileceğiniz platform veya Jetpack API'leri ile işlerinizi halledebilirsiniz. Amaca yönelik uygun bir API varsa neredeyse her zaman ön plan hizmeti yerine onu kullanmanız gerekir. Amaca yönelik API'ler genellikle, normalde kendi başınıza geliştirmeniz gerekebilecek, kullanım alanına özgü ek özellikler sağlar. Örneğin, Bubbles API, sohbet balonu özelliklerini uygulaması gereken mesajlaşma uygulamaları için karmaşık kullanıcı arayüzü mantığını işler.

Ön plan hizmeti türleriyle ilgili belgeler, ön plan hizmetleri yerine kullanılabilecek iyi alternatifleri listeler.

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

Android 12 veya sonraki sürümleri hedefleyen uygulamalar, birkaç özel durum dışında, uygulama 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şılamazsa sistem bir ForegroundServiceStartNotAllowedException atar.

Ayrıca bir uygulama, kullanımdayken izinlere (ör. vücut sensörü, kamera, mikrofon veya konum izinleri) ihtiyaç duyan bir ön plan hizmetini başlatmak istiyorsa arka planda başlatma kısıtlamalarından muaf olunsa bile uygulama arka plandayken hizmeti oluşturamaz. Bu durumun nedeni, Kullanım sırasında izin gerektiren ön plan hizmetlerinin başlatılmasıyla ilgili kısıtlamalar bölümünde açıklanmıştır.

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

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ıyorsanız dikkat etmeniz gereken özel durumlar vardır.

Uygulamanız Android 14 veya sonraki sürümleri hedefliyorsa işletim sistemi, bir ön plan hizmeti oluşturduğunuzda uygulamanızın bu hizmet türü için tüm uygun izinlere sahip olduğunu kontrol eder. Örneğin, microphone 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 izniniz yoksa sistem bir SecurityException atar.

Bu durum, kullanımdaki izinler için olası bir soruna neden olur. Uygulamanızın kullanım sırasında izni varsa bu izne yalnızca ön plandayken sahip olur. Yani 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ı görür ve SecurityException verir.

Benzer şekilde, uygulamanız arka plandaysa ve BODY_SENSORS_BACKGROUND iznine ihtiyaç duyan 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 ihtiyaç duyan bir sağlık hizmeti söz konusuysa bu geçerli değildir.) PermissionChecker.checkSelfPermission() çağrısının yapılması 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ıyorsa uygulama arka planda olsa bile bu yöntem 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" demektir.

Bu nedenle, ön plan hizmetinizin kullanım sırasında izin alması gerekiyorsa uygulamanızın görünür bir etkinliği varken hizmet tanımlanan muafiyetlerden birine tabi değilse Context.startForegroundService() veya Context.bindService() kodunu çağırmanız gerekir.

Kullanımdayken izinlerle ilgili kısıtlamalardan muaflar

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

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

Aşağıdaki listede bu durumlar yer alır:

  • Hizmeti bir sistem bileşeni 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 olarak başlar.
  • Hizmet, cihaz sahibi modunda çalışan bir cihaz politikası denetleyici olan uygulama tarafından başlatılır.
  • Hizmet, VoiceInteractionService sağlayan bir uygulama ile başlar.
  • Hizmet, START_ACTIVITIES_FROM_BACKGROUND ayrıcalıklı izne sahip bir uygulama tarafından başlar.
Uygulamanızda hangi hizmetlerin etkilendiğini belirleyin

Uygulamanızı test ederken ön plan hizmetlerini başlatın. Başlatılan bir hizmet konum, mikrofon ve kamera erişimini kısıtlamışsa 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