Ücretsiz APK oluştur

JavaScript köprü API'si

Medya ve yayınlama

Sayfanızın yönettiği kilit ekranı medya bildirimi ve bir videoyu televizyona aktarma.

navigator.mediaSession web standardı#

navigator.mediaSession + MediaMetadata

Örnek

Sayfanızın oynattığı içeriği bir medya bildiriminde ve kilit ekranında gösterir; Önceki / Oynat-Duraklat / Sonraki / Durdur düğmeleri sayfanıza geri çağrı yapar. Normal Media Session API kullanılır.

Döndürür: hiçbir şey; düğmelere basıldığında, standartta olduğu gibi { action } ile, setActionHandler ile ayarladığınız işleyiciler çağrılır. Gerekenler: derleme yaparken 4. Adım'da (Erişim) Medya Bildirimi seçeneğini açın. Kod bunu kullandığında yapay zekayla oluşturulan uygulamalarda bu seçenek sizin için açılır navigator.mediaSession.

var audio = document.getElementById('player');
var tracks = [
  { src: 'https://example.com/a.mp3', title: 'Morning', artist: 'Band', art: 'https://example.com/a.jpg' },
  { src: 'https://example.com/b.mp3', title: 'Evening', artist: 'Band', art: 'https://example.com/b.jpg' }
];
var index = 0;
var handlersReady = false;

function setupHandlers() {
  if (handlersReady || !('mediaSession' in navigator)) return;
  handlersReady = true;
  var ms = navigator.mediaSession;
  ms.setActionHandler('play', function () { audio.play(); });
  ms.setActionHandler('pause', function () { audio.pause(); });
  ms.setActionHandler('nexttrack', function () { playTrack(index + 1); });
  ms.setActionHandler('previoustrack', function () { playTrack(index - 1); });
  ms.setActionHandler('stop', function () { audio.pause(); audio.currentTime = 0; });
}

function playTrack(i) {
  index = (i + tracks.length) % tracks.length;
  var t = tracks[index];
  audio.src = t.src;
  audio.play();
  setupHandlers();   // on the first play, not at page load (see Notes)
  if ('mediaSession' in navigator && window.MediaMetadata) {
    navigator.mediaSession.metadata = new MediaMetadata({
      title: t.title, artist: t.artist, album: '',
      artwork: [{ src: t.art, sizes: '512x512', type: 'image/jpeg' }]
    });
  }
}

document.getElementById('play-btn').addEventListener('click', function () { playTrack(0); });

Oynat/duraklat düğmesini ve ilerleme çubuğunu doğru tutun:

function publishState() {
  if (!('mediaSession' in navigator)) return;
  navigator.mediaSession.playbackState = audio.paused ? 'paused' : 'playing';   // set this FIRST
  if (audio.duration > 0 && navigator.mediaSession.setPositionState) {
    navigator.mediaSession.setPositionState({
      duration: audio.duration, position: audio.currentTime, playbackRate: 1
    });
  }
}
audio.addEventListener('play', publishState);
audio.addEventListener('pause', publishState);
audio.addEventListener('seeked', publishState);

Bildirimdeki Sonraki / Önceki düğmelerinin bölümü değiştirmek yerine 30 saniye ileri ve 15 saniye geri atladığı bir podcast oynatıcı:

var audio = document.getElementById('player');
function skip(seconds) {
  var end = audio.duration || 0;
  audio.currentTime = Math.max(0, Math.min(end, audio.currentTime + seconds));
  if ('mediaSession' in navigator && navigator.mediaSession.setPositionState && end > 0) {
    navigator.mediaSession.setPositionState({ duration: end, position: audio.currentTime });
  }
}
if ('mediaSession' in navigator) {
  navigator.mediaSession.setActionHandler('play', function () { audio.play(); });
  navigator.mediaSession.setActionHandler('pause', function () { audio.pause(); });
  navigator.mediaSession.setActionHandler('nexttrack', function () { skip(30); });
  navigator.mediaSession.setActionHandler('previoustrack', function () { skip(-15); });
  if (window.MediaMetadata) {
    navigator.mediaSession.metadata = new MediaMetadata({
      title: 'Episode 12: Getting started', artist: 'My Podcast',
      artwork: [{ src: 'https://example.com/podcast-512.jpg', sizes: '512x512' }]
    });
  }
}

