Uygulama temeli

Cihazlar arası sorunsuz etkileşimler sağlama

Hoparlörler

Hakkında

Konuşma hakkında

Kullanıcılar telefonlar, giyilebilir cihazlar ve ses çevre birimleri arasında geçiş yaparken akıcı bir cihazlar arası deneyim sunmak, etkileşim için çok önemli hale geldi. Ancak standart ağ yaklaşımlarına güvenmek genellikle pilin tükenmesine, gecikme sürelerinin artmasına ve kullanıcı oturumlarının bölünmesine neden olur.

Bu ayrıntılı incelemede, çeşitli cihazlar arasında iletişim için geliştirilmiş özel Android API'leri tanıtılıyor. Bu API'ler, cihazlar arasındaki geçişleri anında, güvenilir ve sezgisel hale getirmek için bellek ve güç açısından verimli kalıplar sunuyor.

Özet

  • Companion Device Manager, Bluetooth çevre birimleri için ön plan hizmetlerinin yerini alır. Bunu, uygulamaları varlığa göre uyandırarak ve bağlantıları pil tüketmeden yöneterek yapar. Android 17, özellikle tıbbi cihazlar ve fitness takip cihazları için yeni profiller ekler.
  • Jetpack Telecom, Android 8'e kadar olan saat ve araba gibi bağlı cihazlardaki VoIP uygulamaları için sistem araması koordinatörü olarak çalışır. Ayrıca CallControlScope aracılığıyla sessize alma ve kapatma işlemlerini de senkronize eder.
  • Yakında kullanıma sunulacak Jetpack Telecom 1.1.0 özellikleri arasında, sistem çeviricisinde birleştirilmiş arama geçmişleri (SDK 36.1+) ve desteklenen operatör ağlarında otomatik 5G ağ dilimleme yer alıyor.
  • Quick Share SDK'sı önümüzdeki yıl kullanıma sunulacak. Böylece geliştiriciler, yerel ve uçtan uca şifrelenmiş dosya paylaşımını doğrudan Android ve iOS uygulamalarına yerleştirebilecek. Paylaşmak için dokunun (Pixel 11 ile kullanıma sunuldu) özelliği, kapalı olan alıcı uygulamayı otomatik olarak uyandırabilir.

Kaynaklar

Gemini Notebook

Konular

  • cihazlar arası
  • companion-device-manager
  • jetpack-telecom
  • quick-share
  • bluetooth
  • voip
  • eşler arası

Transkript

Cihazlar arası etkileşimlere giriş

  • Herkese merhaba.

  • "Cihazlar Arası Sorunsuz Etkileşimleri Etkinleştirme" kursuna hoş geldiniz.

  • Ben Hanrui. Bugün meslektaşlarım Yacine ve Nataraj da bana eşlik ediyor.

  • Bağlantı dendiğinde genellikle temel bir ağ bağlantısı veya Bluetooth mikrofonlu kulaklıklar akla gelir.

  • Android'de bağlantı bundan çok daha kapsamlıdır.

  • Asıl amaç, cihazların birlikte daha iyi çalışmasını sağlamaktır.

  • Bugün, yaygın cihazlar arası senaryoları inceleyecek ve her biri için hangi API'nin uygun olduğunu göstereceğiz.

  • Uzun bir süre boyunca yalnızca tek bir cihaz, yani telefon için uygulama geliştirdik.

  • Ardından giyilebilir cihazlar popüler oldu.

  • Kısa süre içinde, akıllı saatlerin telefonlarla eşlenmesi, arka planda veri senkronizasyonu yapması veya doğrudan aramaları yanıtlaması çok yaygın hale geldi.

  • Kablosuz kulaklık ekle.

  • Artık kullanıcılar görüşme sırasında ses cihazını değiştirebiliyor. Kol saatinden telefona, kulaklığa veya arabaya geçiş yapabiliyorlar.

  • Son zamanlarda birçok kullanıcı, katlanabilir telefon veya tablet gibi ikinci bir büyük ekranlı cihaz da kullanıyor.

  • Uygulamanın bu cihazlarda sorunsuz çalışmasını beklerler.

  • Bu durum, kullanıcıların Android uygulamalarını çalıştırabileceği ve masalarından ayrılmadan bağlantıda kalabileceği dizüstü bilgisayarlar ve Chromebook'lar için de geçerlidir.

  • 2023'te bile ortalama bir kullanıcının üç ila dört cihazı vardı.

  • Kullanıcılar bu cihazlarda bağımsız işlevlerden daha fazlasını bekler.

  • Birlikte olağanüstü bir deneyim sunan cihazlar arıyorlar.

  • Bu "birlikte daha iyi" deneyimi, özellikle bugün bizim olduğumuz gibi aynı odada bulunan ve yanlarındaki kişilerle fotoğraf, bağlantı veya uygulama paylaşmanın kolay bir yolunu arayan kullanıcılar için çok belirgindir.

  • Rakamlara bakıldığında ekosistemin devasa olduğu ve hızla büyüdüğü görülüyor.

  • Bu yıl dünya genelinde yaklaşık 22 milyar IoT cihazı var ve bu sayı yıldan yıla %14 artıyor.

  • Tüm bu uç noktalar arasında kablosuz bağlantı üçte birini, Bluetooth ise dörtte birini oluşturur.

  • Cihazlar arası bağlantı artık uç bir durum değil.

  • Günlük hayatımızın bir parçasıdır.

  • Ancak günümüzde çoğu uygulama, cihazlar arası özelliklerini hâlâ alt düzey ağ ve Bluetooth API'leri üzerine inşa ediyor. Bu da üç zorluğa neden oluyor.

  • İlk olarak pil ve bellek.

  • Arka plan taramalarının ve hizmetlerinin çalışmaya devam etmesi pil ve bellek tüketir.

  • İkincisi, gecikme.

  • Öngörülemeyen gecikmeler, gerçek zamanlı aramaları ve veri senkronizasyonunu kesintiye uğratır.

  • Üçüncüsü, bağlantı sorunları.

  • Tüm cihazlarda keşif, eşleme ve yeniden bağlanma işlemlerini yönetmek karmaşıktır ve kullanıcı deneyiminin kolayca bozulmasına neden olur.

  • Bu sorunları ortadan kaldırmak için üç ana alanda özel amaçlı API'ler oluşturarak cihazlar arası özellikleri gerçekten basit hale getirdik.

  • Ben tamamlayıcı uygulamalarla başlayacağım. Ardından Nataraj, VoIP uygulamalarını ele alacak ve daha sonra Yacine, P2P paylaşımından bahsedecek.

