Webtechnologien
Wintersemester 2024
Progressive Web Apps
♯
♫
Progressive Web Apps
<section bg="bicycles.jpg" id="progressive-web-apps" class="slide cover"><div><h2>Progressive Web Apps</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-1"><div><h2>Installation</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--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="offline--serviceworker-1"><div><h2>Offline – ServiceWorker 1</h2> <ul> <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API">ServiceWorker</a></li> </ul> <pre class="highlight language-html" data-lang="html"><code><span class="cp"><!doctype html></span> <span class="nt"><script></span> <span class="k">if </span><span class="p">(</span><span class="dl">'</span><span class="s1">serviceWorker</span><span class="dl">'</span> <span class="k">in</span> <span class="nb">navigator</span><span class="p">)</span> <span class="p">{</span> <span class="nb">navigator</span><span class="p">.</span><span class="nx">serviceWorker</span><span class="p">.</span><span class="nf">register</span><span class="p">(</span><span class="dl">'</span><span class="s1">service-worker.js</span><span class="dl">'</span><span class="p">);</span> <span class="p">};</span> <span class="nt"></script></span> </code></pre> <footer> <ul> <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--serviceworker-2"><div><h2>Offline – ServiceWorker 2</h2> <pre class="highlight language-js" data-lang="js"><code><span class="nb">self</span><span class="p">.</span><span class="nf">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">install</span><span class="dl">'</span><span class="p">,</span> <span class="nx">event</span> <span class="o">=></span> <span class="p">{</span> <span class="nx">event</span><span class="p">.</span><span class="nf">waitUntil</span><span class="p">(</span> <span class="nx">caches</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="dl">'</span><span class="s1">sw-cache</span><span class="dl">'</span><span class="p">).</span><span class="nf">then</span><span class="p">(</span><span class="nx">cache</span> <span class="o">=></span> <span class="p">{</span> <span class="k">return</span> <span class="nx">cache</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="dl">'</span><span class="s1">index.html</span><span class="dl">'</span><span class="p">);</span> <span class="p">})</span> <span class="p">);</span> <span class="p">});</span> <span class="nb">self</span><span class="p">.</span><span class="nf">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">fetch</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span> <span class="nx">event</span><span class="p">.</span><span class="nf">respondWith</span><span class="p">(</span> <span class="nx">caches</span><span class="p">.</span><span class="nf">match</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">).</span><span class="nf">then</span><span class="p">(</span><span class="nx">response</span> <span class="o">=></span> <span class="p">{</span> <span class="k">return</span> <span class="nx">response</span> <span class="o">||</span> <span class="nf">fetch</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">);</span> <span class="p">})</span> <span class="p">);</span> <span class="p">});</span> </code></pre> </div></section> <section class="slide" id="web-push-notifications"><div><h2>Web Push Notifications</h2> <p><img src="push-notifications.gif" alt="Web Push Notifications" class="right" style="margin-right:-10rem" /></p> <pre class="highlight language-js" data-lang="js"><code><span class="nb">self</span><span class="p">.</span><span class="nf">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">push</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span> <span class="kd">var</span> <span class="nx">title</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Hallo!.</span><span class="dl">'</span><span class="p">;</span> <span class="kd">var</span> <span class="nx">body</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Hier ist deine Nachricht</span><span class="dl">'</span><span class="p">;</span> <span class="kd">var</span> <span class="nx">icon</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">/images/icon-192x192.png</span><span class="dl">'</span><span class="p">;</span> <span class="kd">var</span> <span class="nx">tag</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">dmeo-tag</span><span class="dl">'</span><span class="p">;</span> <span class="nx">event</span><span class="p">.</span><span class="nf">waitUntil</span><span class="p">(</span> <span class="nb">self</span><span class="p">.</span><span class="nx">registration</span><span class="p">.</span><span class="nf">showNotification</span><span class="p">(</span> <span class="nx">title</span><span class="p">,</span> <span class="p">{</span> <span class="nx">body</span><span class="p">,</span> <span class="nx">icon</span><span class="p">,</span> <span class="nx">tag</span> <span class="p">}</span> <span class="p">)</span> <span class="p">);</span> <span class="p">});</span> </code></pre> <p class="note">Quelle: <a href="https://developer.chrome.com/blog/push-notifications-on-the-open-web?hl=de">developer.chrome.com</a></p> <footer> <ul> <li>guter browser support</li> <li>Registrierung und Ereignisbehandlung im Service Worker</li> <li>Push-Service Subscription-Management</li> <li>Explizite Nutzererlaubnis erforderlich</li> </ul> </footer> </div></section> <section class="slide" id="web-share-api"><div><h2>Web Share API</h2> <p><img src="web-share-api.gif" alt="Web Share API" class="right" /></p> <pre class="highlight language-js" data-lang="js"><code><span class="nx">btn</span><span class="p">.</span><span class="nf">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span> <span class="nb">navigator</span><span class="p">.</span><span class="nf">share</span><span class="p">({</span> <span class="na">title</span><span class="p">:</span> <span class="dl">'</span><span class="s1">HTW Berlin</span><span class="dl">'</span><span class="p">,</span> <span class="na">text</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Hochschule für Technik …</span><span class="dl">'</span><span class="p">,</span> <span class="na">url</span><span class="p">:</span> <span class="dl">'</span><span class="s1">https://www.htw-berlin.de</span><span class="dl">'</span><span class="p">,</span> <span class="p">});</span> <span class="p">});</span> </code></pre> <p class="note">Quelle: <a href="https://hospodarets.com/web-share-api">hospodarets.com</a></p> </div></section> <section class="slide" id="contact-picker-api"><div><h2>Contact Picker API</h2> <p><img src="contact-picker-api.gif" alt="Contact Picker API" class="right" /></p> <pre class="highlight language-js" data-lang="js"><code><span class="nx">btn</span><span class="p">.</span><span class="nf">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span> <span class="nb">navigator</span><span class="p">.</span><span class="nx">contacts</span><span class="p">.</span><span class="nf">select</span><span class="p">(</span> <span class="p">[</span><span class="dl">'</span><span class="s1">name</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">email</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">tel</span><span class="dl">'</span><span class="p">],</span> <span class="p">{</span> <span class="na">multiple</span><span class="p">:</span> <span class="kc">true</span> <span class="p">}</span> <span class="p">).</span><span class="nf">then</span><span class="p">(</span><span class="nx">contacts</span> <span class="o">=></span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">contacts</span><span class="p">)</span> <span class="p">});</span> <span class="p">});</span> </code></pre> <p class="note">Quelle: <a href="https://developer.chrome.com/docs/capabilities/web-apis/contact-picker">developer.chrome.com</a></p> <footer> <ul> <li>nur Chrome!</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>Pressespiegel: <a href="https://www.heise.de/news/Microsoft-installiert-ungefragt-Office-PWAs-unter-Windows-10-4932142.html">Microsoft installiert ungefragt Office-PWAs unter Windows 10</a></li> <li>Case Study: <a href="https://web.dev/zdf/">PWA des ZDF</a></li> <li><a href="https://developers.google.com/web/fundamentals/device-access/">Device Access & Integration</a></li> <li><a href="https://whatwebcando.today/">What Web Can Do Today</a></li> <li><a href="https://web.dev/articles/pwas-in-app-stores">PWAs in app stores</a></li> </ul> </div></section>