Notlar:

  • Uygulamada navigator.mediaSession, sayfanın ilk betiğinden önce kurulur; bu yüzden işleyiciler ve meta veriler her zaman - sayfanın başında veya oynatma başladığında - ayarlanabilir. Ana sayfada bulunur, iframe'lerin içinde değil.
  • Desteklenen eylemler: play, pause, nexttrack, previoustrack, stop. Bildirimden atlama desteklenmez, bu yüzden seekto asla tetiklenmez.
  • playbackState ayarlamak, son setPositionState çağrınızdaki konumu korur; konum gerçekten değiştiğinde (bir atlama) setPositionState işlevini yeniden çağırın.
  • Yalnızca son kapak resmi kullanılır. İnternette tam bir https:// adresi olmalıdır (uygulama onu indirir, 4 sn sınırı vardır); uygulama ZIP'inizin içindeki bir dosya görünmez.
  • <audio> / <video> öğeleri sizin için izlenir: sayfa bir düğmeyi ne setActionHandler ne de kendi window.WebToApkOnMediaAction işleviyle ele almadığında, Oynat / Duraklat / Durdur çalan medya öğesini (yoksa en son oynatılanı, o da yoksa ilkini) denetler.
  • Bildirimi kaldırmak için WebToApk.clearMediaNotification() çağırın (metadata = null ayarlamak onu kaldırmaz).
  • window.WebToApkOnMediaAction = function (action) { ... } tanımlayan bir sayfa (eylemler play, pause, next, prev, stop) her düğme basışını orada da alır - uygulama artık onun üzerine yazmaz. İkisinden birini kullanın, ikisini birden değil; yoksa bir basış iki kez çalışır.

requestPictureInPicture web standardı#

video.requestPictureInPicture() — Picture-in-Picture

Örnek

Standart Resim içinde Resim API'si: kullanıcı başka bir şey yaparken bir videoyu küçük bir pencerede yüzdürün. Android'deki Chrome'da vardır, Android'in WebView'ında yoktur; uygulamada video, Chrome'daki gibi yüzen pencereyi doldurur.

Döndürür: bir PictureInPictureWindow için Promise (width, height, resize olayı). Video önce enterpictureinpicture, kullanıcı pencereyi kapatınca veya genişletince leavepictureinpicture alır; bu arada document.pictureInPictureElement videodur. Dokunma olmadan NotAllowedError, videonun meta verileri yüklenmeden önce veya disablePictureInPicture olduğunda InvalidStateError ile reddedilir. Gerekenler: derlemede Resim içinde resim açık (kodunuz requestPictureInPicture çağırınca kendiliğinden açılır), Android 8 veya daha yeni.

<video id="v" src="clip.mp4" controls playsinline></video>
<button id="pip">Pop out</button>
<script>
const v = document.getElementById('v');
const btn = document.getElementById('pip');
btn.hidden = !document.pictureInPictureEnabled;
btn.addEventListener('click', async () => {
  try {
    if (document.pictureInPictureElement) await document.exitPictureInPicture();
    else await v.requestPictureInPicture();
  } catch (e) {
    console.warn('Picture-in-Picture:', e.name);
  }
});
v.addEventListener('enterpictureinpicture', () => { btn.textContent = 'Back to app'; });
v.addEventListener('leavepictureinpicture', () => { btn.textContent = 'Pop out'; });
</script>

Kullanıcı ayrıldığında otomatik olarak açılın ve desteklenmeyen bir derlemeyi bildirin:

const v = document.getElementById('v');
if (!document.pictureInPictureEnabled || v.disablePictureInPicture) {
  document.getElementById('pip').hidden = true;      // this build has no picture-in-picture
}
document.addEventListener('visibilitychange', async () => {
  if (document.hidden && !v.paused && !document.pictureInPictureElement) {
    try { await v.requestPictureInPicture(); }
    catch (e) { console.warn(e.name); }               // NotAllowedError without a tap
  }
});