Tamamlayıcı uygulamalara genel bakış

  • Öncelikle tamamlayıcı uygulamalara göz atalım.

  • Tamamlayıcı uygulama, akıllı saat veya glikoz sensörü gibi yardımcı cihazların telefonunuzla uyumlu çalışabilmesi için telefonunuza yüklediğiniz bir uygulamadır.

  • Bu bölümde, Bluetooth üzerinden bağlı cihazlara odaklanacağız.

  • Genellikle dört yardımcı cihaz kategorisi vardır.

  • İlk olarak, glikoz sensörleri ve yaşamsal değer monitörleri gibi tıbbi cihazlar.

  • Akıllı saat ve fitness bilekliği gibi giyilebilir cihazlar da buna dahildir.

  • Hızlı Eşleme ve akıllı kontroller içeren kulaklıklar.

  • Araç kitleri de dijital araba anahtarları ve eller serbest arama gibi özellikler için kullanılır.

  • Her kategorinin kendine ait önemli kullanıcı yolculukları vardır ancak tüm kategoriler, cihaz ile telefon arasında güvenilir bir bağlantı kurulmasına bağlıdır.

  • Tıbbi cihazlar için bu bağlantı hayati önem taşıyabilir.

  • Bu kategorilerde gördüğümüz dört yaygın ihtiyacı inceleyelim.

  • İlk olarak Cihaz Yönetim Paneli.

  • Uygulamanın, yakındaki tüm cihazlar arasından doğru cihazı (ör. kulaklık veya hoparlör değil, buradaki saat) bulması ve ardından bağlanmak için eşleme akışını başlatması gerekir.

  • İkincisi, varlık kontrolü.

  • Uygulamanın, cihazın ne zaman yakında olduğunu ve ne zaman uzaklaştığını bilmesi gerekir.

  • Cihaz göründüğünde, uygulamanın kullanıcı tarafından açılmamış olsa bile işini yapabilmesi için uyandırılması gerekir.

  • Üçüncüsü, bağlantı bakımı.

  • Uygulamalar, bağlantı kurulduktan sonra bağlantının güvenilir ve kalıcı olmasını ister.

  • Bağlantı kesilirse (ör. kullanıcı kapsama alanı dışına çıkıp geri dönerse) uygulama o sırada çalışmıyor olsa bile otomatik olarak yeniden bağlanmalıdır.

  • Dördüncü olarak, veri senkronizasyonu ve aktarımı.

  • Gerçek değer burada yatıyor.

  • Sensör ölçümlerini senkronize etme, donanım yazılımı güncellemelerini gönderme veya ayarları cihaza gönderme.

  • Tıbbi cihazlar için bu durum kritik olabilir.

  • Ölçümün kaçırılması, uyarının kaçırılması anlamına gelebilir.

  • Tüm bunlar için uygulama işleminin doğru zamanda etkin ve bağlı olması gerekir.

  • Peki, uygulamalar tüm bu ihtiyaçları nasıl karşıladı?

  • Uygulamalar geleneksel olarak ön plan hizmetini yoğun bir şekilde kullanıyordu.

  • Tipik bir uygulama örneği:

  • Daha önce tamamlayıcı uygulama geliştirdiyseniz bu size tanıdık gelebilir.

  • Bluetooth tarama ve bağlanma izinlerini, ön plan hizmet izinlerini ve bağlı cihazın ön plan hizmet türünü beyan edersiniz. Ardından, ön plan hizmetinin kalıcı bir bildirim göstermesi gerektiğinden bildirim iznini beyan edersiniz.

    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"
                     android:usesPermissionFlags="neverForLocation" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
  • Ardından, uygulama işlemini etkin tutmak için yapışkan bir hizmet çalıştırırsınız.

    class BleForegroundService : Service() {
       override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
          …
          return START_STICKY
       }
    }
  • Bu yöntem işe yarar ancak cihaz yakında olmasa bile hizmet sürekli çalıştığı için pil ve bellek tüketir.

  • Bu nedenle, Companion Device Manager'ı (kısaca CDM) geliştirdik.

  • İlk olarak, cihazın varlığına göre uygulamanızı uyandırabilir ve cihaz kapsama alanında kaldığı sürece sistem, uygulama işleminizi etkin tutar.

  • Ön plan hizmeti gerekmez.

  • İkinci olarak CDM, cihaz profillerini destekler.

  • Cihaz profili sayesinde kullanıcı, bir dizi izin iletişim kutusu yerine tek bir dokunuşla uygulamanızın ihtiyaç duyduğu tüm izinleri verir.

  • Bu sayede kullanıcı deneyimi ve dönüşüm oranı önemli ölçüde iyileşir.

  • Kol saati profili Android 12'den, gözlük profili ise Android 14'ten beri kullanılabilir.

  • Android 17'de, özellikle tıbbi cihazlar ve fitness takip cihazları için iki yeni profil ekledik.

  • Şu anda yalnızca sistem uygulamaları için bazı ayrıcalıklı profiller de vardır.

  • Ekosistemden daha geniş bir talep gelirse bu özellikleri daha fazla geliştiriciye sunmayı düşünebiliriz.

