Sınır hizmetlerine genel bakış

Bağlı hizmet, istemci-sunucu arayüzündeki sunucudur. Bileşenlerin hizmete bağlanması, istek gönderme, yanıt alma ve performansın işlemler arası iletişim (IPC) Bağlı bir hizmet genellikle yalnızca başka bir kullanıcıya hizmet verirken çalışır uygulama bileşenine sahiptir ve arka planda süresiz olarak çalışmaz.

Bu dokümanda, bağlama ve bağlı hizmet oluşturma hakkında bilgi verilmektedir. diğer uygulama bileşenlerinden hizmete geçiyor. Aşağıdaki hizmetler hakkında daha fazla bilgi edinmek için: Örneğin, bir hizmetten bildirim gönderme ve hizmeti çalışacak şekilde ayarlama ön planda çalışıyorsa, şuraya bakın: Hizmetlere genel bakış.

Temel bilgiler

Bağlı hizmet, Service sınıfının bir uygulamasıdır ve diğer uygulamalar da bu modele bağlı kalarak onunla etkileşimde bulunur. Bir hizmeti için onBind() geri çağırma yöntemini uygularsınız. Bu yöntem, kullanılan programlama arayüzünü tanımlayan bir IBinder nesnesi kullanabileceği bazı araçlar da vardır.

Başlatılan bir hizmete bağlan

Hizmetlere genel bakış bölümünde açıklandığı gibi, hem başlamış hem de bağlı bir hizmet oluşturabilirsiniz. Yani, Arkadaş Bitkiler projesinin hizmeti başlatan startService(). Bu çağrı, süresiz olarak çalışmasını sağlar. Ayrıca, bir istemcinin hizmete bağlanmasını sağlamak için bindService() aranıyor.

Hizmetinizin başlatılmasına ve bağlanmasına izin verirseniz hizmet başladığında Sistem, tüm istemcilerin bağlantısını kaldırdığında hizmeti kaldırmaz. Bunun yerine stopSelf() veya stopService() numaralı telefonu çağırarak hizmeti açıkça durdurmanız gerekir.

Genellikle onBind() veya onStartCommand(), bazen gerekli olan uygulayabilirsiniz. Örneğin, bir müzik çalar, verdiği hizmetin çalışması için uygulamayı faydalı bulabilir. süresiz olarak sağlar ve bağlayıcılığı da sağlar. Bu şekilde, bir etkinlik biraz daha oynayabilmek için ve kullanıcı uygulamadan ayrılsa bile müzik çalmaya devam eder. Ardından, kullanıcı uygulamaya döndüğünde ise etkinlik, kontrolün sizde olmasını sağlamak için oynatmaya devam edebilirsiniz.

Başlatılan bir hizmete bağlama eklerken hizmet yaşam döngüsü hakkında daha fazla bilgi edinmek için Bağlı bir hizmetin yaşam döngüsünü yönetme bölümüne bakın.

İstemci, çağırarak bir hizmete bağlanır bindService() Bu durumda, ServiceConnection bir uygulama sağlar. hizmetle olan bağlantıyı izler. Döndürülen değer bindService(), ve istemcinin bu hizmete erişim izni verilip verilmediğini gösterir.

Zaman Android sistemi, istemci ile hizmet arasında bağlantı oluşturur. şunu arar: onServiceConnected() ServiceConnection üzerinde. İlgili içeriği oluşturmak için kullanılan onServiceConnected() yöntemi bir IBinder içeriyor bağımsız değişkeni oluşturur.

Bir hizmete aynı anda birden çok istemci bağlayabilirsiniz. Ancak sistem, IBinder hizmeti iletişim kanalını önbelleğe alır. Başka bir deyişle, sistem, hizmetin onBind() öğesini çağırır. yöntemini kullanarak IBinder özelliğini yalnızca ilk kullanır. Daha sonra sistem aynı IBinder öğesini arama yapmadan aynı hizmete bağlanan tüm ek istemcileri. tekrar onBind().

Son istemcinin hizmet ile olan bağlantısını kestiğinde, hizmeti startService() kullanılarak başlatıldı.

Bağlı hizmet uygulamanızın en önemli kısmı, onBind() geri çağırma yönteminizin döndürdüğü sonuçlardır. Aşağıdakiler Bu bölümde, hizmet kalitenizi tanımlamanın IBinder arayüzü.