Meta verileri bekleyin ve pencereyle birlikte yeniden boyutlandırın:

async function popOut(video) {
  if (video.readyState < 1) await new Promise((r) => video.addEventListener('loadedmetadata', r, { once: true }));
  try {
    const pipWin = await video.requestPictureInPicture();
    pipWin.addEventListener('resize', () => console.log(pipWin.width, pipWin.height));
  } catch (e) {
    if (e.name === 'InvalidStateError') showMessage('This video cannot float.');
    else if (e.name === 'NotAllowedError') showMessage('Tap the button to pop out.');
  }
}
document.getElementById('pip').onclick = () => popOut(document.getElementById('v'));

Notlar: Android tüm uygulamayı kayan pencereye koyar; bu yüzden video önce tek başına (tam ekran) gösterilir ve pencere videonun şeklini alır; pencereden çıkınca video sayfaya geri döner. document.exitPictureInPicture() uygulamayı tam ekrana geri getirir. Derlemede pencere içinde pencere (PiP) yoksa document.pictureInPictureEnabled değeri, bu özelliği olmayan bir tarayıcıdaki gibi false olur. Mod değişikliği sayfaya appmint:pip olarak ulaşır. Dahili aktarım yolları: __pipEnter, __pipExit, __pipAvailable, __pipPrepare.

__pipAvailable köprü#

window.WebToApk.__pipAvailable(): Boolean

video.requestPictureInPicture() çalışabilir mi: derlemede PiP açık, Android 8+.

Örnek

WebToApk.__pipEnter ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.

video.requestPictureInPicture() ve document.exitPictureInPicture() arkasındaki dahili aktarım. Sayfalar standart API'yi kullanır; bunları asla doğrudan çağırmayın, çünkü __ yöntemleri haber verilmeden değişebilir.

Döndürür: __pipEnter(width, height), Android pencereyi kabul ettiğinde (videonun en-boy oranıyla) "ok", aksi halde "unsupported" / "failed" döndürür. Pencerenin açılıp kapanması {inPip} ile appmint:pip olarak gelir. __pipAvailable(), derlemede Android 8+ üzerinde resim içinde resim açıksa doğrudur. Gerekenler: derlemede Resim içinde resim açık.

Genel API'yi kullanın:

const video = document.querySelector('video');
button.addEventListener('click', () => video.requestPictureInPicture());

Önce desteği denetleyin ve reddi bildirin:

async function floatVideo(video) {
  if (!document.pictureInPictureEnabled) { showMessage('Picture-in-picture is not on in this app.'); return; }
  try {
    await video.requestPictureInPicture();
  } catch (err) {
    showMessage('Could not open the floating window.');
  }
}

Tekrar çıkın ve durumu standart olaylarla izleyin:

video.addEventListener('enterpictureinpicture', () => hideControls());
video.addEventListener('leavepictureinpicture', () => showControls());
closeBtn.onclick = () => { if (document.pictureInPictureElement) document.exitPictureInPicture(); };

Notlar: Uygulama kabuğunda (PictureInPictureShim.kt) uygulanır. __pipPrepare, kabuğun pencereye geçerken tam ekran adımı için ekranı yana çevirmesini engeller.

__pipEnter köprü#

window.WebToApk.__pipEnter(width: Int, height: Int): String

PiP penceresini [width]×[height] boyutlu bir videonun en boy oranıyla açar: "ok" veya "unsupported" / "failed". Mod değişikliği şu olarak gelir: `appmint:pip`.

Örnek

video.requestPictureInPicture() ve document.exitPictureInPicture() arkasındaki dahili aktarım. Sayfalar standart API'yi kullanır; bunları asla doğrudan çağırmayın, çünkü __ yöntemleri haber verilmeden değişebilir.

