Ders 12 / 24
Medya ve Aygıt API'leri
İzin gerektiren yeteneklere erişim; iznin durumları ve ön koşulları, güvenli bağlam ile kullanıcı hareketi gereği, yetenek saptama ile zarif düşüş, medya izlerinin yaşam döngüsü ve konum erişiminin gizlilik dengesi.
İçindekiler
Yerel ayar, saat dilimi ve dil tercihi kullanıcının cihazından izin sorulmadan okunur; bunlar sayfanın zaten bildiği bilgilerdir. Ölçüm istasyonu sayfasının isteyeceği başka şeyler de vardır: ölçümün alındığı noktanın koordinatları, bir arıza kaydına eklenecek fotoğraf, sesli not.
Bunların hiçbiri sorulmadan verilmez. Aralarındaki ortak nokta, kullanıcının cihazından dışarı bilgi taşımalarıdır. Tarayıcı bu yetenekleri ortak bir izin düzeneğinin arkasına koyar ve düzenek bir kez öğrenildiğinde hepsine uygulanır.
İzin Gerektiren Yetenekler
Yetenekler üç kümeye ayrılır.
İzin gerektirmeyenler, cihazın kullanıcıyı tanımlamayan genel özellikleridir: görünüm alanı ölçüleri, dil tercihi, saat dilimi, bağlantının çevrimiçi olup olmadığı. Bunlar sorulmadan okunur.
Açık izin gerektirenler, kullanıcının çevresinden veri toplayanlardır: kamera, mikrofon, konum, ekran paylaşımı, hareket ve yönelim sensörleri, panonun okunması, bildirim gönderme.
Kullanıcı hareketiyle sınırlananlar, izin sormayan ama kendiliğinden çalıştırılamayan yeteneklerdir: tam ekrana geçmek, dosya seçtirmek, ekranı uyanık tutmak, panoya yazmak. Bunlar yalnızca kullanıcının bir eyleminden doğan olay işlenirken çalışır.
Bir yetenek daha en baştan kapalı olabilir. Gömülü İçerik dersinde tanımlanan yetenek izni bildirimi, bir çerçeveye hangi yeteneklerin devredildiğini belirler; devredilmemiş bir yetenek, kullanıcı izin verse de çalışmaz.
İznin Durumları
İzin üç durumdan birinde bulunur: henüz sorulmamış, verilmiş, reddedilmiş. İstek yapıldığında tarayıcı önce ön koşulları sınar, sonra duruma bakar.
// izin.mjs — izin durumu makinesi ve istegin on kosullari function istek(durum, ortam) { if (ortam.guvenliBaglam === false) return { durum, sonuc: "hata: guvenli baglam yok, sorulmadi" }; if (durum === "verildi") return { durum, sonuc: "dogrudan verildi, sorulmadi" }; if (durum === "reddedildi") return { durum, sonuc: "reddedildi, yeniden sorulmadi" }; if (ortam.kullaniciHareketi === false) return { durum, sonuc: "hata: kullanici hareketi yok, sorulmadi" }; return { durum: ortam.yanit, sonuc: `kullaniciya soruldu -> ${ortam.yanit}` }; } const senaryolar = [ ["guvensiz baglam", { guvenliBaglam: false, kullaniciHareketi: true, yanit: "verildi" }], ["hareketsiz cagri", { guvenliBaglam: true, kullaniciHareketi: false, yanit: "verildi" }], ["kullanici kapatti", { guvenliBaglam: true, kullaniciHareketi: true, yanit: "sorulmadi" }], ["kullanici verdi", { guvenliBaglam: true, kullaniciHareketi: true, yanit: "verildi" }], ["ikinci istek", { guvenliBaglam: true, kullaniciHareketi: true, yanit: "verildi" }], ]; let durum = "sorulmadi"; console.log("baslangic durumu:", durum); for (const [ad, ortam] of senaryolar) { const sonuc = istek(durum, ortam); durum = sonuc.durum; console.log(ad.padEnd(18), "->", sonuc.sonuc.padEnd(38), "| durum:", durum); } // Kullanici ayarlardan izni geri aldiginda durum degisir; sayfa bunu yalniz sorarak ogrenir. durum = "reddedildi"; console.log("izin geri alindi ->", istek(durum, { guvenliBaglam: true, kullaniciHareketi: true, yanit: "verildi" }).sonuc);
baslangic durumu: sorulmadi guvensiz baglam -> hata: guvenli baglam yok, sorulmadi | durum: sorulmadi hareketsiz cagri -> hata: kullanici hareketi yok, sorulmadi | durum: sorulmadi kullanici kapatti -> kullaniciya soruldu -> sorulmadi | durum: sorulmadi kullanici verdi -> kullaniciya soruldu -> verildi | durum: verildi ikinci istek -> dogrudan verildi, sorulmadi | durum: verildi izin geri alindi -> reddedildi, yeniden sorulmadi
Beş kural bu çıktıda toplanır.
Güvenli bağlam zorunludur. Şifrelenmemiş bir bağlantı üzerinden sunulan sayfa bu yetenekleri isteyemez; HTTPS’in Rolü dersinde tanımlanan gizlilik güvencesi olmadan kameradan gelen veri ağda açık taşınır. Yerel geliştirme adresi bu kuralın tanımlı istisnasıdır.
Kullanıcı hareketi gerekir. Sayfa yüklenir yüklenmez izin isteyen kod, tarayıcı tarafından reddedilebilir. İstek, kullanıcının bir düğmeye basmasıyla başlayan olay işlenirken yapılır.
Kapatmak reddetmek değildir. Kullanıcı soruyu yanıtlamadan kapattığında durum “sorulmamış” olarak kalır; sonraki istek yeniden sorabilir. Bu, ısrarla sormanın da kapısını açar ve kötüye kullanıldığında tarayıcı istekleri kendiliğinden engeller.
Verilmiş izin yeniden sorulmaz. İkinci istek kullanıcıyı rahatsız etmeden sonuçlanır.
Reddedilmiş izin de yeniden sorulmaz. İstek doğrudan başarısız olur; kullanıcıya gösterilecek şey bir soru değil, izni tarayıcı ayarlarından nasıl açacağını anlatan bir açıklamadır.
İzin durumu ayrıca sorgulanabilir: istekte bulunmadan durumun ne olduğu öğrenilebilir ve durum değiştiğinde bildirim alınabilir. Bu, kullanıcı ayarlardan izni geri aldığında arayüzü güncellemeyi sağlar.
Yetenek Saptama ve Zarif Düşüş
Bir yeteneğin bulunmaması ile reddedilmesi ayrı durumlardır ve ayrı ele alınır.
Yetenek saptama (feature detection), ilgili arayüzün var olup olmadığını çalışma zamanında sınamaktır. Tarayıcı adına ya da sürümüne bakan kod yanlış yoldur: adı sınamak yeteneği sınamaz. Sınama, kullanılacak nesnenin ya da yöntemin varlığına bakarak yapılır ve sonuç olumsuzsa arayüz o seçeneği hiç göstermez.
Bu üç durumun karşılıkları farklıdır. Yetenek yoksa seçenek gösterilmez. Yetenek var ama izin reddedilmişse seçenek gösterilir ve nasıl açılacağı anlatılır. Yetenek var, izin var ama işlem başarısız olduysa hata bildirilir ve yeniden denenebilir.
Her durumda ortak kural şudur: sayfa, yetenek olmadan da işini görmelidir. Konumu okuyamıyorsa kullanıcıdan koordinatı yazmasını ister; kamerayı açamıyorsa dosya seçtirir. Yeteneğe bağımlı tek yol bırakan tasarım, reddeden kullanıcıyı sayfanın dışında bırakır.
Medya İzleri ve Aygıtın Bırakılması
Kamera ya da mikrofon isteği bir akış döndürür. Akış, her biri tek bir kaynağa bağlı izlerden (track) oluşur ve kaynağın serbest bırakılması izlerin durdurulmasına bağlıdır.
// akis.mjs — medya izlerinin yasam dongusu ve aygitin serbest birakilmasi const aygitlar = { kamera: 0, mikrofon: 0 }; // kac iz aygiti kullaniyor const iz = (tur, aygit, ayarlar) => { aygitlar[aygit] += 1; return { tur, aygit, ayarlar, canli: true, durdur() { if (this.canli) { this.canli = false; aygitlar[aygit] -= 1; } }, }; }; function akisAl(kisit) { const izler = []; if (kisit.video) izler.push(iz("video", "kamera", { genislik: 1280, yukseklik: 720 })); if (kisit.ses) izler.push(iz("ses", "mikrofon", { yankiGiderme: true })); return { izler, durdur() { for (const i of this.izler) i.durdur(); } }; } const yaz = (etiket) => console.log(etiket.padEnd(24), "kamera:", aygitlar.kamera, "| mikrofon:", aygitlar.mikrofon); yaz("baslangic"); const akis = akisAl({ video: true, ses: true }); yaz("akis alindi"); console.log("izler:", akis.izler.map((i) => `${i.tur}(${JSON.stringify(i.ayarlar)})`).join(" ")); akis.izler[0].durdur(); // yalniz video izi durduruldu yaz("video izi durduruldu"); akis.izler[0].durdur(); // ikinci durdurma etkisizdir yaz("ayni iz yeniden durduruldu"); akis.durdur(); yaz("akis durduruldu"); console.log("izlerin durumu:", akis.izler.map((i) => `${i.tur}=${i.canli ? "canli" : "bitti"}`).join(" "));
baslangic kamera: 0 | mikrofon: 0
akis alindi kamera: 1 | mikrofon: 1
izler: video({"genislik":1280,"yukseklik":720}) ses({"yankiGiderme":true})
video izi durduruldu kamera: 0 | mikrofon: 1
ayni iz yeniden durduruldu kamera: 0 | mikrofon: 1
akis durduruldu kamera: 0 | mikrofon: 0
izlerin durumu: video=bitti ses=bitti
Dördüncü satır en sık yapılan hatayı gösterir. Görüntü ögesinin kaynağını boşaltmak ya da ögeyi ağaçtan çıkarmak izi durdurmaz; kayıt göstergesi yanmaya devam eder ve kullanıcı sayfanın kendisini dinlediğini düşünür. Aygıt yalnızca her izi tek tek durdurunca serbest kalır. Durdurma işlemi yinelemeye dayanıklıdır: ikinci çağrı sayacı bozmaz.
İstek sırasında verilen kısıtlar, istenen çözünürlük ve ses işleme gibi ayarları bildirir. Bunlar bir dilektir, güvence değil: cihazın sağladığı gerçek ayarlar izden geri okunur ve istenenden farklı olabilir. Kısıtın zorunlu biçimde verilmesi, karşılanamadığında isteğin tümüyle başarısız olması anlamına gelir.
Konum ve Sensörler
Konum erişiminin iki biçimi vardır: tek seferlik okuma ve sürekli izleme. İzleme, konum değiştikçe bildirim üretir ve açıkça bırakılana kadar sürer; bırakılmayan izleme pili tüketir.
İstekte bildirilen yüksek doğruluk isteği, uydu tabanlı konumlandırmayı devreye sokabilir; bu daha yavaş ve daha pahalıdır. Ölçüm noktasının hangi vadide olduğunu bilmek için gerekli olan doğruluk ile kaldırımın hangi tarafında durulduğunu bilmek için gerekli doğruluk aynı değildir; istenmeyen doğruluk istenmez.
Gelen konumun bir doğruluk yarıçapı vardır ve bu değer arayüze yansıtılmalıdır; tek bir nokta göstermek, elde olmayan bir kesinlik iddia eder. Zaman aşımı ve önbellek yaşı da istekte bildirilir: eski bir okuma kabul edilebilir mi, ne kadar beklenecek.
Hareket ve yönelim sensörleri benzer bir çerçevede durur ve bazı platformlarda ayrıca izin ister. Ölçüm alırken cihazın eğimini kaydetmek gibi bir kullanım, sensör verisinin kullanıcıyı tanımlamaya da yarayabileceği gerçeğiyle birlikte değerlendirilir.
Gizlilik Sözleşmesi
Bu yeteneklerin ortak sözleşmesi dört maddededir. İzin bağlam içinde istenir: kullanıcı neden sorulduğunu anladığı anda, yani ilgili düğmeye bastığında. Toplanan veri en azdır: ölçümün yanına konum eklenecekse tam koordinat yerine istasyon adı yeterli olabilir. Erişim görünürdür: yetenek kullanılırken arayüz bunu gösterir. Ve erişim bırakılır: iş bittiğinde izler durdurulur, izlemeler sonlandırılır.
Özet
- Yetenekler izin gerektirmeyen, açık izin gerektiren ve kullanıcı hareketiyle sınırlanan kümelere ayrılır; çerçevelere devredilmemiş bir yetenek izinle de açılmaz.
- İzin isteği güvenli bağlam ve kullanıcı hareketi ön koşullarına bağlıdır; verilmiş ve reddedilmiş izinler yeniden sorulmaz, kapatılan soru ise durumu değiştirmez.
- Yetenek saptama tarayıcı adına değil arayüzün varlığına bakar; yetenek yokluğu, izin reddi ve işlem hatası ayrı karşılıklar gerektirir.
- Sayfa yetenek olmadan da işini görmelidir; yeteneğe bağımlı tek yol bırakan tasarım reddeden kullanıcıyı dışarıda bırakır.
- Aygıt yalnızca akıştaki her iz durdurulduğunda serbest kalır; ögeyi ağaçtan çıkarmak izi durdurmaz.
- Konumda doğruluk isteği maliyet üretir ve gelen okumanın doğruluk yarıçapı arayüze yansıtılır; izleme açıkça sonlandırılır.
Sonraki Adım
Bu dersteki yeteneklerin çoğu ağır veri üretir: kameradan gelen kareler, sensör okumaları, seçilen bir ölçüm dosyasının binlerce satırı. Bunların işlenmesi ana iş parçacığında yapıldığında Zamanlama ve Çizim Döngüsü dersindeki kare bütçesi tek bir çağrıda tükenir ve arayüz yanıt vermeyi keser. İşi parçalara bölmek gecikmeyi dağıtır ama toplam süreyi kısaltmaz. Sonraki ders, hesabı ana iş parçacığının dışına taşıyan çalışan iş parçacıklarını, aralarındaki ileti geçişini ve bu ayrımın bedelini ele alır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.