Bağlı hizmet oluştur

Bağlama sağlayan bir hizmet oluştururken IBinder sağlamanız gerekir müşterilerin hizmetle etkileşime girmek için kullanabileceği programlama arayüzünü sağlar. Orada arayüzü üç farklı şekilde tanımlayabilirsiniz:

Bağlayıcı sınıfını genişletme
Hizmetiniz kendi uygulamanıza özelse ve aynı süreçte çalışıyorsa (genellikle Binder) uzantısını genişleterek arayüzünüzü oluşturun. sınıf bunun bir örneğini şuradan döndürebilir: onBind(). Müşteri, Binder ve Binder uygulamasında bulunan herkese açık yöntemlere doğrudan erişmek için bunu kullanabilir. veya Service.

Hizmetiniz yalnızca kendi şirketiniz için arka plan çalışanıysa tercih ettiğiniz teknik budur. bir uygulamadır. Arayüzünüzü oluşturmak için tercih edilen yöntemin bu olmadığı durumlarda, tek kullanım alanı ve farklı işlemlerde kullanılıp kullanılmadığını gösterir.

Messenger'ı kullanma
Arayüzünüzün farklı süreçlerde çalışması gerekiyorsa Messenger içeren hizmet arayüzü. Bu şekilde, hizmet farklı Message nesne türlerine yanıt veren bir Handler tanımlar.

Bu Handler daha sonra IBinder paylaşabilecek bir Messenger için temel oluşturur Böylece istemcinin Message nesneleri kullanarak hizmete komutlar göndermesini sağlayabilirsiniz. Buna ek olarak, müşteri bir Messenger tanımlayabilir gönderebilir, böylece hizmet iletileri geri gönderebilir.

Bu, işlemler arası iletişimi (IPC) gerçekleştirmenin en basit yoludur çünkü Messenger tüm istekleri tek bir iş parçacığında sıraya alır ve böylece sizin tasarım yapmanız gerekmez. güvenli olmasını sağlar.

AIDL'yi kullanma
Android Arayüz Tanımlama Dili (AIDL), nesneleri aşağıdaki parçalara ayırır: işletim sisteminin anlayabileceği ve bunları işlem süreçlerinde IPC ile uyumludur. Messenger kullanan önceki teknik, aslında olduğunu göreceksiniz.

Önceki bölümde belirtildiği gibi, Messenger, bir satır öğesi tüm istemci isteklerini tek bir iş parçacığında toplar. Bu nedenle hizmet, istekleri teker teker alır. Eğer, ancak hizmetinizin aynı anda birden fazla isteği işlemesini istiyorsanız AIDL'yi kullanabilirsiniz. doğrudan ekleyebilirsiniz. Bu durumda, hizmetiniz iş parçacığı açısından güvenli ve çoklu iş parçacıkları oluşturabilir.

AIDL'yi doğrudan kullanmak için programlama arayüzünü tanımlayan bir .aidl dosyası oluşturun. Android SDK araçları, arayüzü uygulayan ve IPC'yi işleyen soyut bir sınıf oluşturmak için bu dosyayı hizmetiniz kapsamında genişletilebilir.

Not: AIDL, çoğu uygulama için en iyi seçenek değildir. bağlı hizmet oluşturabilirsiniz çünkü çoklu iş parçacığı özellikleri ve uygulama daha karmaşık bir hale gelebilir. Dolayısıyla bu belgede hizmetiniz için kullanmak. Bir projeyi tamamlamak için doğrudan AIDL kullanmak için AIDL'ye bakın uygulayacaksınız.

Bağlayıcı sınıfını genişletme

Hizmetinizi yalnızca yerel uygulama kullanıyorsa ve şunu yapması gerekmiyorsa: farklı süreçlerde müşterilerinize doğrudan erişim sağlayan kendi Binder sınıfınızı hizmette herkese açık yöntemlere erişim.

Not: Bu yalnızca istemci ve hizmet aynıysa çalışır uygulama ve işlem süreçlerine odaklanıyoruz. Örneğin bu, bir müzik türü için müzik çalan kendi hizmetine bir etkinlik bağlamasını gerektiren arka plan.