Döndürür: __pipEnter(width, height), Android pencereyi kabul ettiğinde (videonun en-boy oranıyla) "ok", aksi halde "unsupported" / "failed" döndürür. Pencerenin açılıp kapanması {inPip} ile appmint:pip olarak gelir. __pipAvailable(), derlemede Android 8+ üzerinde resim içinde resim açıksa doğrudur. Gerekenler: derlemede Resim içinde resim açık.

Genel API'yi kullanın:

const video = document.querySelector('video');
button.addEventListener('click', () => video.requestPictureInPicture());

Önce desteği denetleyin ve reddi bildirin:

async function floatVideo(video) {
  if (!document.pictureInPictureEnabled) { showMessage('Picture-in-picture is not on in this app.'); return; }
  try {
    await video.requestPictureInPicture();
  } catch (err) {
    showMessage('Could not open the floating window.');
  }
}

Tekrar çıkın ve durumu standart olaylarla izleyin:

video.addEventListener('enterpictureinpicture', () => hideControls());
video.addEventListener('leavepictureinpicture', () => showControls());
closeBtn.onclick = () => { if (document.pictureInPictureElement) document.exitPictureInPicture(); };

Notlar: Uygulama kabuğunda (PictureInPictureShim.kt) uygulanır. __pipPrepare, kabuğun pencereye geçerken tam ekran adımı için ekranı yana çevirmesini engeller.

__pipExit köprü#

window.WebToApk.__pipExit()

document.exitPictureInPicture(): uygulamayı tam ekrana geri getirir.

Örnek

WebToApk.__pipEnter ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.

video.requestPictureInPicture() ve document.exitPictureInPicture() arkasındaki dahili aktarım. Sayfalar standart API'yi kullanır; bunları asla doğrudan çağırmayın, çünkü __ yöntemleri haber verilmeden değişebilir.

Döndürür: __pipEnter(width, height), Android pencereyi kabul ettiğinde (videonun en-boy oranıyla) "ok", aksi halde "unsupported" / "failed" döndürür. Pencerenin açılıp kapanması {inPip} ile appmint:pip olarak gelir. __pipAvailable(), derlemede Android 8+ üzerinde resim içinde resim açıksa doğrudur. Gerekenler: derlemede Resim içinde resim açık.

Genel API'yi kullanın:

const video = document.querySelector('video');
button.addEventListener('click', () => video.requestPictureInPicture());

Önce desteği denetleyin ve reddi bildirin:

async function floatVideo(video) {
  if (!document.pictureInPictureEnabled) { showMessage('Picture-in-picture is not on in this app.'); return; }
  try {
    await video.requestPictureInPicture();
  } catch (err) {
    showMessage('Could not open the floating window.');
  }
}

Tekrar çıkın ve durumu standart olaylarla izleyin:

video.addEventListener('enterpictureinpicture', () => hideControls());
video.addEventListener('leavepictureinpicture', () => showControls());
closeBtn.onclick = () => { if (document.pictureInPictureElement) document.exitPictureInPicture(); };

Notlar: Uygulama kabuğunda (PictureInPictureShim.kt) uygulanır. __pipPrepare, kabuğun pencereye geçerken tam ekran adımı için ekranı yana çevirmesini engeller.

__pipPrepare köprü#

window.WebToApk.__pipPrepare()

Sayfa, PiP için bir videoyu tam ekrana almak üzere: bunun için yatay yönü zorlamayın.

Örnek

WebToApk.__pipEnter ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.

video.requestPictureInPicture() ve document.exitPictureInPicture() arkasındaki dahili aktarım. Sayfalar standart API'yi kullanır; bunları asla doğrudan çağırmayın, çünkü __ yöntemleri haber verilmeden değişebilir.

Döndürür: __pipEnter(width, height), Android pencereyi kabul ettiğinde (videonun en-boy oranıyla) "ok", aksi halde "unsupported" / "failed" döndürür. Pencerenin açılıp kapanması {inPip} ile appmint:pip olarak gelir. __pipAvailable(), derlemede Android 8+ üzerinde resim içinde resim açıksa doğrudur. Gerekenler: derlemede Resim içinde resim açık.