Companion Device Manager'ı kullanarak uygulama

  • CDM'yi kullanmak çok kolaydır.

  • Örnek olarak bir tıbbi cihazı ele alalım.

  • Öncelikle gerekli izinleri beyan edin: biri tıbbi cihaz için, biri arka planda çalışmak için ve biri cihazın varlığını gözlemlemek için.

    <uses-permission android:name="android.permission.REQUEST_COMPANION_PROFILE_MEDICAL" />
    <uses-permission android:name="android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND" />
    <uses-permission android:name="android.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE" />
  • Ön plan hizmeti uygulamasında gördüğümüz izinlerin aksine, burada listelenen tüm izinler normal izinlerdir. Yani yükleme sırasında verilirler ve istem iletişim kutusu gösterilmez.

  • Kullanıcının onaylaması gereken tek şey ilişkilendirmedir.

  • Bu ilişkilendirmenin nasıl oluşturulacağına bakalım.

  • Burada, yalnızca doğru cihazın gösterilmesi için cihaz filtresi içeren bir ilişkilendirme isteği oluşturuyoruz.

    val paringRequest = AssociationRequest.Builder()
       .addDeviceFilter(deviceFilter)
       .setSingleDevice(true)
       .setDeviceProfile(AssociationRequest.DEVICE_PROFILE_MEDICAL)
       .build()
    
    companionDeviceManager.associate(paringRequest, ContextCompat.getMainExecutor(this),
       object : CompanionDeviceManager.Callback() {
           override fun onAssociationPending(intentSender: IntentSender) {
               intentSenderLauncher.launch(IntentSenderRequest.Builder(intentSender).build())
           }
    
           override fun onAssociationCreated(associationInfo: AssociationInfo) { … }
    
           override fun onFailure(error: CharSequence?) { … }
       }
    )
  • setSingleDevice değerini true olarak ayarlayın ve profili "medical" olarak belirleyin.

  • Ardından satış temsilcisini arayın.

  • Tarama işlemini CDM gerçekleştirir.

  • onAssociationPending içinde IntentSender alacağız.

  • Uygulamayı başlattığınızda sistem bir ilişkilendirme iletişim kutusu gösterir.

  • Tıbbi profil sayesinde, buraya bir kez dokunulduğunda yalnızca ilişkilendirme onaylanmakla kalmaz, aynı zamanda profilin ihtiyaç duyduğu tüm izinler de verilir. Hatta Rahatsız Etmeyin modu bile atlanır. Bu, çok önemli uyarılar için kritik bir özelliktir.

  • Kullanıcı "İzin ver"e dokunduğunda AssociationInfo ile onAssociationCreated'yi alırız. Bu, ilişkilendirme kimliğini de içerir.

  • Ardından, bu ilişkilendirme kimliğiyle startObservingDevicePresence'ı çağırarak cihazın varlığını gözlemleyebiliriz.

  • Ayrıca CompanionDeviceService sınıfını genişleten bir hizmet de uygulamanız gerekir.

    class BleCompanionDeviceService : CompanionDeviceService() {
    
       override fun onDevicePresenceEvent(event: DevicePresenceEvent) {
           when (event.event) {
               DevicePresenceEvent.EVENT_BLE_APPEARED -> onDeviceAppeared(event.associationId)
               DevicePresenceEvent.EVENT_BLE_DISAPPEARED -> onDeviceDisappeared(event.associationId)
           }
       }
    
       private fun onDeviceAppeared(associationId: Int) { … }
    
       private fun onDeviceDisappeared(associationId: Int) { … }
    }
  • Cihaz kapsama alanına girdiğinde, uygulamanız çalışmıyor olsa bile sistem hizmetinize bağlanır.

  • Sistem, onDevicePresenceEvent numarasını EVENT_BLE_APPEARED ile arayacak.

  • Ardından bağlanıp senkronizasyon yapabilirsiniz.

  • Cihaz ayrıldığında EVENT_BLE_DISAPPEARED alırsınız.

  • Ardından temizleme işlemini yapabilirsiniz.

  • Sürekli çalışan hizmet ve yalnızca etkin kalmak için gönderilen bildirimler yoktur.

  • CDM'nin, geliştiricilerin dikkat etmesi gereken birkaç sınırlaması olduğunu kabul etmemiz gerekir.

  • İlk olarak işletim sistemi sürümleri.

  • Çoğu CDM özelliği Android 12 ve 13'te kullanıma sunuldu.

  • Ancak Android 16'da bazı etkileyici iyileştirmeler yapıldı ve Android 17'de yeni profiller kullanıma sunuldu.

  • Bu nedenle, çalışma zamanında işletim sistemi sürümünü kontrol edin ve eski sürümler için bir yedek bulundurun.

  • Bununla birlikte, hedef SDK her yıl artar ve minimum SDK da bunu takip eder.

  • Uygulamaların şu anda karşılaştığı ve gelecekte karşılaşacağı bellek baskısını azaltmak için uygulamaların en kısa sürede ön plan hizmetinden CDM'ye geçmesini önemle tavsiye ederiz.

  • CDM tarafından desteklenmeyen bir kullanım alanınız varsa bize bildirin.

  • İkinci olarak, CDM şu anda arka planda taramayı destekler ancak arka planda bildirmeyi desteklemez.

  • Bu özelliğe nadiren ihtiyaç duyuluyor.

  • Ancak uygulamanızın, telefonun çevre birimi olarak çalışmasına ve arka planda sürekli olarak bildirimde bulunmasına ihtiyacı varsa bu konuda daha fazla bilgi edinmek isteriz.

  • Üçüncü olarak, CDM düşük güçte tarama modunu kullanır.

  • Pil ve bellek için gerçek zamanlı yanıt verme hızından biraz ödün verir.

  • Bu nedenle, anında uyanma beklemeyin.

  • Son olarak, yük içeriği incelenemez.

  • Belirli bir özellik veya reklam verileri için kaydolamazsınız.

  • Ancak cihaz kapsama alanına girdiğinde uygulamanız uyandırılır.

  • Böylece gerektiğinde bağlanıp yükü kontrol edebilir.

  • Tamamlayıcı uygulamalar ve CDM hakkında her şeyi öğrendiniz.

  • Şimdi sözü VoIP uygulamaları için Nataraj'a bırakıyorum.