Bunu nasıl kuracağınız aşağıda açıklanmıştır:

  1. Hizmetinizde, şunu yapan bir Binder örneği oluşturun: şunlardan biri:
    • İstemcinin çağırabileceği herkese açık yöntemleri içerir.
    • Herkese açık yöntemleri olan geçerli Service örneğini döndürür: telefon edebilir.
    • Hizmet tarafından barındırılan ve herkese açık yöntemlere sahip başka bir sınıfın bir örneğini döndürür: telefon edebilir.
  2. onBind() geri çağırma yönteminden bu Binder örneğini döndürün.
  3. İstemcide, onServiceConnected() geri çağırma yönteminden Binder değerini alın ve verilen yöntemleri kullanarak bağlı hizmete çağrı yapın.

Not: Hizmet ve istemci aynı olmalıdır istemcinin döndürülen nesneyi yayınlayabilmesi ve API'lerini düzgün bir şekilde çağırabilmesi için uygulamanız gerekir. Hizmet Ayrıca müşteri de aynı süreçte olmalıdır çünkü bu teknik, nasıl işlediğini tartıştık.

Örneğin, müşterilere hizmetteki yöntemlere Binder uygulaması:

Kotlin

class LocalService : Service() {
    // Binder given to clients.
    private val binder = LocalBinder()

    // Random number generator.
    private val mGenerator = Random()

    /** Method for clients.  */
    val randomNumber: Int
        get() = mGenerator.nextInt(100)

    /**
     * Class used for the client Binder. Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
    inner class LocalBinder : Binder() {
        // Return this instance of LocalService so clients can call public methods.
        fun getService(): LocalService = this@LocalService
    }

    override fun onBind(intent: Intent): IBinder {
        return binder
    }
}

Java

public class LocalService extends Service {
    // Binder given to clients.
    private final IBinder binder = new LocalBinder();
    // Random number generator.
    private final Random mGenerator = new Random();

    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
    public class LocalBinder extends Binder {
        LocalService getService() {
            // Return this instance of LocalService so clients can call public methods.
            return LocalService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    /** Method for clients. */
    public int getRandomNumber() {
      return mGenerator.nextInt(100);
    }
}

LocalBinder, istemcilerin getService() LocalService örneği. Bu, müşterilerin geliştirmenizi sağlar. Örneğin, müşteriler hizmetten getRandomNumber() numarasını arayabilir.

İşte LocalService ile bağlantı kuran ve getRandomNumber() çağrısı yapan bir etkinlik bir düğme tıklandığında:

Kotlin

class BindingActivity : Activity() {
    private lateinit var mService: LocalService
    private var mBound: Boolean = false

    /** Defines callbacks for service binding, passed to bindService().  */
    private val connection = object : ServiceConnection {

        override fun onServiceConnected(className: ComponentName, service: IBinder) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance.
            val binder = service as LocalService.LocalBinder
            mService = binder.getService()
            mBound = true
        }

        override fun onServiceDisconnected(arg0: ComponentName) {
            mBound = false
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)
    }

    override fun onStart() {
        super.onStart()
        // Bind to LocalService.
        Intent(this, LocalService::class.java).also { intent ->
            bindService(intent, connection, Context.BIND_AUTO_CREATE)
        }
    }

    override fun onStop() {
        super.onStop()
        unbindService(connection)
        mBound = false
    }

    /** Called when a button is clicked (the button in the layout file attaches to
     * this method with the android:onClick attribute).  */
    fun onButtonClick(v: View) {
        if (mBound) {
            // Call a method from the LocalService.
            // However, if this call is something that might hang, then put this request
            // in a separate thread to avoid slowing down the activity performance.
            val num: Int = mService.randomNumber
            Toast.makeText(this, "number: $num", Toast.LENGTH_SHORT).show()
        }
    }
}

Java

public class BindingActivity extends Activity {
    LocalService mService;
    boolean mBound = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    protected void onStart() {
        super.onStart();
        // Bind to LocalService.
        Intent intent = new Intent(this, LocalService.class);
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        unbindService(connection);
        mBound = false;
    }

    /** Called when a button is clicked (the button in the layout file attaches to
      * this method with the android:onClick attribute). */
    public void onButtonClick(View v) {
        if (mBound) {
            // Call a method from the LocalService.
            // However, if this call is something that might hang, then put this request
            // in a separate thread to avoid slowing down the activity performance.
            int num = mService.getRandomNumber();
            Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
        }
    }

    /** Defines callbacks for service binding, passed to bindService(). */
    private ServiceConnection connection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,
                IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance.
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };
}