Genel API'yi kullanın:

const video = document.querySelector('video');
button.addEventListener('click', () => video.requestPictureInPicture());

Önce desteği denetleyin ve reddi bildirin:

async function floatVideo(video) {
  if (!document.pictureInPictureEnabled) { showMessage('Picture-in-picture is not on in this app.'); return; }
  try {
    await video.requestPictureInPicture();
  } catch (err) {
    showMessage('Could not open the floating window.');
  }
}

Tekrar çıkın ve durumu standart olaylarla izleyin:

video.addEventListener('enterpictureinpicture', () => hideControls());
video.addEventListener('leavepictureinpicture', () => showControls());
closeBtn.onclick = () => { if (document.pictureInPictureElement) document.exitPictureInPicture(); };

Notlar: Uygulama kabuğunda (PictureInPictureShim.kt) uygulanır. __pipPrepare, kabuğun pencereye geçerken tam ekran adımı için ekranı yana çevirmesini engeller.

castMedia köprü#

window.WebToApk.castMedia(mediaUrl: String)

[mediaUrl] adresini, bu telefonda onu başka bir ekranda oynatabilen her şeye - Chromecast, bir Akıllı TV uygulaması, yerel bir oynatıcı - sistem seçicisi üzerinden sunar. Tür URL'den alınır ([CastMediaType]): bir ses dosyası (.mp3, .m4a, .aac, .ogg, .opus, .wav, .flac …) veya bir ses `data:` URL'si ses uygulamalarına, diğer her şey - video dosyaları, akış bildirimleri, uzantısız URL'ler - video uygulamalarına sunulur. Bu bir devir işlemidir, yayın oturumu değil: uygulama oynatmanın denetimini elinde tutmaz ve geri çağrı yoktur. Gerçek oturuma ihtiyaç duyan bir sayfa bunun yerine JavaScript'te Cast SDK'sını kullanmalıdır.

Örnek

Bir video veya ses adresini, telefondaki onu başka bir ekranda oynatabilen uygulamalara (bir Chromecast uygulaması, bir Akıllı TV uygulaması, bir video oynatıcı) Android "Yayınla..." seçicisi üzerinden sunar.

Döndürür: hiçbir şey ve geri çağırma yok. Gerekenler: açılacak bir şey yok. Telefonda bağlantıyı kabul eden bir uygulama olmalı.

function castToTv(url) {
  if (window.WebToApk && typeof window.WebToApk.castMedia === 'function') {
    window.WebToApk.castMedia(url);          // opens the "Cast to..." chooser
  } else {
    alert('Casting is only available in the app');
  }
}

document.getElementById('cast-btn').addEventListener('click', function () {
  var video = document.querySelector('video');
  var url = video && video.currentSrc ? video.currentSrc : 'https://example.com/movie.mp4';
  castToTv(url);
});

Listeden bir podcast bölümünü bir hoparlör veya TV uygulamasına gönderin (bir .mp3 bağlantısı ses uygulamalarına sunulur):

// <li><button class="cast" data-src="https://example.com/ep12.mp3">Cast</button> Episode 12</li>
document.getElementById('episodes').addEventListener('click', function (e) {
  var btn = e.target.closest('button.cast');
  if (!btn) return;
  var src = btn.getAttribute('data-src') || '';
  if (src.indexOf('https://') !== 0) {
    alert('This episode cannot be cast');   // files inside the app cannot be handed over
    return;
  }
  if (window.WebToApk && typeof window.WebToApk.castMedia === 'function') {
    window.WebToApk.castMedia(src);
  }
});

Yayın düğmesini yalnızca uygulamanın içinde gösterin ve canlı yayını devretmeden önce sayfanın kendi oynatıcısını duraklatın:

var castBtn = document.getElementById('cast-live');
var canCast = !!(window.WebToApk && typeof window.WebToApk.castMedia === 'function');
castBtn.hidden = !canCast;

