Tworzenie aplikacji za pomocą Sencha Ext JS

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.