Cihazlar arası VoIP aramalarıyla ilgili sorunlar

  • Uygulamanızın özel bir çevre birimi varsa ve bu çevre birimi üzerinden sürekli iletişim kuruyorsa CompanionDeviceManager doğru araçtır.

  • Herkese merhaba.

  • Ben Nataraj K R.

  • Şimdi, bir sonraki cihazlar arası senaryo olan gerçek zamanlı aramadan bahsedeceğim.

  • Günümüzde kullanıcıların aramaları yönetme şekli değişiyor.

  • Aramaların %40'ından fazlası VoIP ağları üzerinden yapılıyor.

  • Android de bu konuda önemli bir rol oynuyor.

  • Aslında bu aramaların %71'i Android cihazlarda yapılıyor. Bu da her iki aramadan birinin Android cihazlarda yapıldığı anlamına geliyor.

  • Sadece aramalar değil.

  • Kullanıcıların sahip olduğu cihaz ekosistemi de büyük bir hızla büyüyor.

  • Şu anda yollarda Android Auto kullanan 250 milyondan fazla araç var ve kullanıcılara bir milyardan fazla Bluetooth cihazı gönderiyoruz.

  • Kulaklıklar, Wear OS kol saatleri, Android Auto özellikli Android arabalar ve Bluetooth hoparlörler, kullanıcıların telefonun yanı sıra sahip olduğu cihazlardır. Kullanıcılar, aramalarının tüm bu cihazlar arasında sorunsuz bir şekilde aktarılmasını ister.

  • Örneğin, kullanıcı bir arama aldığında arayanın bilgilerini öğrenmek için saatine bakabilir.

  • Aramayı saatinden yanıtlar.

  • Gerektiğinde seslerini kapatıp açabilir, kulaklıklarını takıp aramalarına devam edebilirler.

  • Dışarı çıkmak istediklerinde arabalarına binerler ve telefon görüşmelerinin otomatik geçiş ile arabanın kabinine geçmesini beklerler.

  • Bu durum kullanıcı için normal bir rutin haline geldi ve bu, premium bir deneyim değil.

  • Kullanıcılar için bu temel bir gereksinimdir ve VoIP uygulamalarımızda kullanıcılara bu sorunsuz deneyimi sunmak biz Android geliştiricilerinin sorumluluğundadır.

  • Ancak tüm bunları sıfırdan kendiniz oluşturmaya çalışırsanız üç büyük sorunla karşılaşırsınız.

  • Birincisi, Bluetooth soketleriyle parçalanma.

  • Sistem, uygulamanızın bir arama gerçekleştirdiğini bilmediğinden, aramanızın saate veya Android Auto'ya yansıtılabilmesi için özel Bluetooth soketleri ve özel medya oturumları oluşturmanız gerekir.

  • İkinci sorun ise ses odağıdır.

  • Düşük seviyeli AudioManager API'leri ve Bluetooth API'leriyle uğraşmanız gerektiğinden ses sızıntıları meydana gelir ve bu, sistem için öncelikli bir konu değildir, değil mi?

  • Uygulamanızda VoIP araması yapılıyorsa operatör araması geldiğinde bu arama kesilir ve modem sesi alır. Bu durumda uygulamanızda ses olmaz.

  • En kötüsü, hücresel arama sona erse bile ses odağı uygulamanıza geri dönmez.

  • Üçüncü sorun ise senkronizasyondur.

  • Kullanıcı, saatinde "Sesi kapat"a dokunsa da telefonun kullanıcı arayüzünde aramanın sesi açık olarak gösteriliyordu.

  • Bu durum büyük bir kafa karışıklığına neden olur.

  • Kullanıcı, aramayı aracın direksiyonundan sonlandırsa da telefonda devam eden arama bildirimi gösteriliyordu.

  • Bu durum kullanıcı için büyük bir hayal kırıklığıdır.