castBtn.addEventListener('click', function () {
  var video = document.getElementById('live');
  video.pause();                                   // avoid playing twice, here and on the TV
  window.WebToApk.castMedia('https://example.com/live/stream.m3u8');   // offered to video apps
});

Notlar:

  • Bu bir devretmedir, yayın oturumu değildir: kullanıcı bir uygulama seçtikten sonra sayfanız oynatmayı denetlemez.
  • Adres, diğer uygulamaların açabileceği tam bir https:// bağlantısı olmalıdır. Uygulama ZIP'inizdeki bir dosya, bir blob: URL'si veya bir web sayfası adresi oynatılmaz.
  • Tür bağlantıdan gelir: bir ses dosyası (.mp3, .m4a, .aac, .ogg, .opus, .wav, .flac …) veya bir audio/ data: URL'si ses uygulamalarına sunulur; diğer her şey - video dosyaları, .m3u8 akışları, dosya uzantısı olmayan bağlantılar - video uygulamalarına.

clearMediaNotification köprü#

window.WebToApk.clearMediaNotification()

Web içeriğinin Android medya tarzı bildirimini yönetmesini ve kilit ekranından ile bildirim panelinden aktarım denetimi geri çağırmalarını (oynat/duraklat/sonraki/önceki) almasını sağlar. JavaScript'ten kullanım: window.WebToApk.setMediaMetadata('Song Title', 'Artist Name', 'https://…/art.jpg') window.WebToApk.setPlaybackState(true, 30000, 240000) // oynuyor, konum ms, süre ms window.WebToApk.clearMediaNotification() Android → JS geri çağırması: window.WebToApkOnMediaAction('play'|'pause'|'next'|'prev'|'stop')

Tek başına değil, grubu olan Medya Bildirim Köprüsü altında açıklanır.

Örnek

Medya bildirimini ve kilit ekranı denetimlerini kaldırır; örneğin kullanıcı oynatıcınızı kapattığında.

Döndürür: hiçbir şey. Gerekenler: derleme sırasında 4. Adım'da (Erişim) Medya Bildirimi seçeneğini açın. Açık değilse çağrı hiçbir şey yapmaz.

Bunun için standart bir web çağrısı yoktur, bu yüzden köprüyü kullanın:

function closePlayer() {
  var audio = document.getElementById('player');
  audio.pause();
  audio.currentTime = 0;
  if (window.WebToApk && typeof window.WebToApk.clearMediaNotification === 'function') {
    window.WebToApk.clearMediaNotification();
  }
}

document.getElementById('close-player').addEventListener('click', closePlayer);

// The notification's own Stop button already removes it; just stop your audio:
if ('mediaSession' in navigator) {
  navigator.mediaSession.setActionHandler('stop', function () {
    var audio = document.getElementById('player');
    audio.pause();
    audio.currentTime = 0;
  });
}

Seçilen dakika sayısı sonunda sesi durduran ve bildirimi kaldıran bir uyku zamanlayıcısı:

var sleepTimer = null;
function setSleepTimer(minutes) {
  clearTimeout(sleepTimer);
  sleepTimer = setTimeout(function () {
    var audio = document.getElementById('player');
    audio.pause();
    if (window.WebToApk && typeof window.WebToApk.clearMediaNotification === 'function') {
      window.WebToApk.clearMediaNotification();
    }
  }, minutes * 60 * 1000);
}
document.getElementById('sleep-30').addEventListener('click', function () { setSleepTimer(30); });

Bir oynatma listesinin son parçası bittiğinde, boşuna bir Oynat düğmesi bırakmak yerine bildirimi kaldırın:

var audio = document.getElementById('player');
var playlist = ['https://example.com/1.mp3', 'https://example.com/2.mp3'];
var current = 0;

audio.addEventListener('ended', function () {
  current++;
  if (current < playlist.length) {
    audio.src = playlist[current];
    audio.play();
  } else if (window.WebToApk && typeof window.WebToApk.clearMediaNotification === 'function') {
    window.WebToApk.clearMediaNotification();
  }
});