Yukarıdaki örnek, istemcinin ServiceConnection ve onServiceConnected() geri araması. Sonraki bölümü, hizmete bu bağlama süreci hakkında daha fazla bilgi sağlar.

Not: Yukarıdaki örnekte, onStop() yöntemi, istemci ile hizmet arasındaki bağlantıyı kaldırır. Ek notlar bölümü.

Daha fazla örnek kod için LocalService.java sınıfı ve ApiDemos'ta LocalServiceActivities.java sınıfı.

Messenger'ı kullanma

Hizmetinize, uzak işlemlerle iletişim kurmak için ihtiyaç duyuyorsanız Messenger, hizmetinize arayüz sağlar. Bu teknik, AIDL kullanmaya gerek kalmadan işlemler arası iletişim (IPC) gerçekleştiriyorsanız.

Arayüzünüz için Messenger kullanma AIDL kullanmaktan daha basittir, çünkü Messenger çağrışımlar yapılır. Sadece AIDL arayüzü, eş zamanlı istekleri hizmetini kullanabilirsiniz.

Çoğu uygulamada hizmetin çoklu iş parçacığı işlemesi gerekmez. Dolayısıyla, Messenger kullanılması hizmetin tek seferde bir çağrıyı işlemesine olanak tanır. Önemliyse çok iş parçacıklı olmasını istiyorsanız arayüzünüzü tanımlamak için AIDL kullanın.

Aşağıda, Messenger özelliğinin nasıl kullanılacağıyla ilgili bir özet verilmiştir:

  1. Hizmet, her biri için geri çağırma alan bir Handler uygular araması yapabilirsiniz.
  2. Hizmet, Messenger oluşturmak için Handler öğesini kullanır nesne (Handler öğesine referanstır).
  3. Messenger, IBinder hizmetin onBind() tarihinden itibaren müşterilere iade ediyor.
  4. İstemciler, Messenger örneğini oluşturmak için IBinder kullanır. (hizmetin Handler öğesine referans verir) (hizmetin Handler öğesini referans alır) Hizmete Message nesne eklendi.
  5. Hizmet, her Message değerini Handler içinde (özellikle de handleMessage() yönteminde) alır.

Bu şekilde, istemcinin hizmeti çağırabileceği herhangi bir yöntem olmaz. Bunun yerine istemci, hizmetinMessage alır Handler değeri.

Aşağıda, Messenger arayüzü kullanan basit bir örnek hizmet verilmiştir:

Kotlin

/** Command to the service to display a message.  */
private const val MSG_SAY_HELLO = 1

class MessengerService : Service() {

    /**
     * Target we publish for clients to send messages to IncomingHandler.
     */
    private lateinit var mMessenger: Messenger

    /**
     * Handler of incoming messages from clients.
     */
    internal class IncomingHandler(
            context: Context,
            private val applicationContext: Context = context.applicationContext
    ) : Handler() {
        override fun handleMessage(msg: Message) {
            when (msg.what) {
                MSG_SAY_HELLO ->
                    Toast.makeText(applicationContext, "hello!", Toast.LENGTH_SHORT).show()
                else -> super.handleMessage(msg)
            }
        }
    }

    /**
     * When binding to the service, we return an interface to our messenger
     * for sending messages to the service.
     */
    override fun onBind(intent: Intent): IBinder? {
        Toast.makeText(applicationContext, "binding", Toast.LENGTH_SHORT).show()
        mMessenger = Messenger(IncomingHandler(this))
        return mMessenger.binder
    }
}

Java

public class MessengerService extends Service {
    /**
     * Command to the service to display a message.
     */
    static final int MSG_SAY_HELLO = 1;

    /**
     * Handler of incoming messages from clients.
     */
    static class IncomingHandler extends Handler {
        private Context applicationContext;

        IncomingHandler(Context context) {
            applicationContext = context.getApplicationContext();
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SAY_HELLO:
                    Toast.makeText(applicationContext, "hello!", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    /**
     * Target we publish for clients to send messages to IncomingHandler.
     */
    Messenger mMessenger;

    /**
     * When binding to the service, we return an interface to our messenger
     * for sending messages to the service.
     */
    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
        mMessenger = new Messenger(new IncomingHandler(this));
        return mMessenger.getBinder();
    }
}

Şuradaki handleMessage() yöntemi: Handler, hizmetin gelen Message verilerini aldığı yerdir ve what üyesine bağlı olarak ne yapacağına karar verir.

İstemcinin yapması gereken tek şey, hizmet tarafından döndürülen IBinder öğesini temel alarak bir Messenger oluşturmak ve send() öğesini kullanarak bir ileti göndermektir. Örneğin, aşağıda açıklandığı gibi MSG_SAY_HELLO mesajını hizmete gönderir:

Kotlin

class ActivityMessenger : Activity() {
    /** Messenger for communicating with the service.  */
    private var mService: Messenger? = null