Jetpack Telecom ile tanışın

  • Tüm bu sorunları çözmek için Jetpack Telecom'u geliştirdik.

  • Bu nedenle, aramanızı CallsManager kullanarak Jetpack Telecom'a bir kez kaydedersiniz. Jetpack Telecom, merkezi bir sistem çağrısı koordinatörü olarak görev yapar.

  • Aramanızı saate, Android Auto'ya ve kullanıcının sahip olduğu diğer uzak yüzeylere yansıtma sorumluluğunu üstlenir.

  • Ayrıca ses odağını da yönetir.

  • En önemlisi de tüm bunlar, Android 8'e kadar olan tüm sürümlerde sorunsuz bir şekilde çalışır.

  • Görüşmeyi saat veya araba ekranına yansıtmak, işin yalnızca yarısıdır. Kullanıcılar, görüşmenin durumunu bu cihazlardan kontrol etmek ister.

  • Aramanın sesini saatlerinden kapatmak veya gerektiğinde açmak istiyorlar.

  • Kullanıcı, aramayı aracın direksiyonundan veya kulaklığına iki kez dokunarak sonlandırmak istiyor.

  • Jetpack Telecom, bu donanım etkinliklerini dinler ve hepsini tek bir yerde (CallControlScope) geri çağırma olarak sunar.

  • Tek yapmanız gereken bu geri çağırmaları dinlemek, arama motorunuzu yönetmek ve arama durumunu buna göre güncellemektir.

  • Jetpack Telecom, bu arama durumunu cihazlar arasında senkronize etme sorumluluğunu üstlenir.

  • Yani kitaplık, arka planda iki grupta avantajlar sunar.

  • Birincisi, bahsettiğimiz tüm sorunları çözüyor.

  • Yani alt düzey AudioManager API'leriyle uğraşmak yerine kitaplık, bildirim temelli arama uç noktaları sağlar, ses odağını yönetir ve cihazlar arasında senkronizasyon yapar.

  • Cihazlar arasında arama aktarma sorumluluğunu üstlenir.

  • Hücresel arama geldiğinde de bu işlemi yapar.

  • Ancak kitaplığın sağladığı diğer bir avantaj, kitaplığın Kotlin üzerine inşa edilmiş olmasıdır. Jetpack Telecom ile bir arama eklediğinizde Kotlin eş yordam kapsamı açılır.

  • Böylece Kotlin eş yordamlarından yararlanır ve bu Kotlin eş yordamı tam olarak arama süresi boyunca etkin kalır.

  • Bu nedenle, görüşmeyle ilgili olarak çalıştırdığınız tüm işler, görüşme bağlantısı kesilir kesilmez otomatik olarak temizlenir.

  • Böylece, başıboş işler kalmaz ve çağrı yaşam döngüsü de kitaplık tarafından yönetilir.

  • Bu harika kitaplığı kullanmak istediğinizi tahmin edebiliyorum.

  • Üstelik çok kolay.

  • İlk adım, bağımlılığı açıkça beyan etmektir.

  • Ardından, gerekli izni (MANAGE_OWN_CALLS) beyan edin ve bir CallsManager nesnesi örneklendirin.

    <uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
  • CallsManager nesnesini örneklendirdikten sonra uygulamanızı, uygulamayla sağlamak istediğiniz özelliklerle (ör. görüntülü görüşme veya çağrı akışı) kaydedin.

    // Initialize CallsManager & register supported capabilities once
    val callsManager = CallsManager(context)
    
    callsManager.registerAppWithTelecom(
        capabilities = CallsManager.CAPABILITY_SUPPORTS_VIDEO_CALLING or
                       CallsManager.CAPABILITY_SUPPORTS_CALL_STREAMING
    )
  • Ardından 2. adıma geçin.

  • Uygulamanızı Jetpack Telecom'a kaydettikten sonra gelen ve giden aramaları yönetebilirsiniz.

  • Bunun için aramanın meta verilerini (ör. arayanın veya arananın displayName, arayanın uç noktası olan adres, aramanın gelen arama mı yoksa giden arama mı olduğunu belirten yön) içeren bir CallAttributesCompat nesnesi oluşturmanız gerekir. Böylece Jetpack Telecom, ilgili kullanıcı arayüzünü bu uzak yüzeylerde sunabilir ve ardından sesli arama mı yoksa görüntülü görüşme mi olduğunu belirten callType ile gerekli kaynakları alabilirsiniz.

    val attributes = CallAttributesCompat(
        displayName = "Kukk Nat",
        address = Uri.parse("tel:+16505550199"),
        direction = CallAttributesCompat.DIRECTION_INCOMING,
        callType = CallAttributesCompat.CALL_TYPE_AUDIO_CALL
    )
    
    callsManager.addCall(
        attributes, onAnswer, onDisconnect, onSetActive, onSetInactive
    ) {
        // Coroutine CallControlScope active for the duration of the call
    }
  • Meta veri nesnesini hazırladıktan sonra callsManager.addCall yöntemini kullanarak ekleyin.

  • Bu işlem, bir arama kontrolü eş yordam kapsamı açar.

  • Aramanızı ekledikten sonra 3. adıma geçebilirsiniz.

  • 3. adımda, kullanıcının bu uzak yüzeylerden gerçekleştireceği işlemler dinlenir.

  • CallControlScope kullandığınız için tek yapmanız gereken Kotlin akışlarını toplamak.

    callsManager.addCall(attributes, onAnswer, onDisconnect, onSetActive, onSetInactive) {
        // 1. React to hardware mute toggles from Watch, Car, or Headset
        launch {
            isMuted.collect { muted -> audioEngine.setMicMuted(muted) }
        }
    
        // 2. Observe available endpoints & request declarative switches
        launch {
            currentCallEndpoint.collect { endpoint -> updateUi(endpoint) }
        }
        requestEndpointChange(preferredBluetoothEndpoint)
    }
  • Kullanıcı, bu uzak yüzeylerden aramayı sessize aldığında tepki vermek için isMuted değerini toplarsınız ve buna göre arama durumunuzu güncelleyebilirsiniz.

  • Görüşmenin şu anda hangi uç noktada gerçekleştiğini öğrenmek için currentCallEndpoint değerini toplayın. Böylece kullanıcı arayüzünüzü buna göre güncelleyebilirsiniz.

  • Telefonunuzun kullanıcı arayüzünde belirli cihazları gösterebilirsiniz.

  • Kullanıcı bir cihazdan başka bir cihaza geçmek istediğinde, tercih ettiği uç noktayla requestEndpointChange yöntemini çağırmanız yeterlidir.

  • İşte bu kadar basit.

  • Bu üç adımı tamamladığınızda uygulamanız kullanıma hazır olur ve Jetpack Telecom entegre edilir.

  • Ancak hepsi bu kadar değil.

  • Jetpack Telecom 1.1.0 ile birleştirilmiş arama geçmişleri gibi daha birçok özellik sunuyoruz. Bu sayede, tüm VoIP aramalarınız artık sistem çeviricisinde yerel olarak gösterilecek.

  • Bu sayede kullanıcılarınız, sistem çeviricinizden doğrudan uygulamanıza tek dokunuşla geri arama yapabilir.

  • Bu sayede, tüm uygulamalar arasında belirli bir uygulamayı aramanıza gerek kalmaz.

  • Alışık oldukları sistem numara çeviricisinden geri aramayı başlatabilirler.

  • Ancak bazı kullanıcılar için ayrıntılı kontroller de sunuyoruz.

  • Bir aramanın veya belirli bir aramanın sisteme kaydedilmesini istemiyorsanız CallAttributesCompat nesnesinin içindeki isLogExcluded işaretini "true" olarak ayarlamanız yeterlidir.

  • Daha önce bahsettiğim meta veri nesnesini "true" olarak ayarladığınızda aramanız sisteme kaydedilmez ve sistem çeviricisinde gösterilmez.

  • 1.1.0 ile sunulacak ikinci muhteşem özellik ise 5G ağ dilimleme.

  • Desteklenen operatör ağlarında, ağlar size premium ağ dilimleri sağlar. Yani operatör, belirli bir kullanım alanı için düşük gecikmeli ve kesintisiz bir ağ dilimi sunar. Böylece daha kaliteli ve daha iyi bir deneyim yaşarsınız.

  • Bu nedenle, desteklenen operatör ağlarında bu özelliği kullanıma hazır bir şekilde alırsınız. Bu sayede, sizin tarafınızdan ekstra bir çaba gösterilmesi gerekmez, tek bir satır kod bile yazmanız gerekmez.

  • Kitaplığı entegre ettikten sonra aramalarınız bu ağ dilimlerinden yararlanır ve daha iyi gecikme süresi ile daha iyi performans elde edersiniz.

  • Ancak herhangi bir nedenle bu özelliği kullanmak istemiyorsanız CAPABILITY_OPT_OUT_OF_PREMIUM_NETWORK işaretini kullanarak devre dışı bırakabilirsiniz.

  • Jetpack Telecom; Google Meet, WhatsApp, KakaoTalk ve Zoho Arattai gibi dünyanın en popüler iletişim uygulamaları tarafından kullanılmaktadır.

  • Bu kitaplığı uygulamanıza entegre etmek ve kullanıcılara daha iyi bir deneyim sunmak artık sizin elinizde.

  • Gerçek zamanlı arama özelliğini ele aldığımıza göre, dokunarak paylaşma özelliğini anlatması için sözü muhteşem meslektaşım Yacine'e bırakıyorum.

  • Teşekkür ederiz.

