JSON Abfrage auf dem Samsung Smart TV
Im TV App Tutorial werden wir heute eine AJAX-Abfrage an einen Server schicken. Dieser liefert einen JSON-String zurück, der dann auf dem Samsung Smart TV empfangen wird. Das Ganze machen wir, um die einzelnen Videos online vom Server abzuholen.
Ich werde die Videos erstmal relativ statisch mit PHP als JSON ausgeben lassen, hier könnt ihr das natürlich beliebig erweitern. Fangen wir doch einfach mal mit zwei kleinen Videos an:
<?php $videos = array( array("title" => "How will Google interpret links to URLs ending with a campaign tag?", "author" => "GoogleWebmasterHelp", "player" => "youtube", "id" => "qr2Rg8sJRUU", "thumb" => "http://smart-tv.stevieswebsite.de/thumbs/matt-cutts-url-ending.jpg"), array("title" => "'Not' Venice Update | Alpha9 Talk", "author" => "alpha9marketing", "player" => "youtube", "id" => "qjUGbQIdJtk", "thumb" => "http://smart-tv.stevieswebsite.de/thumbs/not-venise.jpg")); echo json_encode($videos); ?>
Ich gebe hier einfach folgende Daten an:
- title Titel des Videos
- author Autor
- player Erstmal unterstützen wir nur YouTube, später können hier auch andere rein.
- id Die ID bei dem Video-Anbieter (aus der Url bei YouTube entnommen)
- thumb Adresse eines Bildausschnitts des Videos
Bevor wir jetzt anfangen die JSON Abfrage zu machen, müssen wir noch eine neue Klasse im Projekt anlegen. Diese ist unter /app/javascript/Category.js gesperichert und repräsentiert wie zu erwarten eine einzelne Kategorie. Auch enthalten ist die Funktion loadVideos, die aus der Menu.js kopiert wurde (dort hieß sie loadDummyVideos):
function Category() { this.title = ""; this.tag = ""; this.menuEntry = false; //Lädt die Videos in den Screen this.loadVideos = function() { document.getElementById('videolist').innerHTML = ""; //6 Videos hinzufügen for(var i = 1;i<=6;i++) { //Video erstellen var video = new Video(); video.title = this.title + " " + i; video.author = "Stefan Wienströer"; video.playUrl = "/tutorial-smart-tv-app-entwickeln/"; video.previewImage = "http://www.contentlion.de/content/uploads/doku/seite-anlegen-525.jpg"; document.getElementById('videolist').innerHTML += video.GetTeaserCode(); } }; //Liefert den Menüeintrag zurück this.GetMenuEntry = function() { if(!this.menuEntry) { //Nachladen this.menuEntry= new MenuEntry(); this.menuEntry.OnActivate = this.loadVideos; } //Titel kann sich geändert haben, also immer neu setzen this.menuEntry.title = this.title; //Weg damit return this.menuEntry; }; }
Ich habe auch die Funktion GetMenuEntry hinzugefügt, die den Menüeintrag zurückliefert. Dieser wurde ja bisher in der Menu.js erstellt. Und genau diese können wir nun so verändern, dass auch hier die Category-Klasse genutzt wird:
//----- Gekürzt ----- document.body.appendChild(a); //und fokussieren... a.focus(); }; var seo = new Category(); seo.title = "SEO"; seo.tag = "seo"; this.AddEntry(seo.GetMenuEntry()); //Social Media var socialmedia = new Category(); socialmedia.title = "Social Media"; socialmedia.tag = "social-media"; this.AddEntry(socialmedia.GetMenuEntry()); //Entwickler var developer = new Category(); developer.title = "Entwickler"; developer.tag = "developer"; this.AddEntry(developer.GetMenuEntry()); //CMS var cms = new Category(); cms.title = "CMS"; cms.tag = "cms"; this.AddEntry(cms.GetMenuEntry()); //Als Default werden die Neuvorstellungen gewählt seo.GetMenuEntry().Activate(); //Versteckten Fokus hinzufügen this.AddFocus(); };
Zu guter letzt müssen wir unsere neue Category.js auch in die index.html laden. Das geht so:
<!-- gekürzt --> <script language="javascript" type="text/javascript" src="app/javascript/Video.js"></script> <script language="javascript" type="text/javascript" src="app/javascript/Category.js"></script> <link rel="stylesheet" href="app/stylesheets/Main.css" type="text/css"> <!-- gekürzt -->
Wenn du nun die App erneut starten, wird dir bestimmt etwas ganz cooles auffallen: Es hat sich nichts verändert. Aber wir haben jetzt die Struktur so umgebaut, dass wir nun tatsächlich mit dem Auslesen des JSONs beginnen können. Jede Kategorie hat bei mir ein eigenes JSON-File auf dem Server. Euch ist eben vielleicht aufgefallen, dass es eine Eigenschaft namens „tag“ gab. In dieser wird der Name gespeichert, mit dem wir die Url aufbauen.
Im nächsten Schritt fragen wir die Videos per JSON vom Server ab. Das funktioniert so:
function Category() { this.title = ""; this.tag = ""; this.menuEntry = false; //Lädt die Videos in den Screen this.loadVideos = function() { document.getElementById('videolist').innerHTML = ""; this.GetVideos(function(videos){ //Videos hinzufügen for(var i = 0;i<=videos.length;i++) { document.getElementById('videolist').innerHTML += videos[i].GetTeaserCode(); } }); }; //Liefert den Menüeintrag zurück this.GetMenuEntry = function() { if(!this.menuEntry) { //Nachladen this.menuEntry= new MenuEntry(); this.menuEntry.tag = this; this.menuEntry.OnActivate = function(){ this.tag.loadVideos(); }; } //Titel kann sich geändert haben, also immer neu setzen this.menuEntry.title = this.title; //Weg damit return this.menuEntry; }; this.GetVideos = function(callback) { var res = new Array(); var xmlhttp = null; // Mozilla if (window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest(); } // IE else if (window.ActiveXObject) { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } //Kategorie abfragen xmlhttp.open("GET", 'http://smart-tv.stevieswebsite.de/' + this.tag + '.php', true); xmlhttp.onreadystatechange = function() { if(xmlhttp.readyState == 4 && xmlhttp.status == 200) { //Abfrage erfolgreich. Parsen wir das JSON! obj = JSON.parse(xmlhttp.responseText); for(var i = 0;i < obj.length; i++) { //Videos erstellen var video = new Video(); video.title = obj[i].title; video.author = obj[i].author; video.previewImage = obj[i].thumb; res[res.length] = video; } //Callback aufrufen callback(res); } }; //Abfrage starten xmlhttp.send(null); }; }
Da wir hier mit einer Serverabfrage arbeiten, müssen wir auch warten, bis diese zu Ende durchgeführt wurde. Deshalb arbeiten wir mit einem Callback, der die Videos nach erfolgreiche Abfrage der Ansicht hinzufügt.
Nach dem Start der App, sehen wir folgendes:
Wie ihr seht, sind die Titel viel zu lang. Aber das ist kein Problem. Zwei kleine Änderungen an der /app/stylesheets/Main.css und die Sache passt:
.video_teaser { font-weight:lighter; float:left; padding-right:15px; height:250px; width:200px } .video_teaser h2{ margin-top:5px; color:#b00000; font-size:1em; font-weight:lighter; }
Das Ergebnis des heutigen Artikels sieht wie folgt aus. Später darf ich mir noch ein paar mehr Videos heraussuchen, die ich anzeigen kann:
Hier kann auch wieder mein aktueller Stand heruntergeladen werden.
Du arbeitest in einer Agentur oder als Freelancer?
Dann wirf doch mal einen Blick auf unsere Software FeatValue.
Kommentare
Eugen schrieb am 08.12.2012:
Hallo, folgender Code funktioniert nicht: obj = JSON.parse(xmlhttp.responseText); Das JSON fehlt. Da muss wohl noch ein weiteres JS geladen werden. Wäre super, wenn du das noch nachtragen würdest.
Stefan Wienströer schrieb am 09.12.2012:
JSON ist fester Bestandteil von JavaScript ;-)
Gajan schrieb am 10.04.2013:
Hallo bekomme folgenden fehler [JS ERROR]: File: file://c/Program%20Files%20(x86)/Samsung/Samsung%20TV%20SDK%204/apps/_temp_20100108_/app/javascript/Category.js Line No: 16 Error Detail: TypeError: 'undefined' is not an object (evaluating 'videos[i].GetTeaserCode') kannst du mir weiterghelfen?
Stefan Wienströer schrieb am 10.04.2013:
Das Objekt videos[i] wird nicht gefunden. Kannst du mal schreiben, was bei dir in der Category.js um Zeile 16 steht?
Gajan schrieb am 11.04.2013:
Habs herausgefunden. Es war ein Loop zuviel und es gab eine leerlauf bzw. keine Daten. Da das Loop/for bei 0 anfängt, sollte es bei Zeile 14 for(var i = 0;i<videos.length;i++) heissen; anstatt ...i<=videos... (gekürzt)
Über uns

Wir entwickeln Webanwendungen mit viel Leidenschaft. Unser Wissen geben wir dabei gerne weiter. Mehr über a coding project