Webtechnologien
Sommersemester 2019
Mobile Web Applications
♯
♫
Mobile Web Applications
<section bg="bicycles.jpg" id="mobile-web-applications" class="slide cover"><div><h2>Mobile Web Applications</h2> <p class="note right">Quelle: <a href="http://www.designerspics.com/photographs/bicycles/">Jeshu John</a></p> </div></section> <section class="slide" id="übersicht"><div><h2>Übersicht</h2> <p><img src="installing.png" alt="XKCD" class="right full-height" /></p> <ul> <li>Anwendung die auf Web-Technologien aufbaut</li> <li>Inhärent plattformübergreifend</li> <li>Im Idealfall nicht als Web-App erkennbar, sondern selbes natives Verhalten</li> <li>wachsender Zugang zur Hardware (Accelerometer, GPS …)</li> </ul> <p class="note">Quelle: <a href="http://xkcd.com/1367/">XKCD</a></p> <footer> <ul> <li>andere Bausteine: Persistente Datenhaltung, Offline-Zugang, Homescreen-Icon, Vollbild, <q>Installation</q>, Marktplätze, Bezahlmodelle</li> </ul> </footer> </div></section> <section class="slide" id="vor--und-nachteile"><div><h2>Vor- und Nachteile</h2> <div class="parts "> <div class="part"> <h3 id="vorteile">Vorteile</h3> <ul> <li>Einsteigerfreundlich</li> <li>Günstig / Kostenlos</li> <li>Unternehmensunabhängig</li> <li>Plattformübergreifend</li> <li>Einheitliche Codebase</li> </ul> </div><div class="part"> <h3 id="nachteile">Nachteile</h3> <ul> <li>keine nativen SDKs (+ Look & Feel)</li> <li>reduzierte Möglichkeiten</li> <li>schlechtere Performance (und Kontrolle über RAM etc)</li> <li>Distribution / Payment</li> </ul> </div> </div> <footer> <ul> <li>Schwierig: Push-Notifications, Versionierung, State</li> <li>Aber wir bekommen auch all die tollen Eigenschaften des Web: <ul> <li>Indexierbarkeit</li> <li>Deep Linking</li> <li>reibungslose Updates</li> <li>aufwandsarme Nutzung: Keine aktive Installation, keine initiale Einrichtung, keine Vorab-Rechte-Vergabe, einfach da</li> </ul> </li> </ul> </footer> </div></section> <section class="slide" id="lebenszyklus"><div><h2>Lebenszyklus</h2> <ol> <li>Discovery</li> <li>Installation</li> <li>Launch</li> <li>Background</li> <li>Offline</li> <li>Updates</li> <li>Notifications</li> </ol> </div></section> <section class="slide" id="installation"><div><h2>Installation</h2> <pre class="highlight language-html" data-lang="html"><code><span class="c"><!-- Als Web-App ausweisen und Anwendung im Vollbildmodus anzeigen. --></span> <span class="nt"><meta</span> <span class="na">name=</span><span class="s">"mobile-web-app-capable"</span> <span class="na">content=</span><span class="s">"yes"</span><span class="nt">></span> <span class="nt"><meta</span> <span class="na">name=</span><span class="s">"apple-mobile-web-app-capable"</span> <span class="na">content=</span><span class="s">"yes"</span><span class="nt">></span> <span class="c"><!-- Namen der Anwendung festlegen. --></span> <span class="nt"><meta</span> <span class="na">name=</span><span class="s">"apple-mobile-web-app-title"</span> <span class="na">content=</span><span class="s">"Meine Anwendung"</span><span class="nt">></span> <span class="nt"><meta</span> <span class="na">name=</span><span class="s">"application-name"</span> <span class="na">content=</span><span class="s">"Meine Anwendung"</span><span class="nt">></span> <span class="c"><!-- Windows --></span> <span class="c"><!-- Icon der Anwendung festlegen. --></span> <span class="nt"><link</span> <span class="na">rel=</span><span class="s">"apple-touch-icon"</span> <span class="na">href=</span><span class="s">"/img/icon-precomposed.png"</span><span class="nt">></span> <span class="c"><!-- Startbild der Anwendung festlegen. --></span> <span class="nt"><link</span> <span class="na">rel=</span><span class="s">"apple-touch-startup-image"</span> <span class="na">href=</span><span class="s">"/img/startup.png"</span><span class="nt">></span> </code></pre> <footer> <ul> <li>Konfiguration über Meta-Tags</li> <li>Das Suffix <q>precomposed</q> verhindert Veränderung durch iOS < 7</li> </ul> </footer> </div></section> <section class="slide" id="installation--manifest"><div><h2>Installation – <a href="https://w3c.github.io/manifest/">Manifest</a></h2> <p><img src="theme-color.png" alt="Theme Color" class="right full-height" /></p> <pre class="highlight language-html" data-lang="html"><code><span class="nt"><meta</span> <span class="na">name=</span><span class="s">"theme-color"</span> <span class="na">content=</span><span class="s">"#BADA55"</span><span class="nt">></span> <span class="nt"><link</span> <span class="na">rel=</span><span class="s">"manifest"</span> <span class="na">href=</span><span class="s">"manifest.json"</span><span class="nt">></span> </code></pre> <pre class="highlight language-json" data-lang="json"><code><span class="p">{</span><span class="w"> </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Web Application Sample"</span><span class="p">,</span><span class="w"> </span><span class="nl">"short_name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"MyApp"</span><span class="p">,</span><span class="w"> </span><span class="nl">"icons"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">],</span><span class="w"> </span><span class="nl">"start_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"index.html"</span><span class="p">,</span><span class="w"> </span><span class="nl">"display"</span><span class="p">:</span><span class="w"> </span><span class="s2">"standalone"</span><span class="p">,</span><span class="w"> </span><span class="nl">"orientation"</span><span class="p">:</span><span class="w"> </span><span class="s2">"landscape"</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre> <p class="note">Quelle: <a href="https://github.com/GoogleChrome/samples/blob/gh-pages/web-application-manifest/manifest.json">GoogleChrome/samples</a></p> <footer> <ul> <li>Manifest ist erweiterbar und von Suchmaschinen durchsuchbar</li> </ul> </footer> </div></section> <section class="slide" id="installation---alt"><div><h2>Installation - alt</h2> <p><img src="home_add.png" alt="Add to Home" class="right full-height" /></p> <ul> <li>Prozess nur zwei Schritte, aber ungewohnt</li> <li>Plugins wie <a href="http://cubiq.org/add-to-home-screen">Add To Homescreen</a> sollen helfen</li> </ul> <p><img src="ath-preview.png" alt="Add to Home" class="left" /></p> <p class="note">Quelle: <a href="https://developer.chrome.com/multidevice/android/installtohomescreen">developer.chrome.com</a>, <a href="http://cubiq.org/add-to-home-screen">cubiq.org</a></p> <footer> <ul> <li>Unter iOS ist erkennbar, in welchem Modus eine App läuft</li> <li>Unter Chrome nicht, weshalb der Benutzer nicht zur Installation aufgefordert werden sollte</li> </ul> </footer> </div></section> <section class="slide" id="installation--neu"><div><h2>Installation – neu</h2> <p><img src="add-to-home-screen.gif" alt="Add to Home" class="center full-height" /></p> <p class="note">Quelle: <a href="https://developers.google.com/web/updates/2015/03/increasing-engagement-with-app-install-banners-in-chrome-for-android">developers.google.com</a></p> <footer> <ul> <li>Die Seite beginnt ihr Leben als regulärer Tab</li> <li>Beim zweiten (3., 4. …) Besuch – wenn der Browser denkt, dass die Seite öfter benutzt wird - wird ein Installations-Prompt gezeigt (basierend auf dem Manifest)</li> <li>Wenn die Seite dann installiert und vom Homescreen gestartet wird, fügt sie sich nahtlos in ihre Umgebung ein (Tab im App Switcher, Vollbild, Offline etc)</li> </ul> </footer> </div></section> <section class="slide" id="launch"><div><h2>Launch</h2> <pre class="highlight language-html" data-lang="html"><code><span class="c"><!-- Größe setzen un Zoomen in der Anwendung verhindern. --></span> <span class="nt"><meta</span> <span class="na">name=</span><span class="s">"viewport"</span> <span class="na">content=</span><span class="s">"width=device-width, initial-scale=1.0, user-scalable=no"</span><span class="nt">></span> <span class="c"><!-- Schwarze Statusbar mit weißem Text. --></span> <span class="nt"><meta</span> <span class="na">name=</span><span class="s">"apple-mobile-web-app-status-bar-style"</span> <span class="na">content=</span><span class="s">"black"</span><span class="nt">></span> </code></pre> <footer> <ul> <li>Chrome zeigt ab Version 39 Web-Apps im Task Switcher als eigenständige App</li> </ul> </footer> </div></section> <section class="slide" id="formulare"><div><h2>Formulare</h2> <p><img src="input-type-datetime-ios.png" alt="Datepicker" class="right full-height" /></p> <pre class="highlight language-html" data-lang="html"><code><span class="nt"><input</span> <span class="na">type=</span><span class="s">"email"</span><span class="nt">></span> <span class="nt"><input</span> <span class="na">type=</span><span class="s">"tel"</span><span class="nt">></span> <span class="nt"><input</span> <span class="na">type=</span><span class="s">"datetime-local"</span><span class="nt">></span> <span class="nt"><input</span> <span class="na">type=</span><span class="s">"number"</span> <span class="na">pattern=</span><span class="s">"[0-9]*"</span><span class="nt">></span> <span class="nt"><input</span> <span class="na">type=</span><span class="s">"password"</span> <span class="na">pattern=</span><span class="s">"[0-9]*"</span><span class="nt">></span> ... </code></pre> <p class="note">Quelle: <a href="http://diveintohtml5.info/i/input-type-datetime-ios.png">diveintohtml5.info</a></p> </div></section> <section class="slide" id="rich-text-editing"><div><h2>Rich Text Editing</h2> <p><img src="rte.jpg" alt="RTE" class="right" width="450" /></p> <pre class="highlight language-html" data-lang="html"><code><span class="nt"><div</span> <span class="na">contenteditable</span><span class="nt">></span> <span class="nt"><ul></span> <span class="nt"><li></span>Eins<span class="nt"></li></span> <span class="nt"><li></span>Zwei<span class="nt"></li></span> <span class="nt"></ul></span> <span class="nt"></div></span> </code></pre> <p class="note">Quelle: <a href="http://www.creativebloq.com/html5/12-html5-tricks-mobile-81412803">creativebloq.com</a></p> <footer> <ul> <li>neue Listeneinträge, Text-Stile etc</li> <li>erreichbar über <code class="language-plaintext highlighter-rouge">innerHTML</code> des Elements</li> </ul> </footer> </div></section> <section class="slide" id="touch-events"><div><h2>Touch-Events</h2> <table> <tbody> <tr> <td><code class="language-plaintext highlighter-rouge">touchstart</code></td> <td>Ein Finger wird auf ein DOM-Element gelegt.</td> </tr> <tr> <td><code class="language-plaintext highlighter-rouge">touchmove</code></td> <td>Ein Finger wird über ein DOM-Element gezogen.</td> </tr> <tr> <td><code class="language-plaintext highlighter-rouge">touchend</code></td> <td>Ein Finger wird von einem DOM-Element entfernt.</td> </tr> </tbody> </table> <ul> <li><code class="language-plaintext highlighter-rouge">click</code> wird um 300ms verzögert, wodurch Anwendung langsam erscheint (weil könnte auch Doppelklick für Zoom werden)</li> <li>Verzögerung kann deaktiviert werden durch: <ul> <li>Setzen des Viewports: <code class="language-plaintext highlighter-rouge"><meta name="viewport" content="width=device-width"></code></li> <li>Setzen der CSS-Property: <code class="language-plaintext highlighter-rouge">touch-action: manipulation;</code></li> </ul> </li> </ul> </div></section> <section class="slide" id="scrolling"><div><h2>Scrolling</h2> <pre class="highlight language-css" data-lang="css"><code><span class="nt">overflow</span><span class="o">:</span> <span class="nt">auto</span><span class="o">;</span> <span class="nt">-webkit-overflow-scrolling</span><span class="o">:</span> <span class="nt">touch</span><span class="o">;</span> <span class="c">/* disable rubber band effect*/</span> <span class="nt">body</span> <span class="p">{</span> <span class="py">overscroll-behavior</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span> <span class="p">}</span> </code></pre> <ul> <li>nativ anfühlendes, moment-basiertes Scrollen</li> <li>durch Events nicht / nur schwer (Position-Polling) kontrollierbar (Scroll-Event feuert erst nach Stillstand)</li> <li>Abhilfe durch Plugins wie <a href="http://cubiq.org/iscroll-5">iScroll</a>, die Scrolling deaktivieren und selbst nachbauen</li> </ul> <footer> <ul> <li>Auf <code class="language-plaintext highlighter-rouge">body</code> deaktivieren und auf Elementen aktivieren</li> <li>Der Android Browser auf Android 4.0 oder früher aktualisiert die Position des scrollenden Elements nicht</li> <li>iOS8-Safari schon, aber angeblich nur im Browser, nicht als Homescreen-App</li> </ul> </footer> </div></section> <section class="slide" id="tap-highlight"><div><h2>Tap-Highlight</h2> <ul> <li>Emulation nativen Verhaltens</li> </ul> <pre class="highlight language-css" data-lang="css"><code><span class="o">*</span> <span class="p">{</span> <span class="nl">-webkit-tap-highlight-color</span><span class="p">:</span> <span class="n">rgba</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">0</span><span class="p">,</span><span class="m">0</span><span class="p">,</span><span class="m">0</span><span class="p">);</span> <span class="p">}</span> </code></pre> <ul> <li>Eigenes Verhalten über <code class="language-plaintext highlighter-rouge">:active</code>-State eines Elements</li> </ul> <pre class="highlight language-css" data-lang="css"><code><span class="nt">button</span><span class="nd">:active</span> <span class="p">{</span> <span class="nl">background-color</span><span class="p">:</span> <span class="no">skyblue</span><span class="p">;</span> <span class="p">}</span> </code></pre> <footer> <p>Standardmäßig werden Links nach dem Klicken visuell hervorgehoben, um Feedback zu geben. Das entspricht nicht dem verhalten nativer Anwendungen und sieht zum anderen auch noch unschön aus.</p> </footer> </div></section> <section class="slide" id="offline"><div><h2>Offline</h2> <div class="parts "> <div class="part"> <ul> <li><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache">ApplicationCache</a> weite verbreitet aber deprecated</li> <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API">ServiceWorker</a> findet zunehmend Verbreitung (Chrome 45, iOS 11.3)</li> </ul> <pre class="highlight language-html" data-lang="html"><code><span class="cp"><!doctype html></span> <span class="nt"><html</span> <span class="na">manifest=</span><span class="s">"app.appcache"</span><span class="nt">></span> ... </code></pre> </div><div class="part"> <pre class="highlight language-bash" data-lang="bash"><code>CACHE MANIFEST <span class="c"># Revision: 1.28</span> CACHE: /images/logo.png /styles/style.css NETWORK: /login.html FALLBACK: /index.html /offline.html </code></pre> </div> </div> <footer> <ul> <li>Manifest-Datei muss mit dem Content-Type <code class="language-plaintext highlighter-rouge">text/cache-manifest</code> ausgeliefert werden</li> <li><code class="language-plaintext highlighter-rouge">logo.png</code> und <code class="language-plaintext highlighter-rouge">style.css</code> werden immer über den Cache ausgeliefert</li> <li><code class="language-plaintext highlighter-rouge">login.html</code> immer vom Server geholt</li> <li><code class="language-plaintext highlighter-rouge">index.html</code> nicht erreichbar: Fallback auf <code class="language-plaintext highlighter-rouge">offline.html</code></li> <li>ServiceWorker etwas komplizierter und benötigt HTTPS, aber das ist leichter geworden und es gibt viele Tutorials / Boierplates</li> </ul> </footer> </div></section> <section class="slide" id="offline--events"><div><h2>Offline – Events</h2> <pre class="highlight language-js" data-lang="js"><code><span class="c1">// Netzverbindung prüfen</span> <span class="kd">const</span> <span class="nx">isOnline</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nb">navigator</span><span class="p">.</span><span class="nx">onLine</span><span class="p">;</span> <span class="c1">// true / false</span> <span class="c1">// auf Wechsel reagieren</span> <span class="nb">window</span><span class="p">.</span><span class="nf">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">online</span><span class="dl">'</span><span class="p">,</span> <span class="nx">ev</span> <span class="o">=></span> <span class="nf">alert</span><span class="p">(</span><span class="dl">'</span><span class="s1">😃</span><span class="dl">'</span><span class="p">));</span> <span class="nb">window</span><span class="p">.</span><span class="nf">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">offline</span><span class="dl">'</span><span class="p">,</span> <span class="nx">ev</span> <span class="o">=></span> <span class="nf">alert</span><span class="p">(</span><span class="dl">'</span><span class="s1">😱</span><span class="dl">'</span><span class="p">));</span> </code></pre> <footer> <ul> <li>Be aware of the Lie-Fi!</li> </ul> </footer> </div></section> <section class="slide" id="weitere-apis"><div><h2>Weitere APIs</h2> <table> <tbody> <tr> <td><a href="https://developer.mozilla.org/en-US/docs/Web/API/Battery_Status_API">Battery Status</a></td> <td>Akku-Informationen</td> </tr> <tr> <td><a href="https://developer.mozilla.org/en-US/docs/Web/API/Notification/Using_Web_Notifications">Web Notifications</a></td> <td>Benachrichtigungen</td> </tr> <tr> <td><a href="https://developer.mozilla.org/en-US/docs/Web/API/Proximity_Events">Proximity</a></td> <td>Nähe des Benutzers zum Gerät</td> </tr> <tr> <td><a href="https://developer.mozilla.org/en-US/docs/Web/Guide/API/Vibration">Vibration</a></td> <td>Lässt Gerät vibrieren</td> </tr> <tr> <td><a href="https://developer.mozilla.org/en-US/docs/Web/API/Detecting_device_orientation">Device Orientation</a></td> <td>Ausrichtung des Geräts</td> </tr> <tr> <td><a href="https://developer.mozilla.org/en-US/docs/Web/API/DeviceMotionEvent">Device Motion</a></td> <td>Daten über Bewegungen</td> </tr> <tr> <td><a href="https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share">Web Share API </a></td> <td>Assets in andere Anwendungen teilen (<a href="https://css-tricks.com/how-to-use-the-web-share-api/">Tutorial</a>)</td> </tr> </tbody> </table> </div></section> <section class="slide" id="hybrid-apps"><div><h2>Hybrid-Apps</h2> <ul> <li>Wrapper um Web-App, der native APIs zur Verfügung stellt</li> <li>Distribution über Marktplätze</li> <li>Schnellere Entwicklung, aber schlechtere Kontrolle und Performance</li> <li><a href="http://phonegap.com/">PhoneGap</a>, <a href="http://cordova.apache.org/">Cordova</a>, <a href="http://ionicframework.com/">Ionic</a></li> </ul> </div></section> <section class="slide" id="links"><div><h2>Links</h2> <ul> <li>Beispiel-App: <a href="https://github.com/HTW-Webtech/KFZ-Kennzeichen">KFZ-Kennzeichen</a></li> <li><a href="https://developers.google.com/web/fundamentals/device-access/">Device Access & Integration</a></li> <li><a href="http://www.html5rocks.com/en/tutorials/service-worker/introduction/">Service Worker</a></li> <li><a href="http://jquerymobile.com/">jQuery Mobile</a>, <a href="http://onsen.io/">Onsen UI</a>, <a href="http://chocolatechip-ui.com/">ChocolateChip-UI</a></li> <li><a href="https://whatwebcando.today/">What Web Can Do Today</a></li> </ul> </div></section>