Eşler arası paylaşım zorlukları

  • Evet arkadaşlar, biraz yorulduğunuzu biliyorum. Endişelenmeyin, bu son bölüm.

  • Bu nedenle, eşler arası dosya paylaşımını ele alacağım ancak eşler arası paylaşım ile yapabileceğimiz başka kullanım alanları da var.

  • Mobil ekosistemde her gün sosyal medya ve mesajlaşma uygulamalarında 14 milyardan fazla fotoğraf ve video paylaşıldığını görüyoruz. Bu gerçekten çok büyük bir rakam.

  • Bu dosyaların çoğu bulut üzerinden paylaşılıyor. Yani fotoğrafı çekip favori hizmetiniz üzerinden yüklüyorsunuz, karşı taraf da aynı şekilde indiriyor.

  • Aynı durum, birini veya bir arkadaşınızı sosyal ağa davet etmeye çalıştığınızda da geçerlidir. Birini bir oynatma listesi veya doküman üzerinde ortak çalışmaya davet etmek için genellikle kullanıcı adını ya da e-posta adresini yazmanız gerekir. Bu da klavyenizde biraz zaman alır.

  • Hata yapabilirsiniz ve bu, özellikle de yan yana otururken iyi bir deneyim olmaz. "Bulut üzerinden göndermem gerekiyor, beklemem gerekiyor" gibi bir durum ortaya çıkar.

  • Pek iyi değil.

  • Günümüzde hepimizin şık telefonları, cihazları, tabletleri, katlanabilir cihazları var ve bunlarla muhteşem fotoğraflar çekiyoruz.

  • Ancak bu sosyal medya platformlarından veya mesajlaşma uygulamalarından bazıları üzerinden paylaşım yaptığınızda, performans sorunları ve depolama alanı nedeniyle görüntüler sıkıştırılıyor. Sonuç olarak, muhteşem ekranınızda oldukça pikselli veya en iyi kalitede olmayan görüntüler elde ediyorsunuz.

  • Premium cihazınızda böyle bir deneyim yaşamanızı istemeyiz.

  • İkinci olarak, dosyalar artık oldukça büyük.

  • Tek bir resim kolayca 10 MB, 5 dakikalık bir video ise 500 MB olabilir. Bu nedenle, tüm bunları yüklemek ve indirmek oldukça uzun sürer.

  • Son olarak, diğer tarafta bu gecikmeyi beklemeniz gerekir.

  • Örneğin, bazen kalabalık bir otobüse bindiğinizde otobüs hareket ederken en iyi gecikme süresini ve en iyi ağ kapsama alanını elde edemezsiniz. Bazen dosya aktarımı kesilir, bazen de bu çok uzun gecikme süresi nedeniyle zaman aşımı yaşayabilirsiniz ve dosya aktarımı iptal edilir. Bu durum kullanıcı için gerçekten can sıkıcıdır.

  • Tüm bu dosyaları paylaşmak için buluta güvenmek ve tüm bu işlemleri beklemek yerine neden Bluetooth veya kablosuz bağlantı gibi yerel ağları kullanmıyorsunuz?

  • Ancak bunu kendiniz yapmaya çalışırsanız Bluetooth yöneticisi, kablosuz ağ yöneticisi ve kendi protokolünüzü yazma gibi konularla uğraşmanız gerekir. Herkes bu işlere zaman ayırmak istemeyebilir.

  • Ancak aslında Android'de zaten mevcut olan bir şey var.

  • Bu özellik zaten kullanıma sunuldu ve adını duymuş olabilirsiniz: Quick Share.

