L'objectif de ce document est de vous aider à créer des applications Chrome avec Sencha Ext JS. d'infrastructure. Pour atteindre cet objectif, nous allons découvrir une application de lecteur multimédia conçue par Sencha. La source du code et la documentation de l'API sont disponibles sur GitHub.
Cette appli détecte les serveurs multimédias disponibles d'un utilisateur, y compris les appareils multimédias connectés à un PC et des logiciels qui gèrent les contenus multimédias sur le réseau. Les utilisateurs peuvent parcourir les contenus multimédias, les lire via le réseau ou enregistrer hors connexion.
Voici les principales étapes à suivre pour créer une application de lecteur multimédia à l'aide de Sencha Ext JS:
- Créez le fichier manifeste
manifest.json
. - Créez la page de l'événement
background.js
. - La logique d'une application bac à sable.
- Communication entre l'application Chrome et les fichiers en bac à sable
- Découvrir les serveurs multimédias
- Explorez et lisez les contenus multimédias.
- Enregistrer des contenus multimédias hors connexion
Créer un fichier manifeste
Toutes les applications Chrome nécessitent un fichier manifeste contenant les informations nécessaires au lancement de Chrome. applications. Comme indiqué dans le fichier manifeste, l'application de lecteur multimédia est "offline_enabled" (hors connexion). les assets multimédias peuvent être enregistrées localement, consultées et lues quelle que soit la connectivité.
Le "bac à sable" est utilisé pour mettre en bac à sable la logique principale de l'application dans une origine unique. En bac à sable est exempté du Content Security Policy de l'application Chrome, mais ne peut pas y accéder directement. API Chrome App. Le fichier manifeste inclut également le "socket" Autorisation l'application de lecture multimédia utilise API de socket pour se connecter à un serveur de contenus sur le réseau.
{
"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"
]
}
]
}
Page "Créer un événement"
Toutes les applications Chrome nécessitent background.js
pour lancer l'application. La page principale du lecteur multimédia
index.html
s'ouvre dans une fenêtre avec les dimensions spécifiées:
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;
});
});
Logique de l'application sandbox
Les applications Chrome s'exécutent dans un environnement contrôlé qui applique une Content Security Policy stricte
(CSP). L'application de lecteur multimédia nécessite des droits plus élevés pour afficher les composants JS ext. À
est conforme à CSP et exécute la logique de l'application, la page principale de l'application, index.html
, qui crée un iFrame qui
agit comme un environnement de bac à sable:
<iframe id="sandbox-frame" sandbox="allow-scripts" src="sandbox.html"></iframe>
L'iFrame pointe vers sandbox.html, qui inclut les fichiers requis pour l'extension JS application:
<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>
Le script app.js exécute tout le code JS ext et affiche les vues du lecteur multimédia. Étant donné que
est exécuté en bac à sable, il ne peut pas accéder directement aux API Chrome App. Communication entre app.js
et hors bac à sable se fait à l'aide de l'API HTML5 Post Message.
Communiquer entre les fichiers
Pour que l'application de lecture multimédia puisse accéder aux API de l'application Chrome (par exemple, interroger le réseau pour des contenus multimédias)
serveurs, app.js
publie des messages dans index.js. Contrairement au app.js
en bac à sable, index.js
peut
accéder directement aux API Chrome App.
index.js
crée l'iFrame:
var iframe = document.getElementById('sandbox-frame');
iframeWindow = iframe.contentWindow;
Il écoute également les messages des fichiers en bac à sable:
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);
Dans l'exemple suivant, app.js
envoie un message à index.js
demandant la clé.
'extension-baseurl':
Ext.data.PostMessage.request({
key: 'extension-baseurl',
success: function(data) {
//...
}
});
index.js
reçoit la requête, attribue le résultat et répond en renvoyant l'URL de base:
function extensionBaseUrl(data) {
data.result = chrome.extension.getURL('/');
iframeWindow.postMessage(data, '*');
}
Découvrir des serveurs multimédias
Il y a beaucoup de choses qui entrent dans
la découverte des serveurs multimédias. De manière générale, le workflow de découverte
initiée par une action de l'utilisateur pour rechercher
les serveurs multimédias disponibles. Le contrôleur MediaServer
publie un message à l'adresse index.js
; index.js
écoute ce message et appelle
Upnp.js :
Le Upnp library
utilise l'API de socket de l'application Chrome pour connecter l'application de lecteur multimédia aux
les serveurs de médias découverts
et reçoivent des données multimédias du serveur. Upnp.js
utilise aussi
soapclient.js pour analyser les données du serveur multimédia Le reste de cette section décrit ce processus
le workflow de ML.
Publier le message
Lorsqu'un utilisateur clique sur le bouton "Serveurs multimédias" au centre de l'application de lecture multimédia, MediaServers.js
appelle discoverServers()
. Cette fonction vérifie d'abord les demandes de découverte en attente, et si
true, les annule pour que la nouvelle requête puisse être lancée. Ensuite, le contrôleur
publie un message sur
index.js
avec une clé upnp-discovery et deux écouteurs de rappel:
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');
}
});
Appeler upnpDiscover()
index.js
écoute l'événement "upnp-discover". de app.js
et répond en appelant
upnpDiscover()
Lorsqu'un serveur multimédia est détecté, index.js
extrait le domaine du serveur multimédia
des paramètres, enregistre le serveur localement, met en forme les données du serveur multimédia et les transmet
le contrôleur MediaServer
.
Analyser les données du serveur multimédia
Lorsque Upnp.js
détecte un nouveau serveur multimédia, il récupère une description de l'appareil et l'envoie
une requête Soaprequest pour parcourir et analyser les données du serveur multimédia ; soapclient.js
analyse les éléments multimédias
par nom de tag dans un document.
Se connecter au serveur multimédia
Upnp.js
se connecte aux serveurs multimédias détectés et reçoit les données multimédias à l'aide du socket d'application Chrome
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);
});
});
});
Explorer et lire des contenus multimédias
Le contrôleur MediaExplorer répertorie tous les fichiers multimédias d'un dossier de serveur multimédia et est
qui est chargé de mettre à jour la navigation dans le fil d'Ariane dans la fenêtre de l'application du lecteur multimédia. Lorsqu'un utilisateur
sélectionne un fichier multimédia, la manette publie un message sur index.js
avec l'étiquette "play-media" clé:
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
écoute ce message et répond en appelant 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);
}
Enregistrer des contenus multimédias hors connexion
L'enregistrement de contenus multimédias hors connexion est principalement effectué par la bibliothèque filer.js. Pour en savoir plus, cette bibliothèque dans l'article Présentation de filer.js.
Le processus est lancé lorsqu'un utilisateur sélectionne un ou plusieurs fichiers et lance l'action "Hors connexion". action.
Le contrôleur MediaExplorer publie un message sur index.js
avec une clé "download-media".
index.js
écoute ce message et appelle la fonction downloadMedia()
pour lancer la
processus de téléchargement:
function downloadMedia(data) {
DownloadProcess.run(data.params.files, function() {
data.result = true;
sendMessage(data);
});
}
La méthode utilitaire DownloadProcess
crée une requête xhr pour obtenir les données du serveur multimédia.
attend l'état d'avancement. Cela lance le rappel de chargement qui vérifie le contenu reçu
et enregistre les données localement à l'aide de la fonction 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);
}
);
Une fois le téléchargement terminé, MediaExplorer
met à jour la liste des fichiers multimédias et les contenus multimédias
dans l'arborescence des joueurs.