Ö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 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 geçerli fitness oturumu sırasında katettiği mesafe gösterilebilir.

Ön plan hizmetlerini yalnızca uygulamanızın, uygulamayla doğrudan etkileşimde bulunmadıkları durumlarda bile kullanıcının fark edebileceği bir görevi gerçekleştirmesi gerektiğinde kullanın. İşlem, minimum öncelikli bildirim kullanmak istediğiniz kadar önemli değilse bunun yerine bir arka plan görevi oluşturun.

Bu dokümanda, ön plan hizmetlerini kullanmak için gerekli izin 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ı da 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. Normalde, ö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 ile 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 eder ancak bildirim çekmecesinde görmez.

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 hizmette hizmetin ne tür bir iş yaptığını belirtmek için bir android:foregroundServiceType özelliği kullanın.

Örneğin, uygulamanız müzik çalan bir ön plan hizmeti oluşturuyorsa bu 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 birden çok tür varsa bunları | operatörüyle ayırın. Örneğin, kamera ve mikrofonu kullanan bir hizmet bunu şu şekilde tanımlar:

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 iznini istemesi gerekir. Bu normal bir izin olduğundan sistem, izni isteyen uygulamaya otomatik olarak izni verir.

Buna ek olarak, 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ü, karşılık gelen bir izin türüne sahiptir. Ö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 listelenmeleri halinde 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 ACCESS_COARSE_LOCATION veya ACCESS_FINE_LOCATION iznine sahip olup olmadığını kontrol eder. Aksi takdirde sistem SecurityException mesajını atar.

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 listelenmiştir.

Ö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çinden (genellikle onStartCommand() konumunda) hizmetinizin ön planda çalışmasını isteyebilirsiniz. Bunun 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 hizmet türleri

Bu türler, belirli kullanım alanına bağlı olarak manifest'te tanımlanan türlerin bir alt kümesi olabilir. Ardından, daha fazla hizmet türü eklemeniz gerekirse startForeground() hizmetini 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 takibi hizmeti çalıştırdığını varsayalım. Manifest'te hem location hem de mediaPlayback değerlerini bildirmeniz 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() işlevini tekrar çağırın ve tüm ön plan hizmet türlerinin (bu örnekte ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK) bit tabanlı kombinasyonunu iletin.

Burada, kamera ön plan hizmetinin kullanıma sunulduğu 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öntem, durum çubuğu bildiriminin de kaldırılıp kaldırılmayacağını belirten bir boole alır. Hizmetin çalışmaya devam ettiğini unutmayın.

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

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

Bildirim çekmecesinin alt kısmında, arka planda çalışmakta olan uygulamaların sayısını belirten bir düğme bulunur. Bu düğmeye bastığınızda farklı uygulamaların adlarını listeleyen bir iletişim kutusu görünür. Her uygulamanın sağında Durdur düğmesi bulunur
Ş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 iş akışını tamamlayabilirler. Görev Yöneticisi adı verilen bu olanak, o 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, yalnızca çalışan ön plan hizmeti değil, uygulamanızın tamamı durur.
  • Sistem, uygulamanızın etkinlik geri yığınını kaldırır.
  • Medya oynatması durur.
  • Ön plan hizmetiyle ilişkili bildirim kaldırılır.
  • Uygulamanız geçmişte kalır.
  • Planlanmış işler planlanan zamanda yürütülür.
  • Alarmlar planlanan zamanda veya zaman aralığında çalar.

Kullanıcı uygulamanızı durdurduğunda ve durdurduktan sonra uygulamanızın beklendiği gibi davrandığı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 aşağıdaki bölümlerde açıklanan çeşitli muafiyet düzeyleri sağlar.

Muafiyetler işlem başına değil, uygulama başına yapılır. 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ülenmeyecek muafiyetler

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

Kullanıcıların durdurulabileceği muafiyetler

Aşağıdaki türlerdeki uygulamalar bir ö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 bulunmaz:

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

Birçok kullanım alanında, çalışmak için kullanabileceğiniz platform veya Jetpack API'leri vardır. Aksi takdirde bu API'ler için bir ön plan hizmeti kullanabilirsiniz. Amaca yönelik uygun bir API varsa ön plan hizmeti yerine neredeyse her zaman bunu kullanmanız gerekir. Amaca yönelik API'ler genellikle, kullanım alanına özel, aksi halde kendi başınıza derlemeniz gereken ek yetenekler sağlar. Örneğin Bubbles API, sohbet balonu özelliklerini uygulaması gereken mesajlaşma uygulamaları için karmaşık kullanıcı arayüzü mantığını ele alır.

Ö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 haricinde 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şılamıyorsa 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 hizmeti başlatmak istiyorsa uygulama arka plandayken hizmeti oluşturamaz (uygulama arka planda başlatma kısıtlamalarının istisnalarından birine dahil olsa bile). Bunun nedeni, Kullanım sırasında izinlere ihtiyaç duyulan ö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 hizmetlerini başlatmayla ilgili kısıtlamalar

Android 14 (API düzeyi 34) veya sonraki sürümlerde, kullanım sırasındaki izinleri gerektiren bir ön plan hizmeti başlatırsanız dikkate alınması 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 bir soruna neden olabilir. Uygulamanızın kullanım sırasındaki bir izni varsa yalnızca ön plandayken bu izne 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 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 oluşturur. (ACTIVITY_RECOGNITION gibi farklı izinlere ihtiyacı olan bir sağlık hizmetiyse bu geçerli değildir.) ContextCompat.checkSelfPermission() işlevini çağırmak bu sorunu engellemez. Uygulamanızın kullanım sırasındaki bir izni varsa ve bu izne sahip olup olmadığını kontrol etmek için checkSelfPermission() yöntemini çağırırsa uygulama arka planda olsa bile yöntem PERMISSION_GRANTED değerini döndürür. Yöntem PERMISSION_GRANTED değerini döndürdüğünde "uygulama kullanılırken uygulamanız bu izne sahip" ifadesini içerir.

Bu nedenle, ön plan hizmetinizin kullanım sırasındaki izni gerekiyorsa uygulamanızın görünür bir etkinliği varken hizmet tanımlanmış muafiyetler kapsamında değilse Context.startForegroundService() veya Context.bindService() çağırmanız gerekir.

Kullanım sırasında izinlerle ilgili kısıtlamalardan muafiyetler

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

Aynı durumlarda, ön plan hizmet türü location olarak beyan edilen ve ACCESS_BACKGROUND_LOCATION iznine sahip bir uygulama tarafından başlatılan hizmet, 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 bir 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 tarafından başlatılır.
  • Hizmet, START_ACTIVITIES_FROM_BACKGROUND ayrıcalıklı iznine 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 hizmetin 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