    /** Flag indicating whether we have called bind on the service.  */
    private var bound: Boolean = false

    /**
     * Class for interacting with the main interface of the service.
     */
    private val mConnection = object : ServiceConnection {

        override fun onServiceConnected(className: ComponentName, service: IBinder) {
            // This is called when the connection with the service has been
            // established, giving us the object we can use to
            // interact with the service.  We are communicating with the
            // service using a Messenger, so here we get a client-side
            // representation of that from the raw IBinder object.
            mService = Messenger(service)
            bound = true
        }

        override fun onServiceDisconnected(className: ComponentName) {
            // This is called when the connection with the service has been
            // unexpectedly disconnected—that is, its process crashed.
            mService = null
            bound = false
        }
    }

    fun sayHello(v: View) {
        if (!bound) return
        // Create and send a message to the service, using a supported 'what' value.
        val msg: Message = Message.obtain(null, MSG_SAY_HELLO, 0, 0)
        try {
            mService?.send(msg)
        } catch (e: RemoteException) {
            e.printStackTrace()
        }

    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)
    }

    override fun onStart() {
        super.onStart()
        // Bind to the service.
        Intent(this, MessengerService::class.java).also { intent ->
            bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
        }
    }

    override fun onStop() {
        super.onStop()
        // Unbind from the service.
        if (bound) {
            unbindService(mConnection)
            bound = false
        }
    }
}

Java

public class ActivityMessenger extends Activity {
    /** Messenger for communicating with the service. */
    Messenger mService = null;

    /** Flag indicating whether we have called bind on the service. */
    boolean bound;

    /**
     * Class for interacting with the main interface of the service.
     */
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            // This is called when the connection with the service has been
            // established, giving us the object we can use to
            // interact with the service.  We are communicating with the
            // service using a Messenger, so here we get a client-side
            // representation of that from the raw IBinder object.
            mService = new Messenger(service);
            bound = true;
        }