Notlar: Bunu "duraklat" için değil, "durdur" için kullanın (duraklatmak için setPlaybackState(false, ...) gönderin; böylece Oynat düğmesi kalır). navigator.mediaSession.metadata = null ayarı bildirimi kaldırmaz. Sonraki setMediaMetadata / setPlaybackState (veya yeni navigator.mediaSession meta verisi / durumu) bildirimi ve kilit ekranı denetimlerini geri getirir.

setMediaMetadata köprü#

window.WebToApk.setMediaMetadata(title: String, artist: String, artworkUrl: String)

Web içeriğinin Android medya tarzı bildirimini yönetmesini ve kilit ekranından ile bildirim panelinden aktarım denetimi geri çağırmalarını (oynat/duraklat/sonraki/önceki) almasını sağlar. JavaScript'ten kullanım: window.WebToApk.setMediaMetadata('Song Title', 'Artist Name', 'https://…/art.jpg') window.WebToApk.setPlaybackState(true, 30000, 240000) // oynuyor, konum ms, süre ms window.WebToApk.clearMediaNotification() Android → JS geri çağırması: window.WebToApkOnMediaAction('play'|'pause'|'next'|'prev'|'stop')

Tek başına değil, grubu olan Medya Bildirim Köprüsü altında açıklanır.

Örnek

Medya bildiriminin ve kilit ekranı oynatıcısının başlığını, sanatçısını ve kapak resmini ayarlar. Sayfalar normalde bunu sizin için çağıran navigator.mediaSession.metadata özelliğini ayarlar.

Döndürür: hiçbir şey. Gerekenler: derleme sırasında 4. Adım'da (Erişim) Medya Bildirimi seçeneğini açın. Açık değilse çağrı hiçbir şey yapmaz.

Herkese açık yol (bunu kullanın):

if ('mediaSession' in navigator && window.MediaMetadata) {
  navigator.mediaSession.metadata = new MediaMetadata({
    title: 'Episode 12', artist: 'My Podcast',
    artwork: [{ src: 'https://example.com/cover.jpg', sizes: '512x512' }]
  });
}

Ham çağrı. Argümanlar: title, artist, artworkUrl (resim yoksa '' kullanın):

function showNowPlaying(track) {
  if (!(window.WebToApk && typeof window.WebToApk.setMediaMetadata === 'function')) return;
  window.WebToApk.setMediaMetadata(track.title, track.artist || '', track.cover || '');
  window.WebToApk.setPlaybackState(true, 0, Math.round(track.seconds * 1000));
}

// Buttons in the notification come back through the standard API:
if ('mediaSession' in navigator) {
  navigator.mediaSession.setActionHandler('nexttrack', function () { playNext(); });
  navigator.mediaSession.setActionHandler('previoustrack', function () { playPrevious(); });
}

Şarkının yeni bir dosya yüklemeden değiştiği canlı bir radyo yayını için bildirimin başlığını güncel tutun:

var lastSong = '';
function refreshNowPlaying() {
  fetch('https://example.com/radio/now-playing.json')
    .then(function (r) { return r.json(); })
    .then(function (np) {            // e.g. { "title": "...", "artist": "...", "cover": "https://..." }
      var key = np.title + '|' + np.artist;
      if (key === lastSong) return;  // only update when the song really changed
      lastSong = key;
      if (window.WebToApk && typeof window.WebToApk.setMediaMetadata === 'function') {
        window.WebToApk.setMediaMetadata(np.title || 'Live radio', np.artist || '', np.cover || '');
      }
    })
    .catch(function () { /* try again on the next tick */ });
}
document.getElementById('radio').addEventListener('play', function () {
  refreshNowPlaying();
  setInterval(refreshNowPlaying, 30000);
}, { once: true });

