Sencha Ext JS ile Uygulama Geliştirin

Bu dokümanın amacı, Sencha Ext JS ile Chrome Uygulamaları geliştirmeye başlamanızı sağlamaktır. bahsedeceğim. Bu hedefe ulaşmak için Sencha'nın geliştirdiği medya oynatıcı uygulamasını inceleyeceğiz. Kaynak kodu ve API Belgeleri'ni GitHub'da bulabilirsiniz.

Bu uygulama, kullanıcının PC'ye bağlı medya cihazları da dahil olmak üzere kullanılabilir medya sunucularını keşfeder ve ağ üzerinden medyayı yöneten bir yazılımdır. Kullanıcılar medyaya göz atabilir, ağ üzerinde içerik oynatabilir ve kaydedebilir. çevrimdışı.

Sencha Ext JS kullanarak medya oynatıcı uygulaması oluşturmak için yapmanız gereken önemli şeyler:

  • Manifest oluşturun, manifest.json.
  • background.js adlı etkinlik sayfasını oluşturun.
  • Sandbox uygulamasının mantığı.
  • Chrome uygulaması ile korumalı alana alınan dosyalar arasında iletişim kurar.
  • Medya sunucularını keşfedin.
  • Medya keşfedin ve oynatın.
  • Medyayı çevrimdışına kaydet.

Manifest oluştur

Tüm Chrome uygulamaları için Chrome'un başlatması gereken bilgileri içeren bir manifest dosyası gerekir. Manifest dosyasında belirtildiği gibi, medya oynatıcı uygulaması "çevrimdışı_enabled" medya öğelerini yerel olarak kaydedilir, kullanılır ve bağlantı durumu dikkate alınmaksızın oynanabilir.

"Korumalı alan" alanı, uygulamanın ana mantığını benzersiz bir kaynakta korumalı alana almak için kullanılır. Tümü korumalı alana alındı içerik, Chrome Uygulaması İçerik Güvenliği Politikası'ndan muaf olsa da Chrome Uygulaması API'leri Manifest, izin; medya oynatıcı uygulaması socket API'yi kullanarak ağ üzerinden bir medya sunucusuna bağlanabilirsiniz.

{
    "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"
            ]
        }
    ]
}

Etkinlik sayfası oluştur

Tüm Chrome Uygulamaları'nın başlatılması için background.js gereklidir. Medya oynatıcının ana sayfası index.html, belirtilen boyutlarla bir pencerede açılır:

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;
    });

});

Korumalı alan uygulamasının mantığı

Chrome Uygulamaları, katı bir İçerik Güvenliği Politikası'nı zorunlu kılan kontrollü bir ortamda çalışır (İGP). Medya oynatıcı uygulamasının Ext JS bileşenlerini oluşturmak için daha yüksek ayrıcalıklara ihtiyacı var. Alıcı: CSP'ye uymalı ve uygulama mantığını yürütmelidir. Uygulamanın ana sayfası (index.html), bir korumalı alan ortamı olarak işlev görür:

<iframe id="sandbox-frame" sandbox="allow-scripts" src="sandbox.html"></iframe>

iframe, Ext JS için gerekli dosyaları içeren sandbox.html adresine işaret eder. uygulama:

<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>

app.js komut dosyası, tüm Ext JS kodunu yürütür ve medya oynatıcı görünümlerini oluşturur. Bu tarihten itibaren komut dosyası korumalı alana alındıysa Chrome Uygulama API'lerine doğrudan erişemez. app.js arasındaki iletişim ve korumalı alana alınmamış dosyalar da HTML5 Post Message API kullanılarak yapılır.

Dosyalar arasında iletişim kurma

Medya oynatıcı uygulamasının Chrome Uygulama API'lerine erişebilmesi için ağda medya sorgulaması gibi işlemler yapmak üzere sunucular, app.js iletileri index.js dosyasına gönderir. Korumalı alana alınan app.js uygulamasından farklı olarak index.js şunları yapabilir: doğrudan Chrome Uygulama API'lerine erişebilir.

index.js, iframe'i oluşturur:

var iframe = document.getElementById('sandbox-frame');

iframeWindow = iframe.contentWindow;

Ayrıca, korumalı alana alınan dosyalardan gelen mesajları dinler:

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);

Aşağıdaki örnekte app.js, index.js adlı alıcıya anahtar isteğinde bulunan bir mesaj gönderiyor "extension-baseurl":