        public void onServiceDisconnected(ComponentName className) {
            // This is called when the connection with the service has been
            // unexpectedly disconnected—that is, its process crashed.
            mService = null;
            bound = false;
        }
    };

    public void sayHello(View v) {
        if (!bound) return;
        // Create and send a message to the service, using a supported 'what' value.
        Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
        try {
            mService.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    protected void onStart() {
        super.onStart();
        // Bind to the service.
        bindService(new Intent(this, MessengerService.class), mConnection,
            Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        // Unbind from the service.
        if (bound) {
            unbindService(mConnection);
            bound = false;
        }
    }
}

Bu örnekte, hizmetin istemciye nasıl yanıt verebileceği gösterilmemektedir. URL'nin ve hizmetten geliyorsa istemcide de bir Messenger oluşturmanız gerekir. İstemci onServiceConnected() geri çağırmasını aldığında, aşağıdakileri içeren hizmete bir Message gönderir: müşterinin replyTo parametresindeki Messenger arasında geçiş yapmak için send() yöntemini kullanabilirsiniz.

İki yönlü mesajlaşmanın nasıl sağlanacağına ilişkin bir örneği MessengerService.java (hizmet) ve MessengerServiceActivities.java (istemci) örnekleri.

Bir hizmete bağlan

Uygulama bileşenleri (istemciler) şunu çağırarak bir hizmete bağlanabilir: bindService() Android ardından sistem, hizmetin onBind() yöntemini çağırır. Bu yöntem etkileşim için IBinder döndürür. geri dönelim.

Bağlama eşzamansızdır ve bindService(), IBinder değerini şuraya döndürmeden hemen döndürür: teslim edilir. IBinder öğesini almak için istemcinin örneği ServiceConnection ve bindService() içine iletilsin. ServiceConnection, IBinder teslim etmek için sistem çağrısı.

Not: Yalnızca etkinlikler, hizmetler ve içerik sağlayıcılar bağlanabilir bir hizmete bağlayamazsınız; yayın alıcıdan bir hizmete bağlayamazsınız.

İstemcinizden bir hizmete bağlamak için aşağıdaki adımları uygulayın:

  1. ServiceConnection uygulayın.

    Uygulamanız, iki geri çağırma yöntemini geçersiz kılmalıdır:

    onServiceConnected()
    Sistem, tarafından döndürülen IBinder öğesini teslim etmek için bu komutu hizmetin onBind() yöntemi.
    onServiceDisconnected()
    Hizmetle ilgili bağlantı beklenmedik şekilde olduğunda Android sistemi bu parametreyi çağırır Örneğin, hizmetin çökmesi veya sonlandırılması gibi durumlar. Bu değil istemcinin bağlantısını keser.
  2. bindService() öğesini çağırarak ServiceConnection uygulamasını iletin.

    Not: Yöntem false (yanlış) değerini döndürürse istemcinin hizmetle geçerli bir bağlantısı yok. Ancak, şunu arayın: unbindService(). gerekir. Aksi takdirde, müşteriniz cihaz boştayken kapanıyor.

  3. Sistem, onServiceConnected() geri çağırma yönteminizi çağırdığında şunu kullanarak hizmeti çağırmaya başlayabilirsiniz: arayüz tarafından tanımlanan yöntemler.
  4. Hizmet bağlantısını kesmek için unbindService() numaralı telefonu arayın.

    Uygulamanız istemciyi kaldırdığında istemciniz hâlâ bir hizmete bağlıysa istemcinin bağlantıyı kesmesine neden olur. İşlem tamamlandığında istemcinin bağlantısını kesmek daha iyi bir uygulamadır önemli bir parçasıdır. Bu işlem boşta kalma hizmetinin kapanmasına neden olur. Okuyucu Gelirleri Yöneticisi'ni Ek notlar bölümüne bakın.

Aşağıdaki örnek, istemciyi daha önce Bağlayıcı sınıfını genişletmeyi gerektirir. Böylece, tek yapması gereken döndürülen IBinder öğesini LocalBinder sınıfına gönderin ve LocalService örneğini isteyin:

Kotlin

var mService: LocalService

val mConnection = object : ServiceConnection {
    // Called when the connection with the service is established.
    override fun onServiceConnected(className: ComponentName, service: IBinder) {
        // Because we have bound to an explicit
        // service that is running in our own process, we can
        // cast its IBinder to a concrete class and directly access it.
        val binder = service as LocalService.LocalBinder
        mService = binder.getService()
        mBound = true
    }

    // Called when the connection with the service disconnects unexpectedly.
    override fun onServiceDisconnected(className: ComponentName) {
        Log.e(TAG, "onServiceDisconnected")
        mBound = false
    }
}

Java

LocalService mService;
private ServiceConnection mConnection = new ServiceConnection() {
    // Called when the connection with the service is established.
    public void onServiceConnected(ComponentName className, IBinder service) {
        // Because we have bound to an explicit
        // service that is running in our own process, we can
        // cast its IBinder to a concrete class and directly access it.
        LocalBinder binder = (LocalBinder) service;
        mService = binder.getService();
        mBound = true;
    }

    // Called when the connection with the service disconnects unexpectedly.
    public void onServiceDisconnected(ComponentName className) {
        Log.e(TAG, "onServiceDisconnected");
        mBound = false;
    }
};

Bu ServiceConnection ile istemci bir hizmete bağlanabilir geçmek aşağıdaki örnekte gösterildiği gibi bindService() olarak ayarlanır:

Kotlin

Intent(this, LocalService::class.java).also { intent ->
    bindService(intent, connection, Context.BIND_AUTO_CREATE)
}

Java

Intent intent = new Intent(this, LocalService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
  • bindService() işlevinin ilk parametresi Bağlanacak hizmeti açıkça adlandıran Intent.

    Dikkat: Bir Service, açıkça bir bağlantı kullanarak uygulamanızın güvenli olduğundan emin olun isteyebilirsiniz. Dolaylı intent kullanarak bir hizmeti başlatmak, hangi hizmetin amaca yanıt verdiğinden emin olamayacağınız için, ve kullanıcı hangi hizmetin başlatıldığını göremez. Android 5.0 (API düzeyi 21) sürümünden itibaren, sistem bindService() öğesini çağırırsanız bir istisna oluşturur gizli bir niyeti vardır.

  • İkinci parametre, ServiceConnection nesnesidir.
  • Üçüncü parametre, bağlama seçeneklerini gösteren bir işarettir (henüz yapılmamışsa hizmeti oluşturmak için genellikle BIND_AUTO_CREATE) yaşanıyor. Diğer olası değerler BIND_DEBUG_UNBIND, BIND_NOT_FOREGROUND veya hiçbiri için 0.

Ek notlar

Bir hizmete bağlama hakkında bazı önemli notları aşağıda bulabilirsiniz:

  • Atılan DeadObjectException istisnayı her zaman yakala bağlantı kopar. Uzak yöntemler tarafından atılan tek istisna budur.
  • Nesneler, işlemlerde referans olarak sayılır.
  • Genellikle bağlama ve bağlanmayı çözme sırasında Yukarıda açıklandığı şekilde, müşteri yaşam döngüsünün ortaya çıkan ve yıkıldığı anların şu örneklere bakabilirsiniz:
    • Hizmetle yalnızca etkinliğiniz görünürken etkileşimde bulunmanız gerekiyorsa onStart() sırasında bağlanın ve onStop() sırasında bağlantıyı kaldırın.
    • Etkinliğinizin arka plan, onCreate() sırasında bağlan ve bağlantıyı kes (onDestroy() sırasında). Bunun, verilerinizin çalışması devam ederken bile arka planda bile hizmeti kullanması gerekir. Bu nedenle hizmet başka bir işlemdeyse sürecin ağırlığını artırırsınız daha yüksek ihtimaller vardır.

    Not: Genellikle bağlantıyı bağlayıp etkinliğinizin onResume() ve onPause() geri çağırmaları sırasında, bu geri çağırmaların her defasında yaşam döngüsü geçişidir. Bu geçişlerde gerçekleşen işleme sürecini minimumda tutun.

    Ayrıca, uygulamanızdaki birden fazla etkinlik aynı hizmete bağlı ve bu, belirli bir aradaki geçiş iki tanesi varsa hizmet yok edilebilir ve mevcut haliyle yeniden etkinlik bağlantısını kaldırır (duraklatma sırasında) bir sonraki bağlantı bağlanmadan (devam ettirme sırasında). Bu etkinlik geçişinin yaşam döngülerini koordine eden işlemler Etkinlik yaşam döngüsü bölümünde açıklanmıştır.

Bir hizmete nasıl bağlanılacağını gösteren daha fazla örnek kod için bkz. ApiDemos'ta RemoteService.java sınıfı.

Bağlı bir hizmetin yaşam döngüsünü yönetin

Bir hizmetin tüm istemcilerle bağlantısı kaldırıldığında Android sistemi hizmeti kaldırır (kullanmaya başlamadığınız sürece startService()) bilgileri gösterilir. Bu nedenle hizmetinizin yaşam döngüsünü yönetmeniz bağlı bir hizmettir. Android sistemi bunu sizin için şunları temel alarak yönetir: herhangi bir müşteriye bağlı olup olmadığını görebilirsiniz.

Ancak onStartCommand() geri çağırma yöntemini uygulamayı seçerseniz hizmeti açıkça durdurmanız gerekir çünkü hizmeti artık başlatıldı olarak kabul edilir. Bu durumda hizmet, bağlı olup olmadığına bakılmaksızın, kendisi stopSelf() ile veya başka bir bileşen stopService() çağrısıyla duruyor kullanabilirsiniz.

Ayrıca, hizmetiniz başlatıldı ve bağlamayı kabul ediyorsa sistem onUnbind() yönteminizle, isteğe bağlı olarak Bir istemci hizmete tekrar bağlandığında onRebind() numaralı telefonu almak istiyorsanız true. onRebind(), geçersiz bir yanıt döndürür ancak müşteri, IBinderni kendi içinde almaya devam eder. onServiceConnected() geri arama. Aşağıdaki şekilde, bu yaşam döngüsü türünün mantığı gösterilmiştir.

Şekil 1. Başlatılan bir hizmetin yaşam döngüsü bağlamaya da izin verir.

Başlatılan bir hizmetin yaşam döngüsü hakkında daha fazla bilgi edinmek için Hizmetlere genel bakış başlıklı makaleyi inceleyin.