Notlar:

  • Bildirim bu çağrıyla görünür (veya güncellenir). Boş bir başlık uygulama adını gösterir.
  • artworkUrl internet üzerindeki tam bir https:// adresi olmalıdır. Uygulama onu indirir (4 saniye sınırı); başarısız olursa uygulama simgesi gösterilir.
  • Düğme basışlarını navigator.mediaSession.setActionHandler ile (bkz. navigator.mediaSession) veya kendi window.WebToApkOnMediaAction = function (action) { ... } işlevinizle (play, pause, next, prev, stop) alın - ikisinden birini kullanın. clearMediaNotification() sonrasında, buna (veya setPlaybackState) yapılan bir sonraki çağrı bildirimi ve kilit ekranı denetimlerini geri getirir.

setPlaybackState köprü#

window.WebToApk.setPlaybackState(isPlaying: Boolean, positionMs: Long, durationMs: Long)

Web içeriğinin Android medya tarzı bildirimini yönetmesini ve kilit ekranından ile bildirim panelinden aktarım denetimi geri çağırmalarını (oynat/duraklat/sonraki/önceki) almasını sağlar. JavaScript'ten kullanım: window.WebToApk.setMediaMetadata('Song Title', 'Artist Name', 'https://…/art.jpg') window.WebToApk.setPlaybackState(true, 30000, 240000) // oynuyor, konum ms, süre ms window.WebToApk.clearMediaNotification() Android → JS geri çağırması: window.WebToApkOnMediaAction('play'|'pause'|'next'|'prev'|'stop')

Tek başına değil, grubu olan Medya Bildirim Köprüsü altında açıklanır.

Örnek

Medya bildirimine oynatıp oynatmadığınızı veya duraklatıp duraklatmadığınızı ve parçada nerede olduğunuzu söyler. Sayfalar normalde bunu sizin için çağıran navigator.mediaSession.playbackState ayarlar ve setPositionState çağırır.

Döndürür: hiçbir şey. Gerekenler: derleme sırasında 4. Adım'da (Erişim) Medya Bildirimi seçeneğini açın. Açık değilse çağrı hiçbir şey yapmaz.

Herkese açık yol (bunu kullanın):

var audio = document.getElementById('player');
function publish() {
  if (!('mediaSession' in navigator)) return;
  navigator.mediaSession.playbackState = audio.paused ? 'paused' : 'playing';
  if (audio.duration > 0 && navigator.mediaSession.setPositionState) {
    navigator.mediaSession.setPositionState({ duration: audio.duration, position: audio.currentTime });
  }
}
audio.addEventListener('play', publish);
audio.addEventListener('pause', publish);

Ham çağrı. Argümanlar: isPlaying (true/false), positionMs, durationMs (tam milisaniye):

function publishRaw(audio) {
  if (!(window.WebToApk && typeof window.WebToApk.setPlaybackState === 'function')) return;
  window.WebToApk.setPlaybackState(
    !audio.paused,
    Math.floor(audio.currentTime * 1000),
    Math.floor((audio.duration || 0) * 1000)
  );
}

Kullanıcı atladıktan sonra yeni konumu bildirin ve parça bittiğinde bildirimi Oynat'a geçirin:

var audio = document.getElementById('player');
function report(playing) {
  if (!(window.WebToApk && typeof window.WebToApk.setPlaybackState === 'function')) return;
  var durMs = Math.floor((audio.duration || 0) * 1000);
  var posMs = Math.floor(audio.currentTime * 1000);
  window.WebToApk.setPlaybackState(playing, Math.min(posMs, durMs || posMs), durMs);
}
audio.addEventListener('seeked', function () { report(!audio.paused); });
audio.addEventListener('ended', function () { report(false); });   // Play button, notification can be swiped away

Notlar: true Duraklat düğmesini gösterir ve bildirimin kaydırılıp kapatılmasını engeller; false Oynat düğmesini gösterir. Bildirimin bir başlığı olması için önce setMediaMetadata çağırın. Kullanıcı durdurduğunda bildirimi kaldırmak için şunu çağırın: clearMediaNotification().

Her belge derlemesinde uygulama çalışma zamanından ve örnek dosyalarından oluşturulur. Markdown olarak okuyun · Tüm aileler.

22.10.2026 tarihinde yayınlanan köprüyle karşılaştırılarak kontrol edildi.