Quick Share'e genel bakış

  • Android'deki Quick Share özelliği, bu soyutlamayı sistemde hazır bulundurur. Böylece, tüm bunları yönetmek zorunda kalmadan dosyaları başka bir cihazla paylaşabilirsiniz.

  • Paylaşım sayfanızda zaten mevcut ve her iki cihaz arasında cihazınız için en iyi protokolün hangisi olduğunu değiştiriyor. Marshmallow ve daha yeni sürümlerde kullanılabiliyor. Bu da günümüzde oldukça büyük bir kitle demek, değil mi?

  • Son olarak, yanda gördüğünüz tanıdık kullanıcı arayüzü ve kullanıcı deneyimi, kullanıcılarınıza gerçekten yardımcı olur.

  • Kullanıcı arayüzünü bildikleri için nasıl kullanılacağını öğrenmeleri gerekmez, daha önce görmüşlerdir.

  • Ancak geliştiricilerin deneyimin sahibi olmak istediklerini de biliyoruz.

  • Uygulamanızı ve kullanıcılarınızı muhtemelen bizden daha iyi tanıyorsunuz.

  • Bu nedenle, Quick Share'ı doğrudan uygulamanıza ekleyebilirsiniz.

  • Geliştiricilerle görüşmeye başladık ve Quick Share'in zaten oldukça yaygın olduğunu gördük.

  • Android'de, Chromebook'larda, kısa süre önce Google Kitaplar'da ve Windows'da kullanılabilir. Bu, 3 milyardan fazla cihaz demek. Muazzam bir rakam.

  • Pixel 11'de paylaşmak için dokunma özelliğini de kullanıma sunduk.

  • Yani paylaşmak istediğiniz cihazı seçmek yerine dokunmanız yeterli. NFC ile bu keşfedilebilirliği doğrudan sizin için yapıyoruz.

  • Yani bir fotoğraf veya dosya seçip iki cihazı birbirine dokundurarak doğrudan paylaşabilirsiniz.

  • Ayrıca, deneyimin sahibi olmak isteyen geliştiriciler de var.

  • Kullanıcılarınızın belirli bir özelliği (bu örnekte dosya paylaşımı) kullanabilmesi için en iyi yöntemin bu olduğunu biliyoruz.

  • Bu nedenle, uygulamanıza Quick Share'ı yerleştirebilirsiniz.

  • Bu nedenle, önümüzdeki yıl Quick Share SDK'yı doğrudan kullanımınıza sunacağız.

  • Bu özelliği doğrudan uygulamanızda kullanabilirsiniz. Ayrıca, her iki cihaz arasında uçtan uca şifreleme gibi yerleşik güvenlik özellikleri de sunulur.

  • Aktarımlar bu yerel ağlar arasında gerçekleştiğinden, evinizdeki kablosuz ağda tam hızda aktarım yapabilirsiniz. Ayrıca, ikiniz arasında otomatik olarak bir hotspot oluşturulabilir, bununla uğraşmanız gerekmez.

  • Kablosuz Doğrudan Bağlantı'yı destekleyen cihazlarda ise bu özellik zaten mevcuttur.

  • Muhteşem kameranızla çektiğiniz dosyalar en iyi çözünürlüklerini ve ayrıntılarını korur. Böylece büyük ekranınızda onları net bir şekilde görebilirsiniz.

  • Yerel ağları kullandığı için metronun en derin yerinde bile arkadaşınızla paylaşım yapabilirsiniz.

  • Uçakta da binlerce metre yükseklikte, gökyüzünde olacaksınız ve yine de bu dosyaları paylaşabileceksiniz.

  • Son olarak, geliştirici olarak sizin için veri açısından büyük bir maliyet tasarrufu sağlar. Çünkü öncelikle kullanıcılarınızın bu veri planını kullanması gerekmez ve turist olarak seyahat ederken bu büyük bir avantajdır.

  • Ayrıca kendi sunucularınızda bu bakımı yapmanız gerekmez.

  • Geçen yıl geliştiricilere ve kullanıcılara, Quick Share ile AirDrop üzerinden iPhone cihazlarla dosya paylaşabileceklerini söylemiştik.

  • Quick Share ile geliştiricilere de aynı imkanı sunuyoruz.

  • iOS uygulamaları olan geliştiricilerin, cihazdan bağımsız olarak her iki platform arasında dosya paylaşabilmesi için Quick Share iOS SDK'sı sunacağız.

  • Tüm bunlar şık bir sunumdu. Şimdi koda hızlıca göz atalım.

  • Bu süreci olabildiğince basit hale getirmeye çalıştık.

  • QuickShareClient başlatmanız, paylaşmak istediğiniz dosyaları eklemeniz gerekir. Oturumu başlattığınızda, yan tarafta gördüğünüz bu güzel kalıcı pencereyi, kullanıcıların gönderilen dosyaları önizleme olarak görebileceği alt sayfayı görürsünüz. İçeriğin hassas olduğunu düşünüyorsanız ekranda gördüğünüz seçenekle bunu da etkinleştirebilirsiniz.

    // Final API may undergo further updates
    val quickShareClient = QuickShareClient.create(activity)
    val attachment = FileAttachment(
      fileName = "report.pdf",
      size = 1_048_576L,
      uri = fileUri,
      mimeType = "application/pdf",
      // Sensitive content will be masked in preview
      isSensitiveContent = false,
    )
    
    val content = ShareableContent.withFiles(listOf(attachment))
    val request = SharingRequest.withContent(content)
    val session = quickShareClient.startSharingSession(request, lifecycleOwner)
  • Uygulamanızda bir dosya almak istediğinizde de aynı şey geçerli. Tabii ki bu durumda ek eklemiyorsunuz ve oturum başlar başlamaz bunlarla uğraşmanız gerekmiyor.

    // Final API may undergo further updates
    val quickShareClient = QuickShareClient.create(activity)
    val request = SharingRequest.withoutContent()
    val session = quickShareClient.startSharingSession(request, lifecycleOwner)
    
    // Open the Quick Share overlay in receive mode
    session.launchWindow(activity, contentSelectionIntent = null)
  • Şimdiye kadar her iki tarafta da yalnızca 20 satır kod gördünüz.

  • Quick Share ve paylaşmak için dokunun özelliği sayesinde, dosyaları yalnızca cihazlara dokunarak paylaşabilmenin aslında yeni bir kullanım alanı sağladığını biliyoruz.

  • Uygulamanız diğer cihazda kapatılabilir. Dokunduğunuzda, dosya aktarılır aktarılmaz uygulamanız otomatik olarak açılır ve cihaz üzerinde işleme gibi işlemler yapabilmek veya doğrudan uygulamanızda kullanıcıya bir şey göstermek için URI'yi alırsınız.

    // Final API may undergo further updates
    val quickShareClient = QuickShareClient.create(activity)
    val urlAttachment = TextAttachment(
      text = groupAddUrl,
      type = TextAttachment.Type.URL,
    )
    
    val content = ShareableContent.withText(urlAttachment)
    val appLink = AppLink("https://myapp.com/group/invite")
    val request = SharingRequest.withContent(content, appLink)
    val session = quickShareClient.startSharingSession(request, lifecycleOwner)
  • Yani, alıcı cihazda uygulamanızı açmanız gerekmez.

  • Paylaşmak için dokunun özelliği sayesinde bu bağlantı otomatik olarak açılır.

  • Kullanıcı arayüzünüzün bu dosya aktarımına tepki vermesini istiyorsanız Kotlin Flow'u kullanabilirsiniz. Bu sayede, işlemi gerçekleştirmek için gereken tüm etkinliklere erişebilirsiniz.

    // Final API may undergo further updates
    scope.launch {
      for (event in session.sharingEvents) {
        when (event) {
          is SharingEvent.SendComplete ->
            println("Send finished")
          is SharingEvent.ReceiveComplete ->
            println("Received, files=${event.content?.files?.size}")
          else -> println("other event")
        }
      }
    }

Özet ve kapanış

  • Bugün çok fazla şey gördük, bu yüzden toparlıyorum.

  • Merak etmeyin, mola vermek için birkaç dakikanız olacak.

  • Hanrui'nin daha önce belirttiği gibi CompanionDeviceManager, tüm Bluetooth etkileşimlerini ve sürekli Bluetooth etkileşimlerini yönetmek için en iyi API'dir.

  • Uygulamanızda IP üzerinden sesli arama özelliği varsa bu özelliğin ana kullanım alanı olması gerekmez. Örneğin, uygulamanızda kullanıcının destek ekibini arayabileceği destek istemcileri olabilir.

  • Bu durumda da Android'de IP üzerinden sesli aramaları işlemenin en iyi yolu Jetpack Telecom'dur.

  • Son olarak, bahsettiğim gibi, eşler arası dosya paylaşımı veya uygulama açma için paylaşmak için dokunun özelliğiyle Quick Share çözüm sunar.

  • Hepinize teşekkür ederim. Gitmeden önce küçük bir hatırlatma: Sorularınızı yanıtlamak için dışarıda olacağız.

  • Sunduğumuz tüm kullanım alanlarıyla ilgili sorularınız olursa ofis saatlerimizde bize ulaşabilirsiniz.

  • Konuşmanızdan veya diğer oturumlardan öğrendiklerinizi sosyal medyada paylaşmayı unutmayın.

  • #AndroidDevSummit'i düzenliyoruz.

  • Etkinliğe katılımın yüksek olduğunu ve katılımcıların etkinlikten gerçekten keyif aldığını bilmek bizim için çok önemli.

  • Bu sayede, tekrar görmek istediğimiz bir topluluğumuz olduğunu biliyoruz.

  • Ayrıca, danışma masasından Android bot anahtarlığınıza ekleyebileceğiniz sosyal maskotunuzu alabilirsiniz.

  • Doğru mu yaptım?

  • Teşekkür ederiz.