Ext.data.PostMessage.request({
    key: 'extension-baseurl',
    success: function(data) {
        //...
    }
});

index.js isteği alır, sonucu atar ve Temel URL'yi geri göndererek yanıt verir:

function extensionBaseUrl(data) {
    data.result = chrome.extension.getURL('/');
    iframeWindow.postMessage(data, '*');
}

Medya sunucularını keşfedin

Medya sunucularını keşfetmenin pek çok yönü vardır. Keşif iş akışı genel hatlarıyla Mevcut medya sunucularını aramak için bir kullanıcı işlemi tarafından başlatılır. MediaServer denetleyicisi index.js adresine bir ileti gönderdiğinde; index.js bu mesajı dinler ve alındığında telefon eder Upnp.js.

Upnp library, medya oynatıcı uygulamasını herhangi bir cihaza bağlamak için Chrome Uygulaması socket API'sini kullanır. bulduğunda ve medya sunucusundan medya verileri aldığında. Upnp.js tarafından da kullanılıyor Medya sunucusu verilerini ayrıştırmak için soapclient.js. Bu bölümün geri kalanında, daha ayrıntılı değineceğiz.

Mesajı yayınla

Kullanıcı, medya oynatıcı uygulamasının ortasındaki Medya Sunucuları düğmesini tıkladığında MediaServers.js discoverServers() araması yapıyor. Bu işlev öncelikle bekleyen keşif isteklerini ve true ise yeni isteğin başlatılabilmesi için bunları iptal eder. Ardından kumanda, Bir anahtar upnp keşfi ve iki geri arama dinleyicisi ile index.js:

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');
    }
});

upnpKeşfet() işlevini çağırın

index.js, "upnp-Keşfet" şarkısını dinliyor app.js adlı kişiden mesaj var ve telefonla yanıt veriyor upnpDiscover(). Bir medya sunucusu keşfedildiğinde index.js, medya sunucusu alanını çıkarır sunucuyu yerel olarak kaydeder, medya sunucusu verilerini biçimlendirir ve verileri MediaServer kumandası.

Medya sunucusu verilerini ayrıştır

Upnp.js yeni bir medya sunucusu keşfettiğinde cihazın açıklamasını alıp Medya sunucusu verilerine göz atmak ve ayrıştırmak için bir Soap isteği; soapclient.js, medya öğelerini ayrıştırır etiket adına göre bir dokümana ekleyebilirsiniz.

Medya sunucusuna bağlan

Upnp.js, keşfedilen medya sunucularına bağlanır ve medya verilerini Chrome Uygulama yuvasını kullanarak alır. 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);
        });
    });
});

Medya keşfetme ve oynatma

MediaGezgin denetleyicisi, medya sunucusu klasöründeki tüm medya dosyalarını listeler ve medya oynatıcı uygulama penceresinde içerik haritası gezinmesinin güncellenmesinden sorumludur. Kullanıcı bir medya dosyası seçtiğinde kumanda, index.js uygulamasına "play-media" öğesi içeren bir mesaj gönderir anahtar:

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 bu yayın mesajını dinler ve playMedia() numaralı telefonu arayarak yanıt verir:

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);
}

Medyayı çevrimdışına kaydet

Medyayı çevrimdışı kaydetmeyle ilgili zor işlemlerin çoğu filer.js kitaplığı tarafından gerçekleştirilir. Web sitemiz g.co/newsinitiative/labs üzerinden bu kitaplığı filer.js tanıtımı'nda bulabilirsiniz.

İşlem, kullanıcı bir veya daha fazla dosya seçip "Çevrimdışı al" işlemini başlattığında başlar eyleme dökülebilir. MediaGezgin denetleyicisi, index.js adresine "download-media" anahtarı içeren bir mesaj gönderir; index.js bu mesajı dinler vedownloadMedia() indirme işlemi:

function downloadMedia(data) {
        DownloadProcess.run(data.params.files, function() {
            data.result = true;
            sendMessage(data);
        });
    }

DownloadProcess yardımcı program yöntemi, medya sunucusundan veri almak için bir xhr isteği oluşturur ve tamamlanma durumunu bekler. Bu işlem, alınan içeriği kontrol eden onload geri çağırmasını başlatır ve filer.js işlevini kullanarak verileri yerel olarak kaydeder:

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);
    }
);

İndirme işlemi tamamlandığında MediaExplorer, medya dosyası listesini ve medyayı günceller. oyuncu ağacı paneli.