Ten dokument pomoże Ci zacząć tworzyć aplikacje Chrome przy użyciu interfejsu Sencha Ext JS. platformy. Aby osiągnąć ten cel, skupimy się na aplikacji odtwarzacza multimediów opracowanej przez firmę Sencha. Źródło i dokumentację API znajdziesz na GitHubie.
Ta aplikacja wykrywa dostępne serwery multimediów użytkownika, w tym urządzenia multimedialne podłączone do komputera do zarządzania multimediami w sieci. Użytkownicy mogą przeglądać multimedia, odtwarzać treści przez sieć lub zapisywać treści offline.
Oto najważniejsze czynności, które musisz wykonać, aby utworzyć aplikację odtwarzacza multimediów za pomocą Sencha Ext JS:
- Utwórz plik manifestu,
manifest.json
. - Utwórz stronę wydarzenia,
background.js
. - Logika aplikacji Sandbox.
- Komunikacja między aplikacją Chrome a plikami w piaskownicy.
- Wykrywanie serwerów multimediów.
- Odkrywaj i odtwarzaj multimedia.
- Zapisuj multimedia offline.
Utwórz plik manifestu
Wszystkie aplikacje Chrome wymagają pliku manifestu zawierającego informacje potrzebne do uruchomienia Chrome. aplikacji. Zgodnie z plikiem manifestu aplikacja odtwarzacza multimediów ma stan „offline_enabled”; zasobów multimedialnych można zapisywany lokalnie, dostępny i odtwarzany niezależnie od połączenia.
Piaskownica służy do podziału głównej logiki aplikacji w piaskownicy w unikalnym źródle. Wszystkie w trybie piaskownicy treść jest wykluczona z zasad Content Security Policy w aplikacji Chrome, ale nie ma bezpośredniego dostępu do Interfejsy API aplikacji Chrome. Plik manifestu zawiera też pole „socket” uprawnienia; aplikacja odtwarzacza korzysta z socket API do nawiązania połączenia z serwerem multimediów przez sieć.
{
"name": "Video Player",
"description": "Features network media discovery and playlist management",
"version": "1.0.0",
"manifest_version": 2,
"offline_enabled": true,
"app": {
"background": {
"scripts": [
"background.js"
]
}
},
...
"sandbox": {
"pages": ["sandbox.html"]
},
"permissions": [
"experimental",
"http://*/*",
"unlimitedStorage",
{
"socket": [
"tcp-connect",
"udp-send-to",
"udp-bind"
]
}
]
}
Utwórz stronę wydarzenia
Wszystkie aplikacje Chrome wymagają uprawnienia background.js
do uruchomienia aplikacji. na stronie głównej odtwarzacza,
index.html
– otwiera się w oknie o określonych wymiarach:
chrome.app.runtime.onLaunched.addListener(function(launchData) {
var opt = {
width: 1000,
height: 700
};
chrome.app.window.create('index.html', opt, function (win) {
win.launchData = launchData;
});
});
Logika aplikacji Sandbox
Aplikacje Chrome działają w kontrolowanym środowisku, które wymusza rygorystyczne zasady Content Security Policy
(CSP). Aplikacja odtwarzacza multimediów potrzebuje wyższych uprawnień, aby renderować komponenty Ext JS. Do
są zgodne z CSP i wykonują logikę aplikacji – jej główna strona (index.html
) tworzy element iframe, który
działa jak środowisko piaskownicy:
<iframe id="sandbox-frame" sandbox="allow-scripts" src="sandbox.html"></iframe>
Element iframe wskazuje stronę sandbox.html, która zawiera pliki wymagane przez Ext JS aplikacja:
<html>
<head>
<link rel="stylesheet" type="text/css" href="resources/css/app.css" />'
<script src="sdk/ext-all-dev.js"></script>'
<script src="lib/ext/data/PostMessage.js"></script>'
<script src="lib/ChromeProxy.js"></script>'
<script src="app.js"></script>
</head>
<body></body>
</html>
Skrypt app.js wykonuje cały kod Ext JS i renderuje widoki odtwarzacza. Ponieważ
znajduje się w piaskownicy, nie ma bezpośredniego dostępu do interfejsów API aplikacji Chrome. Komunikacja między app.js
a poza nią odbywa się to za pomocą interfejsu HTML5 Post Message API.
Komunikacja między plikami
Aby aplikacja odtwarzacza mogła uzyskiwać dostęp do interfejsów API aplikacji Chrome (na przykład wysyłać zapytania do sieci w poszukiwaniu multimediów)
z serwerów, app.js
publikuje wiadomości w pliku index.js. W przeciwieństwie do app.js
w trybie piaskownicy index.js
może
bezpośrednio uzyskiwać dostęp do interfejsów API aplikacji Chrome.
index.js
tworzy element iframe:
var iframe = document.getElementById('sandbox-frame');
iframeWindow = iframe.contentWindow;
Nasłuchuje wiadomości z plików w trybie piaskownicy:
window.addEventListener('message', function(e) {
var data= e.data,
key = data.key;
console.log('[index.js] Post Message received with key ' + key);
switch (key) {
case 'extension-baseurl':
extensionBaseUrl(data);
break;
case 'upnp-discover':
upnpDiscover(data);
break;
case 'upnp-browse':
upnpBrowse(data);
break;
case 'play-media':
playMedia(data);
break;
case 'download-media':
downloadMedia(data);
break;
case 'cancel-download':
cancelDownload(data);
break;
default:
console.log('[index.js] unidentified key for Post Message: "' + key + '"');
}
}, false);
W poniższym przykładzie app.js
wysyła do użytkownika index.js
wiadomość z prośbą o klucz
„extension-baseurl”:
Ext.data.PostMessage.request({
key: 'extension-baseurl',
success: function(data) {
//...
}
});
index.js
odbiera żądanie, przypisuje wynik i odpowiada, odsyłając podstawowy adres URL:
function extensionBaseUrl(data) {
data.result = chrome.extension.getURL('/');
iframeWindow.postMessage(data, '*');
}
Odkrywaj serwery multimediów
Znajdowanie serwerów multimediów wymaga sporo pracy. Ogólnie proces odkrywania jest
zainicjowane przez działanie użytkownika w celu wyszukania dostępnych serwerów multimediów. kontroler serwera multimediów,
publikuje wiadomość w: index.js
; index.js
nasłuchuje tej wiadomości, a po jej otrzymaniu – połączenia
Upnp.js.
Upnp library
używa interfejsu socket API aplikacji Chrome, aby połączyć aplikację odtwarzacza z dowolnym
wykryte serwery multimediów i odbierają z niego dane. Upnp.js
używa też:
Plik soapclient.js umożliwia przeanalizowanie danych serwera multimediów. Informacje na ten temat znajdują się w pozostałej części niniejszej sekcji.
o tym więcej szczegółów.
Opublikuj wiadomość
Gdy użytkownik kliknie przycisk Serwery multimediów pośrodku aplikacji odtwarzacza MediaServers.js
dzwoni pod numer discoverServers()
. Ta funkcja najpierw sprawdza, czy nie ma żadnych oczekujących żądań wykrywania i jeśli
true (prawda) spowoduje przerwanie tych żądań, aby można było zainicjować nowe żądanie. Następnie kontroler wysyła wiadomość do
index.js
z kluczem upnp-discovery i 2 detektorami wywołań zwrotnych:
me.activeDiscoverRequest = Ext.data.PostMessage.request({
key: 'upnp-discover',
success: function(data) {
var items = [];
delete me.activeDiscoverRequest;
if (serversGraph.isDestroyed) {
return;
}
mainBtn.isLoading = false;
mainBtn.removeCls('pop-in');
mainBtn.setIconCls('ico-server');
mainBtn.setText('Media Servers');
//add servers
Ext.each(data, function(server) {
var icon,
urlBase = server.urlBase;
if (urlBase) {
if (urlBase.substr(urlBase.length-1, 1) === '/'){
urlBase = urlBase.substr(0, urlBase.length-1);
}
}
if (server.icons && server.icons.length) {
if (server.icons[1]) {
icon = server.icons[1].url;
}
else {
icon = server.icons[0].url;
}
icon = urlBase + icon;
}
items.push({
itemId: server.id,
text: server.friendlyName,
icon: icon,
data: server
});
});
...
},
failure: function() {
delete me.activeDiscoverRequest;
if (serversGraph.isDestroyed) {
return;
}
mainBtn.isLoading = false;
mainBtn.removeCls('pop-in');
mainBtn.setIconCls('ico-error');
mainBtn.setText('Error...click to retry');
}
});
Wywołaj funkcję upnpDiscover()
index.js
nasłuchuje funkcji „upnp-discover” wiadomość od użytkownika app.js
i odpowiada, dzwoniąc
upnpDiscover()
Po wykryciu serwera multimediów index.js
wyodrębnia jego domenę
z parametrów, zapisuje serwer lokalnie, formatuje dane serwera multimediów i przesyła je do
kontrolera MediaServer
.
Analizuj dane serwera multimediów
Po wykryciu nowego serwera multimediów Upnp.js
pobiera opis urządzenia i wysyła
żądanie Soaprequest do przeglądania i analizowania danych serwera multimediów; soapclient.js
analizuje elementy multimedialne
według nazwy tagu.
Połącz z serwerem multimediów
Upnp.js
łączy się ze znalezionymi serwerami multimediów i odbiera dane multimedialne przez gniazdo aplikacji Chrome
Interfejs API:
socket.create("udp", {}, function(info) {
var socketId = info.socketId;
//bind locally
socket.bind(socketId, "0.0.0.0", 0, function(info) {
//pack upnp message
var message = String.toBuffer(UPNP_MESSAGE);
//broadcast to upnp
socket.sendTo(socketId, message, UPNP_ADDRESS, UPNP_PORT, function(info) {
// Wait 1 second
setTimeout(function() {
//receive
socket.recvFrom(socketId, function(info) {
//unpack message
var data = String.fromBuffer(info.data),
servers = [],
locationReg = /^location:/i;
//extract location info
if (data) {
data = data.split("\r\n");
data.forEach(function(value) {
if (locationReg.test(value)){
servers.push(value.replace(locationReg, "").trim());
}
});
}
//success
callback(servers);
});
}, 1000);
});
});
});
Odkrywaj i odtwarzaj multimedia
Kontroler MediaEksplorator wyświetla listę wszystkich plików multimedialnych znajdujących się w folderze serwera multimediów.
odpowiada za aktualizację nawigacji menu nawigacyjnego w oknie aplikacji odtwarzacza. Gdy użytkownik
wybierze plik multimedialny, kontroler wyśle do index.js
wiadomość z wiadomością „play-media” klucz:
onFileDblClick: function(explorer, record) {
var serverPanel, node,
type = record.get('type'),
url = record.get('url'),
name = record.get('name'),
serverId= record.get('serverId');
if (type === 'audio' || type === 'video') {
Ext.data.PostMessage.request({
key : 'play-media',
params : {
url: url,
name: name,
type: type
}
});
}
},
index.js
słucha tego posta i odpowiada, dzwoniąc pod numer playMedia()
:
function playMedia(data) {
var type = data.params.type,
url = data.params.url,
playerCt = document.getElementById('player-ct'),
audioBody = document.getElementById('audio-body'),
videoBody = document.getElementById('video-body'),
mediaEl = playerCt.getElementsByTagName(type)[0],
mediaBody = type === 'video' ? videoBody : audioBody,
isLocal = false;
//save data
filePlaying = {
url : url,
type: type,
name: data.params.name
};
//hide body els
audioBody.style.display = 'none';
videoBody.style.display = 'none';
var animEnd = function(e) {
//show body el
mediaBody.style.display = '';
//play media
mediaEl.play();
//clear listeners
playerCt.removeEventListener( 'transitionend', animEnd, false );
animEnd = null;
};
//load media
mediaEl.src = url;
mediaEl.load();
//animate in player
playerCt.addEventListener( 'transitionend', animEnd, false );
playerCt.style.transform = "translateY(0)";
//reply postmessage
data.result = true;
sendMessage(data);
}
Zapisywanie multimediów offline
Większość ciężkiej pracy przy zapisywaniu multimediów offline wykonuje się przy użyciu biblioteki filer.js. Możesz dowiedzieć się więcej tę bibliotekę znajdziesz w artykule Przedstawiamy pliker.js.
Proces zaczyna się, gdy użytkownik wybierze co najmniej 1 plik i zainicjuje funkcję „Przejdź offline” działania.
Kontroler MediaEksplorator przesyła do index.js
komunikat z kluczem „download-media”.
index.js
nasłuchuje tej wiadomości i wywołuje funkcję downloadMedia()
, aby zainicjować
proces pobierania:
function downloadMedia(data) {
DownloadProcess.run(data.params.files, function() {
data.result = true;
sendMessage(data);
});
}
Metoda narzędzia DownloadProcess
tworzy żądanie xhr, aby pobrać dane z serwera multimediów i
czeka na stan ukończenia. To inicjuje wywołanie zwrotne onload, które sprawdza otrzymaną treść.
i zapisuje dane lokalnie za pomocą funkcji filer.js
:
filer.write(
saveUrl,
{
data: Util.arrayBufferToBlob(fileArrayBuf),
type: contentType
},
function(fileEntry, fileWriter) {
console.log('file saved!');
//increment downloaded
me.completedFiles++;
//if reached the end, finalize the process
if (me.completedFiles === me.totalFiles) {
sendMessage({
key : 'download-progresss',
totalFiles : me.totalFiles,
completedFiles : me.completedFiles
});
me.completedFiles = me.totalFiles = me.percentage = me.downloadedFiles = 0;
delete me.percentages;
//reload local
loadLocalFiles(callback);
}
},
function(e) {
console.log(e);
}
);
Po zakończeniu pobierania MediaExplorer
zaktualizuje listę plików multimedialnych i multimediów
panelu drzewa odtwarzacza.