Kod

Kod snippet'leri

"Tamamlayıcı uygulamalara genel bakış" videosunda 06:17'deki XML snippet'i
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
                 android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
"Tamamlayıcı uygulamalara genel bakış" videosunda 06:34'teki Kotlin snippet'i
class BleForegroundService : Service() {
   override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
      …
      return START_STICKY
   }
}
"Companion Device Manager'ı kullanarak uygulama" bölümünde 08:03'teki XML snippet'i
<uses-permission android:name="android.permission.REQUEST_COMPANION_PROFILE_MEDICAL" />
<uses-permission android:name="android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND" />
<uses-permission android:name="android.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE" />
"Companion Device Manager'ı kullanarak uygulama" bölümünde 08:38'deki Kotlin snippet'i
val paringRequest = AssociationRequest.Builder()
   .addDeviceFilter(deviceFilter)
   .setSingleDevice(true)
   .setDeviceProfile(AssociationRequest.DEVICE_PROFILE_MEDICAL)
   .build()

companionDeviceManager.associate(paringRequest, ContextCompat.getMainExecutor(this),
   object : CompanionDeviceManager.Callback() {
       override fun onAssociationPending(intentSender: IntentSender) {
           intentSenderLauncher.launch(IntentSenderRequest.Builder(intentSender).build())
       }

       override fun onAssociationCreated(associationInfo: AssociationInfo) { … }

       override fun onFailure(error: CharSequence?) { … }
   }
)
"Companion Device Manager'ı kullanarak uygulama" bölümünde 09:47'deki Kotlin snippet'i
class BleCompanionDeviceService : CompanionDeviceService() {

   override fun onDevicePresenceEvent(event: DevicePresenceEvent) {
       when (event.event) {
           DevicePresenceEvent.EVENT_BLE_APPEARED -> onDeviceAppeared(event.associationId)
           DevicePresenceEvent.EVENT_BLE_DISAPPEARED -> onDeviceDisappeared(event.associationId)
       }
   }

   private fun onDeviceAppeared(associationId: Int) { … }

   private fun onDeviceDisappeared(associationId: Int) { … }
}
"Introducing Jetpack Telecom" videosunda 18:29'daki XML snippet'i
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
"Introducing Jetpack Telecom" (Jetpack Telecom'a Giriş) videosunda 18:36'daki Kotlin snippet'i
// Initialize CallsManager & register supported capabilities once
val callsManager = CallsManager(context)

callsManager.registerAppWithTelecom(
    capabilities = CallsManager.CAPABILITY_SUPPORTS_VIDEO_CALLING or
                   CallsManager.CAPABILITY_SUPPORTS_CALL_STREAMING
)
"Introducing Jetpack Telecom" videosunda 18:55'teki Kotlin snippet'i
val attributes = CallAttributesCompat(
    displayName = "Kukk Nat",
    address = Uri.parse("tel:+16505550199"),
    direction = CallAttributesCompat.DIRECTION_INCOMING,
    callType = CallAttributesCompat.CALL_TYPE_AUDIO_CALL
)

callsManager.addCall(
    attributes, onAnswer, onDisconnect, onSetActive, onSetInactive
) {
    // Coroutine CallControlScope active for the duration of the call
}
"Introducing Jetpack Telecom" videosunda 19:49'daki Kotlin snippet'i
callsManager.addCall(attributes, onAnswer, onDisconnect, onSetActive, onSetInactive) {
    // 1. React to hardware mute toggles from Watch, Car, or Headset
    launch {
        isMuted.collect { muted -> audioEngine.setMicMuted(muted) }
    }

    // 2. Observe available endpoints & request declarative switches
    launch {
        currentCallEndpoint.collect { endpoint -> updateUi(endpoint) }
    }
    requestEndpointChange(preferredBluetoothEndpoint)
}
"Quick Share'a genel bakış" videosunda 29:31'deki Kotlin snippet'i
// Final API may undergo further updates
val quickShareClient = QuickShareClient.create(activity)
val attachment = FileAttachment(
  fileName = "report.pdf",
  size = 1_048_576L,
  uri = fileUri,
  mimeType = "application/pdf",
  // Sensitive content will be masked in preview
  isSensitiveContent = false,
)

val content = ShareableContent.withFiles(listOf(attachment))
val request = SharingRequest.withContent(content)
val session = quickShareClient.startSharingSession(request, lifecycleOwner)
"Quick Share'e genel bakış" videosunda 29:57'deki Kotlin snippet'i
// Final API may undergo further updates
val quickShareClient = QuickShareClient.create(activity)
val request = SharingRequest.withoutContent()
val session = quickShareClient.startSharingSession(request, lifecycleOwner)

// Open the Quick Share overlay in receive mode
session.launchWindow(activity, contentSelectionIntent = null)
"Quick Share'e genel bakış" videosunda 30:23'teki Kotlin snippet'i
// Final API may undergo further updates
val quickShareClient = QuickShareClient.create(activity)
val urlAttachment = TextAttachment(
  text = groupAddUrl,
  type = TextAttachment.Type.URL,
)

val content = ShareableContent.withText(urlAttachment)
val appLink = AppLink("https://myapp.com/group/invite")
val request = SharingRequest.withContent(content, appLink)
val session = quickShareClient.startSharingSession(request, lifecycleOwner)
"Quick Share'a genel bakış" videosunda 30:49'daki Kotlin snippet'i
// Final API may undergo further updates
scope.launch {
  for (event in session.sharingEvents) {
    when (event) {
      is SharingEvent.SendComplete ->
        println("Send finished")
      is SharingEvent.ReceiveComplete ->
        println("Received, files=${event.content?.files?.size}")
      else -> println("other event")
    }
  }
}