Ich habe mich in das Programmieren verliebt, als ich meinen ersten CSS-:hover-Effekt erstellt habe. Jahre später führte mich dieser erste Ausflug in die Interaktivität im Web zu einem neuen Ziel: ein Spiel zu machen.
Inhaltsverzeichnis
- Was ist das Spiel (und was ist der Name)?
- Auswahl von Nuxt
- Ein natives App-Gefühl mit dem Web erreichen
- Vibration und Ton
- Gameplay, Geschichte und Auszeichnungen
- Vor- und Nachteile dieses Ansatzes
- Logistik: Eine Web-App in eine native App verwandeln
- Was ist eine TWA-App?
- So generiert man die Android App APK
- Der Signierschlüssel
- Was Sie über das Auflisten einer App wissen sollten
- Monetarisierung, freischaltbare Inhalte und das Umgehen von Google
- Anpassen des App-Erlebnisses für Google Play
- Berücksichtigung von Konten
- Zusammenfassung
Diese frühen Momente, in denen ich mit :hover herumspielte, waren nichts Besonderes und auch nicht nützlich. Ich erinnere mich, wie ich ein responsives Raster aus blauen Quadraten (aus float erstellt, wenn das etwas über die Zeitlinie verrät) gemacht habe, von denen jedes orange wurde, wenn der Cursor darüber fuhr. Ich verbrachte Stunden damit, über die Kästchen zu fahren, das Fenster zu vergrößern und zu verkleinern, um zu sehen, wie sie ihre Größe und Ausrichtung änderten, und dann alles wieder von vorne zu machen. Es fühlte sich wie reine Magie an.
Was ich im Web aufgebaut habe, wurde natürlich im Laufe der Jahre komplexer als dieses Raster aus <div>-Elementen, aber der Nervenkitzel, etwas wirklich Interaktives zum Leben zu erwecken, blieb mir immer erhalten. Und je mehr ich über JavaScript lernte, desto mehr liebte ich es, Spiele zu machen.
Manchmal war es nur eine CodePen-Demo; manchmal war es ein kleines Nebenprojekt, das auf Vercel oder Netlify bereitgestellt wurde. Ich liebte die Herausforderung, Spiele wie Color Flood, Hangman oder Vier gewinnt in einem Browser nachzubilden.
Nach einer Weile wurde das Ziel jedoch größer: was wäre, wenn ich ein echtes Spiel machen würde? Kein reines Web-App; ein richtiges, lebendiges, ehrlich-und-aufrichtiges, aus einem App-Store herunterladbares Spiel. Letzten August begann ich mit meinem bisher ehrgeizigsten Projekt und vier Monate später veröffentlichte ich es in die Welt (sprich: ich hatte es satt, daran herumzufummeln): eine Wortspiel-App namens Quina.

Was ist das Spiel (und was ist der Name)?
Am einfachsten lässt sich Quina erklären: es ist Mastermind, aber mit fünfstelligen Wörtern. Tatsächlich ist Mastermind eine Version eines klassischen Stift-und-Papier-Spiels; Quina ist einfach eine weitere Variation dieses ursprünglichen Spiels.
Das Ziel von Quina ist es, ein geheimes fünfstelliges Wort zu erraten. Nach jedem Versuch erhalten Sie einen Hinweis, der Ihnen sagt, wie nah Ihre Vermutung am Lösungswort ist. Sie verwenden diesen Hinweis, um Ihre nächste Vermutung zu verfeinern und so weiter, aber Sie haben nur zehn Versuche insgesamt; wenn Ihnen die Versuche ausgehen, verlieren Sie.
Der Name „Quina“ entstand, weil er auf Lateinisch „fünf auf einmal“ bedeutet (oder zumindest hat mir Google das gesagt). Das traditionelle Spiel wird normalerweise mit vierstelligen Wörtern oder manchmal mit vier Ziffern (oder im Fall von Mastermind, vier Farben) gespielt; Quina verwendet fünfstellige Wörter ohne wiederholte Buchstaben, daher schien es passend, dass das Spiel einen Namen haben sollte, der nach seinen eigenen Regeln spielt. (Ich habe keine Ahnung, wie das ursprüngliche lateinische Wort ausgesprochen wurde, aber ich sage „QUINN-ah“, was wahrscheinlich falsch ist, aber hey, es ist mein Spiel, oder?)
Ich habe in den Abenden und Wochenenden über einen Zeitraum von etwa vier Monaten die App gebaut. Ich möchte in diesem Artikel über die Technik hinter dem Spiel, die getroffenen Entscheidungen und die gewonnenen Erkenntnisse sprechen, falls dies ein Weg ist, den Sie selbst einschlagen möchten.
Auswahl von Nuxt
Ich bin ein riesiger Fan von Vue und wollte dieses Projekt nutzen, um mein Wissen über sein Ökosystem zu erweitern. Ich habe überlegt, ein anderes Framework zu verwenden (ich habe auch Projekte in Svelte und React erstellt), aber ich hatte das Gefühl, dass Nuxt den Sweet Spot zwischen Vertrautheit, Benutzerfreundlichkeit und Reife traf. (Übrigens, falls Sie es nicht wussten oder nicht erraten haben: Nuxt kann ziemlich genau als das Vue-Äquivalent von Next.js beschrieben werden.)
Ich hatte mich zuvor nicht zu sehr mit Nuxt beschäftigt; nur ein paar sehr kleine Apps. Aber ich wusste, dass Nuxt eine statische App kompilieren kann, was genau das war, was ich wollte – keine (Node-)Server, um die man sich kümmern muss. Ich wusste auch, dass Nuxt das Routing so einfach handhaben kann, indem man Vue-Komponenten in einen /pages-Ordner legt, was sehr ansprechend war.
Außerdem, obwohl Vuex (das offizielle State Management in Vue) für sich genommen nicht besonders komplex ist, schätzte ich die Art und Weise, wie Nuxt nur ein kleines bisschen Zucker hinzufügt, um es noch einfacher zu machen. (Nuxt macht übrigens vieles einfach, z. B. müssen Sie Ihre Komponenten nicht explizit importieren, bevor Sie sie verwenden können; Sie können sie einfach in das Markup legen und Nuxt wird sie erkennen und bei Bedarf automatisch importieren.)
Schließlich wusste ich im Voraus, dass ich eine Progressive Web App (PWA) bauen würde, daher war die Tatsache, dass es bereits ein Nuxt PWA-Modul gibt, das beim Aufbau aller beteiligten Funktionen (wie z. B. eines Service Workers für Offline-Fähigkeiten) hilft, bereits verpackt und einsatzbereit war, ein großer Vorteil. Tatsächlich gibt es eine beeindruckende Reihe von Nuxt-Modulen für alle unvorhergesehenen Hürden. Das machte Nuxt zur einfachsten, offensichtlichsten Wahl, und eine, die ich nie bereut habe.
Ich habe im Laufe der Zeit mehr Module verwendet, darunter das hervorragende Nuxt Content-Modul, das es Ihnen ermöglicht, Seiteninhalte in Markdown oder sogar in einer Mischung aus Markdown und Vue-Komponenten zu schreiben. Ich habe diese Funktion für die „Häufig gestellte Fragen“-Seite und die „Spielanleitung“-Seite verwendet (da das Schreiben in Markdown viel angenehmer ist als das Hardcodieren von HTML-Seiten).
Ein natives App-Gefühl mit dem Web erreichen
Quina würde schließlich ein Zuhause im Google Play Store finden, aber unabhängig davon, wie oder wo es gespielt wurde, wollte ich, dass es sich von Anfang an wie eine vollwertige App anfühlt.
Zunächst bedeutete das einen optionalen Dunkelmodus und eine Einstellung zur Bewegungsreduktion für optimale Benutzerfreundlichkeit, wie sie viele native Apps haben (und im Falle der Bewegungsreduktion, wie es alles mit Animationen haben sollte).

Unter der Haube sind beide Einstellungen letztendlich Booleans im Vuex-Datenspeicher der App. Wenn true ist, rendert die Einstellung eine bestimmte Klasse im Standardlayout der App. Nuxt-Layouts sind Vue-Vorlagen, die den gesamten Inhalt „umhüllen“ und auf allen (oder vielen) Seiten Ihrer App gerendert werden (häufig für gemeinsame Header und Footer verwendet, aber auch nützlich für globale Einstellungen).
<!-- layouts/default.vue -->
<template>
<div
:class="[
{
'dark-mode': darkMode,
'reduce-motion': reduceMotion,
},
'dots',
]"
>
<Nuxt />
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters(['darkMode', 'reduceMotion']),
},
// Other layout component code here
}
</script>
Apropos Einstellungen: Obwohl die Web-App in mehrere verschiedene Seiten unterteilt ist – Menü, Einstellungen, Über uns, Spielen usw. – hilft der gemeinsame globale Vuex-Datenspeicher, die Dinge synchron und nahtlos zwischen den Bereichen der App zu halten (da der Benutzer seine Einstellungen auf einer Seite anpasst und sieht, wie sie sich auf das Spiel auf einer anderen Seite auswirken).
Jede Einstellung in der App wird auch sowohl mit localStorage als auch mit dem Vuex-Store synchronisiert, was das Speichern und Laden von Werten zwischen Sitzungen ermöglicht und gleichzeitig die Einstellungen beim Navigieren des Benutzers zwischen den Seiten verfolgt.
Und apropos Navigation: Der Wechsel zwischen den Seiten ist ein weiterer Bereich, in dem ich das Gefühl hatte, dass es viele Möglichkeiten gab, Quina wie eine native App wirken zu lassen, indem man Übergänge für die gesamte Seite hinzufügt.
Vue-Übergänge sind generell ziemlich einfach – man schreibt nur spezifisch benannte CSS-Klassen für die „zu“- und „von“-Übergangszustände – aber Nuxt geht einen Schritt weiter und ermöglicht es Ihnen, vollständige Seitenübergänge mit nur einer Zeile in einer Vue-Datei zu setzen.
<!-- A page component, e.g., pages/Options.vue -->
<script>
export default {
transition: 'page-slide'
// ... The rest of the component properties
}
</script>
Diese transition-Eigenschaft ist mächtig; sie teilt Nuxt mit, dass wir den page-slide-Übergang auf diese Seite anwenden möchten, wann immer wir zu ihr navigieren oder von ihr weg. Von dort aus müssen wir nur noch die Klassen definieren, die die Animation handhaben, wie Sie es bei jedem Vue-Übergang tun würden. Hier ist mein page-slide SCSS.
/* assets/css/_animations.scss */
.page-slide {
&-enter-active {
transition: all 0.35s cubic-bezier(0, 0.25, 0, 0.75);
}
&-leave-active {
transition: all 0.35s cubic-bezier(0.75, 0, 1, 0.75);
}
&-enter,
&-leave-to {
opacity: 0;
transform: translateY(1rem);
.reduce-motion & {
transform: none !important;
}
}
&-leave-to {
transform: translateY(-1rem);
}
}
Beachten Sie die .reduce-motion-Klasse; das ist, was wir gerade in der Layout-Datei besprochen haben. Sie verhindert visuelle Bewegung, wenn der Benutzer angezeigt hat, dass er reduzierte Bewegung bevorzugt (entweder über Media Query oder manuelle Einstellung), indem jegliche transform-Eigenschaften deaktiviert werden (was die Verwendung der umstrittenen !important-Flagge zu rechtfertigen schien). Die Deckkraft darf jedoch weiterhin ein- und ausgeblendet werden, da dies keine wirkliche Bewegung ist.
Randnotiz zu Übergängen und Behandlung von 404ern: Die Übergänge und das Routing werden natürlich im Hintergrund von JavaScript gehandhabt (genauer gesagt von Vue Router), aber ich stieß auf ein frustrierendes Problem, bei dem Skripte auf ruhenden Seiten nicht mehr ausgeführt wurden (z. B. wenn der Benutzer die App oder den Tab eine Weile im Hintergrund geöffnet ließ). Wenn man zu diesen ruhenden Seiten zurückkehrte und auf einen Link klickte, wäre Vue Router angehalten worden, und so würde der Link als relativ behandelt und ein 404-Fehler ausgelöst.
Beispiel: Die Seite /faq geht in den Leerlauf; der Benutzer kehrt dazu zurück und klickt auf den Link, um zur Seite /options zu gelangen. Die App würde versuchen, zu /faq/options zu gehen, was natürlich nicht existiert.
Meine Lösung dafür war eine benutzerdefinierte error.vue-Seite (dies ist eine Nuxt-Seite, die alle Fehler automatisch behandelt), auf der ich eine Validierung des eingehenden Pfades durchführte und zum Ende des Pfades weiterleitete.
// layouts/error.vue
mounted() {
const lastPage = '/' + this.$route.fullPath.split('/').pop()
// Don't create a redirect loop
if (lastPage !== this.$route.fullPath) {
this.$router.push({
path: lastPage,
})
}
}
Dies funktionierte für meinen Anwendungsfall, weil a) ich keine verschachtelten Routen habe; und b) am Ende, wenn der Pfad ungültig ist, wird immer noch ein 404 erreicht.
Vibration und Ton
Übergänge sind nett, aber ich wusste auch, dass Quina sich nicht wie eine native App anfühlen würde – besonders auf einem Smartphone – ohne Vibration und Ton.
Vibration ist heutzutage dank der Navigator API relativ einfach in Browsern zu erreichen. Die meisten modernen Browser erlauben es Ihnen einfach, window.navigator.vibrate() aufzurufen, um dem Benutzer ein kleines Summen oder eine Reihe von Summen zu geben – oder, mit einer sehr kurzen Dauer, ein winziges bisschen haptisches Feedback, wie wenn Sie eine Taste auf einer Smartphone-Tastatur antippen.
Natürlich möchten Sie Vibration sparsam einsetzen, aus mehreren Gründen. Erstens, weil zu viel leicht zu einer schlechten Benutzererfahrung werden kann; und zweitens, weil nicht alle Geräte/Browser sie unterstützen, sodass Sie sehr vorsichtig sein müssen, wie und wo Sie versuchen, die vibrate()-Funktion aufzurufen, damit Sie keinen Fehler verursachen, der das aktuell laufende Skript abbricht.
Persönlich habe ich als Lösung einen Vuex-Getter eingerichtet, um zu überprüfen, ob der Benutzer Vibration zulässt (sie kann auf der Einstellungsseite deaktiviert werden); dass der aktuelle Kontext der Client und nicht der Server ist; und schließlich, dass die Funktion im aktuellen Browser existiert. (ES2020-Optional-Chaining hätte hier für den letzten Teil ebenfalls funktioniert.)
// store/getters.js
vibration(state) {
if (
process.client &&
state.options.vibration &&
typeof window.navigator.vibrate !== 'undefined'
) {
return true
}
return false
},
Randnotiz: Die Überprüfung auf process.client ist in Nuxt wichtig – und vielen anderen Frameworks mit Code, der auf Node laufen könnte –, da window nicht immer existiert. Dies gilt auch, wenn Sie Nuxt im statischen Modus verwenden, da die Komponenten während der Build-Zeit in Node validiert werden. process.client (und sein Gegenstück process.server) sind Nuxt-Annehmlichkeiten, die die aktuelle Umgebung des Codes zur Laufzeit einfach validieren, sodass sie perfekt zur Isolierung von browser-spezifischem Code geeignet sind.
Ton ist ein weiterer wichtiger Teil des Benutzererlebnisses der App. Anstatt meine eigenen Effekte zu erstellen (was zweifellos Dutzende weiterer Stunden zum Projekt hinzugefügt hätte), habe ich Samples von einigen Künstlern gemischt, die in diesem Bereich besser wissen, was sie tun, und die einige kostenlose Spielgeräusche online angeboten haben. (Siehe die FAQ der App für vollständige Informationen.)
Benutzer können die gewünschte Lautstärke einstellen oder den Ton ganz ausschalten. Dies und die Vibration werden ebenfalls in localStorage im Browser des Benutzers gespeichert und mit dem Vuex-Store synchronisiert. Dieser Ansatz ermöglicht es uns, eine „permanente“ Einstellung im Browser zu speichern, aber ohne dass wir sie jedes Mal abrufen müssen, wenn sie referenziert wird. (Sounds zum Beispiel prüfen jedes Mal, wenn einer abgespielt wird, den aktuellen Lautstärkepegel, und die Latenz beim Warten auf einen localStorage-Aufruf jedes Mal, wenn das passiert, könnte ausreichen, um das Erlebnis zu beeinträchtigen.)
Eine Randbemerkung zum Thema Ton
Es stellt sich heraus, dass Safari aus irgendeinem Grund extrem träge ist, wenn es um Ton geht. Alle Klicks, Boops und Dingse brauchten eine spürbare Zeit nach dem auslösenden Ereignis, um tatsächlich in Safari abgespielt zu werden, besonders unter iOS. Das war ein Deal-Breaker und ein Kaninchenbau, in den ich verzweifelt viele Stunden gegraben habe.
Glücklicherweise fand ich eine Bibliothek namens Howler.js, die plattformübergreifende Soundprobleme sehr einfach löst (und die auch ein lustiges kleines Logo hat). Das einfache Installieren von Howler als Abhängigkeit und das Ausführen aller Sounds der App durch sie – im Grunde ein oder zwei Codezeilen – reichte aus, um das Problem zu lösen.

Wenn Sie eine JavaScript-App mit synchronem Ton erstellen, würde ich dringend empfehlen, Howler zu verwenden, da ich keine Ahnung habe, was Safaris Problem war oder wie Howler es löst. Nichts, was ich versucht habe, funktionierte, also bin ich glücklich, dass das Problem einfach mit sehr geringem Aufwand oder Codeänderungen gelöst wurde.
Gameplay, Geschichte und Auszeichnungen
Quina kann ein schwieriges Spiel sein, besonders am Anfang, daher gibt es ein paar Möglichkeiten, den Schwierigkeitsgrad des Spiels an Ihre persönlichen Vorlieben anzupassen.
- Sie können wählen, welche Art von Wörtern Sie als Lösungswörter erhalten möchten: Basic (gängige englische Wörter), Tricky (Wörter, die entweder obskurer oder schwieriger zu buchstabieren sind) oder Random (eine gewichtete Mischung aus beidem).
- Sie können wählen, ob Sie zu Beginn jedes Spiels einen Hinweis erhalten möchten und wie viel dieser Hinweis preisgibt.

Diese Einstellungen ermöglichen es Spielern mit unterschiedlichen Fähigkeiten, Alter und/oder Englischkenntnissen, das Spiel auf ihrem eigenen Niveau zu spielen. (Ein Basic-Wortset mit starken Hinweisen wäre am einfachsten; Tricky oder Random ohne Hinweise wäre am schwierigsten.)

Während das reine Spielen einer Reihe von Einzelspielen mit einstellbarem Schwierigkeitsgrad unterhaltsam genug sein mag, würde sich das eher wie eine Standard-Web-App oder Demo anfühlen als wie ein echtes, vollwertiges Spiel. Um also im Streben nach diesem nativen App-Gefühl zu bleiben, verfolgt Quina Ihre Spielhistorie, zeigt Ihre Spielstatistiken auf verschiedene Weise an und bietet mehrere „Auszeichnungen“ für verschiedene Leistungen.

Unter der Haube wird jedes Spiel als Objekt gespeichert, das ungefähr so aussieht.
{
guessesUsed: 3,
difficulty: 'tricky',
win: true,
hint: 'none',
}
Die App katalogisiert Ihre gespielten Spiele (erneut über Vuex-State, synchronisiert mit localStorage) in Form eines gameHistory-Arrays von Spielobjekten, das die App dann verwendet, um Ihre Statistiken anzuzeigen – wie z. B. Ihr Gewinn-/Verlustverhältnis, die Anzahl der gespielten Spiele und Ihre durchschnittliche Anzahl von Vermutungen – sowie um Ihren Fortschritt bei den „Auszeichnungen“ des Spiels anzuzeigen.
Dies geschieht alles ganz einfach mit verschiedenen Vuex-Gettern, von denen jeder JavaScript-Array-Methoden wie .filter() und .reduce() auf dem gameHistory-Array verwendet. Dies ist zum Beispiel der Getter, der anzeigt, wie viele Spiele der Benutzer im „Tricky“-Modus gewonnen hat.
// store/getters.js
trickyGamesWon(state) {
return state.gameHistory.filter(
(game) => game.win && game.difficulty === 'tricky'
).length
},
Es gibt viele andere Getter unterschiedlicher Komplexität. (Derjenige zur Ermittlung der längsten Siegesserie des Benutzers war besonders knifflig.)
Das Hinzufügen von Auszeichnungen war eine Angelegenheit der Erstellung eines Arrays von Auszeichnungsobjekten, die jeweils an einen bestimmten Vuex-Getter gebunden sind, und die jeweils eine requirement.threshold-Eigenschaft aufweisen, die angibt, wann diese Auszeichnung freigeschaltet wurde (d. h. wann der vom Getter zurückgegebene Wert hoch genug war). Hier ist ein Beispiel:
// assets/js/awards.js
export default [
{
title: 'Onset',
requirement: {
getter: 'totalGamesPlayed',
threshold: 1,
text: 'Play your first game of Quina',
}
},
{
title: 'Sharp',
requirement: {
getter: 'trickyGamesWon',
threshold: 10,
text: 'Win ten total games on Tricky',
},
},
]
Von dort aus ist es eine ziemlich einfache Sache, die Erfolge in einer Vue-Vorlagendatei zu durchlaufen, um die endgültige Ausgabe zu erhalten, unter Verwendung ihrer requirement.text-Eigenschaft (obwohl eine gute Menge an Mathematik und Animation hinzugefügt wird, um die Messgeräte zu füllen und dem Benutzer seinen Fortschritt bei der Erzielung der Auszeichnung zu zeigen).

Es gibt insgesamt 25 Auszeichnungen (das sind 5 × 5, um dem Thema treu zu bleiben) für verschiedene Errungenschaften wie das Gewinnen einer bestimmten Anzahl von Spielen, das Ausprobieren aller Spielmodi oder sogar das Gewinnen eines Spiels innerhalb Ihrer ersten drei Versuche. (Diese heißt „Lucky“ – als kleiner zusätzlicher Easter Egg ist der Name jeder Auszeichnung auch ein potenzielles Lösungswort, d. h. fünf Buchstaben ohne Wiederholungen.)
Das Freischalten von Auszeichnungen bewirkt nichts außer Angeberei, aber einige davon sind ziemlich schwierig zu erreichen. (Es dauerte mich ein paar Wochen nach der Veröffentlichung, um sie alle zu bekommen!)
Vor- und Nachteile dieses Ansatzes
Die Strategie „einmal bauen, überall bereitstellen“ hat viel zu bieten, aber sie hat auch einige Nachteile.
Vorteile
- Sie müssen Ihre Store-App nur einmal bereitstellen. Danach können alle Updates einfach Website-Deployments sein. (Das ist viel schneller, als auf eine Veröffentlichung im App Store zu warten.)
- Einmal bauen. Das ist irgendwie wahr, erwies sich aber aufgrund von Googles Zahlungsrichtlinien (mehr dazu später) als nicht ganz so einfach, wie ich dachte.
- Alles ist ein Browser. Ihre App läuft immer in der Umgebung, die Sie gewohnt sind, ob sich der Benutzer dessen bewusst ist oder nicht.
Nachteile
- Event-Handler können wirklich knifflig werden. Da Ihr Code auf allen Plattformen gleichzeitig läuft, müssen Sie jede Art von Benutzereingabe gleichzeitig antizipieren. Einige Elemente in der App können angetippt, geklickt, lange gedrückt und auch unterschiedlich auf verschiedene Tastaturtasten reagieren; es kann schwierig sein, all diese gleichzeitig zu behandeln, ohne dass sich die Handler gegenseitig in die Quere kommen.
- Sie müssen möglicherweise Erfahrungen aufteilen. Das hängt davon ab, was Ihre App tut, aber es gab einige Dinge, die ich nur für Benutzer der Android-App anzeigen musste, und andere, die nur für das Web bestimmt waren. (Ich gehe im Folgenden in einem anderen Abschnitt etwas detaillierter darauf ein, wie ich das gelöst habe.)
- Alles ist ein Browser. Sie machen sich keine Sorgen darüber, welche Android-Version Ihre Benutzer verwenden, aber Sie machen sich Sorgen darüber, welcher ihre Standardbrowser ist (da die App im Hintergrund ihren Standardbrowser verwendet). Typischerweise ist das unter Android Chrome, aber Sie müssen jede Möglichkeit berücksichtigen.
Logistik: Eine Web-App in eine native App verwandeln
Es gibt viel Technologie, die das Versprechen „für das Web bauen, überall veröffentlichen“ erfüllt – React Native, Cordova, Ionic, Meteor und NativeScript, um nur einige zu nennen.
Im Allgemeinen lassen sich diese in zwei Kategorien einteilen:
- Sie schreiben Ihren Code so, wie es ein Framework möchte (nicht genau so, wie Sie es normalerweise tun würden), und das Framework wandelt ihn in eine legitime native App um;
- Sie schreiben Ihren Code auf die übliche Weise, und die Technologie umschließt Ihre Web-Technologie mit einer nativen „Shell“ und täuscht sie im Wesentlichen als native App vor.
Der erste Ansatz mag der wünschenswertere der beiden erscheinen (da Sie am Ende theoretisch eine „echte“ native App haben), aber ich stellte auch fest, dass er die größten Hürden mit sich bringt. Jede Plattform oder jedes Produkt verlangt von Ihnen, dass Sie sich dessen Arbeitsweise aneignen, und diese Arbeitsweise ist zwangsläufig ein ganzes Ökosystem und Framework für sich. Das Versprechen „schreibe einfach, was du kennst“ ist meiner Erfahrung nach eine ziemlich starke Übertreibung. Ich vermute, dass in ein oder zwei Jahren viele dieser Probleme gelöst sein werden, aber im Moment spürt man immer noch eine beträchtliche Lücke zwischen dem Schreiben von Webcode und dem Ausliefern einer nativen App.
Auf der anderen Seite ist der zweite Ansatz aufgrund einer Sache namens „TWA“ praktikabel, die es überhaupt erst ermöglicht, eine Website zu einer App zu machen.
Was ist eine TWA-App?
TWA steht für Trusted Web Activity – und da diese Antwort wahrscheinlich nicht sehr hilfreich ist, lassen Sie uns das etwas genauer aufschlüsseln, ja?
Eine TWA-App verwandelt im Grunde eine Website (oder eine Web-App, wenn man pingelig sein will) mit Hilfe kleiner UI-Tricks in eine native App.
Sie können sich eine TWA-App als einen Browser in Verkleidung vorstellen. Es ist eine Android-App ohne interne Elemente, außer einem Webbrowser. Die TWA-App ist auf eine bestimmte Web-URL ausgerichtet, und wann immer die App gestartet wird, lädt sie anstatt normaler nativer App-Funktionen einfach diese Website – Vollbild, ohne Browser-Steuerelemente, wodurch die Website effektiv so aussieht und sich verhält, als wäre sie eine vollwertige native App.
TWA-Anforderungen
Es ist leicht, den Reiz zu erkennen, eine Website in eine native App zu verpacken. Allerdings qualifiziert sich nicht jede beliebige Seite oder URL; um Ihre Website/App als native TWA-App zu starten, müssen Sie die folgenden Kriterien erfüllen.
- Ihre Seite/App muss eine PWA sein. Google bietet eine Validierungsprüfung als Teil von Lighthouse an, oder Sie können mit Bubblewrap prüfen (mehr dazu gleich).
- Sie müssen das App-Bundle/die APK selbst generieren; es ist nicht ganz so einfach, wie nur die URL Ihrer progressiven Web-App einzureichen und die ganze Arbeit erledigt zu haben. (Machen Sie sich keine Sorgen; wir behandeln eine Möglichkeit, dies zu tun, auch wenn Sie nichts über native App-Entwicklung wissen.)
- Sie müssen einen übereinstimmenden sicheren Schlüssel haben, sowohl in der Android-App als auch auf Ihrer Web-App unter einer bestimmten URL hochgeladen.
Dieser letzte Punkt ist entscheidend für den „vertrauenswürdigen“ Teil; eine TWA-App prüft ihren eigenen Schlüssel und verifiziert dann, dass der Schlüssel Ihrer Webanwendung mit ihm übereinstimmt, um sicherzustellen, dass die richtige Website geladen wird (vermutlich, um böswilliges Hijacking von App-URLs zu verhindern). Wenn der Schlüssel nicht übereinstimmt oder nicht gefunden wird, funktioniert die App zwar weiterhin, aber die TWA-Funktionalität entfällt; sie lädt die Website einfach in einem normalen Browser, mit allem Drum und Dran. Der Schlüssel ist also extrem wichtig für das Erlebnis der App. (Man könnte sagen, es ist ein Schlüssel-Punkt. Sorry not sorry.)
Vorteile und Nachteile beim Erstellen einer TWA-App
Der Hauptvorteil einer TWA-App ist, dass Sie Ihren Code überhaupt nicht ändern müssen – kein neues Framework oder keine neue Plattform zu lernen; Sie erstellen einfach eine Website/Web-App wie gewohnt, und sobald das erledigt ist, ist der App-Code im Grunde auch fertig.
Der Hauptnachteil ist jedoch, dass Apple TWA-Apps nicht unterstützt (obwohl sie zur modernen Ära des Webs und JavaScript beigetragen haben); Sie können sie nicht im Apple App Store listen. Nur Google Play.
Das mag wie ein Dealbreaker klingen, aber bedenken Sie ein paar Dinge
- Denken Sie daran, dass Ihre App, um überhaupt gelistet zu werden, eine PWA sein muss – was bedeutet, dass sie standardmäßig installierbar ist. Benutzer auf jeder Plattform können sie von ihrem Browser aus zum Startbildschirm ihres Geräts hinzufügen. Sie muss nicht im Apple App Store sein, um auf Apple-Geräten installiert zu werden (obwohl sie definitiv an Entdeckungsmöglichkeit verliert). Sie könnten also immer noch eine Marketing-Landingpage in Ihre App integrieren und Benutzer auffordern, sie von dort aus zu installieren.
- Es gibt auch nichts, was Sie davon abhält, eine native iOS-App mit einer völlig anderen Strategie zu entwickeln. Selbst wenn Sie sowohl iOS- als auch Android-Apps wünschen, solange eine Web-App Teil des Plans ist, reduziert eine TWA effektiv die Hälfte dieser Arbeit.
- Während iOS in englischsprachigen Ländern und Japan einen Marktanteil von etwa 50 % hat, hat Android im Rest der Welt weit über 90 %. Je nach Zielgruppe ist der Verzicht auf den App Store also möglicherweise nicht so einschneidend, wie Sie denken.
So generieren Sie die Android App APK
An diesem Punkt könnten Sie sagen: „Dieses TWA-Geschäft klingt gut und schön, aber wie nehme ich meine Website/App und schiebe sie in eine Android-App?“
Die Antwort kommt in Form eines wunderbaren kleinen CLI-Tools namens Bubblewrap.
Sie können Bubblewrap als ein Werkzeug betrachten, das einige Eingaben und Optionen von Ihnen entgegennimmt und aus diesen Eingaben eine Android-App (speziell eine APK, eines der Dateiformate, die vom Google Play Store zugelassen sind) generiert.
Die Installation von Bubblewrap ist etwas knifflig, und obwohl die Verwendung nicht ganz Plug-and-Play ist, ist sie definitiv für einen durchschnittlichen Front-End-Entwickler erreichbarer als alle anderen vergleichbaren Optionen, die ich gefunden habe. Die README-Datei auf der NPM-Seite von Bubblewrap enthält die Details, aber hier ist eine kurze Übersicht
Installieren Sie Bubblewrap, indem Sie npm i -g @bubblewrap/cli ausführen (ich gehe davon aus, dass Sie mit NPM und der Installation von Paketen über die Kommandozeile vertraut sind). Das ermöglicht Ihnen die Verwendung von Bubblewrap überall.
Nach der Installation führen Sie aus
bubblewrap init --manifest https://your-webapp-domain/manifest.json
Hinweis: Die Datei manifest.json ist für alle PWAs erforderlich, und Bubblewrap benötigt die URL zu dieser Datei, nicht nur Ihre App. Seien Sie auch gewarnt: Je nachdem, wie Ihre Manifestdatei generiert wird, kann ihr Name für jeden Build eindeutig sein. (Das PWA-Modul von Nuxt hängt beispielsweise eine eindeutige UUID an den Dateinamen an.)
Beachten Sie auch, dass Bubblewrap standardmäßig validiert, dass Ihre Webanwendung eine gültige PWA ist. Aus irgendeinem Grund kam die Prüfung, als ich diesen Prozess durchlief, immer wieder negativ zurück, obwohl Lighthouse bestätigte, dass es sich tatsächlich um eine voll funktionsfähige progressive Web-App handelte. Glücklicherweise erlaubt Bubblewrap Ihnen, diese Prüfung mit dem Flag --skipPwaValidation zu überspringen.
Wenn Sie Bubblewrap zum ersten Mal verwenden, fragt es Sie, ob Sie das Java Development Kit (JDK) und das Android Software Development Kit (SDK) für Sie installieren möchten. Diese beiden sind die im Hintergrund benötigten Hilfsprogramme, um eine Android-App zu generieren. Wenn Sie unsicher sind, drücken Sie „J“ für Ja.
Hinweis: Bubblewrap erwartet, dass diese beiden Entwicklungsumgebungen an sehr spezifischen Orten vorhanden sind und funktioniert nicht richtig, wenn sie nicht da sind. Sie können bubblewrap doctor ausführen, um dies zu überprüfen, oder das vollständige Bubblewrap CLI README einsehen.
Nachdem alles installiert ist – vorausgesetzt, es findet Ihre manifest.json-Datei unter der angegebenen URL – stellt Bubblewrap einige Fragen zu Ihrer App.

Viele der Fragen betreffen Präferenzen (wie die Hauptfarbe Ihrer App) oder bestätigen einfach grundlegende Details (wie die Domain und den Einstiegspunkt für die App), und die meisten werden aus der Manifestdatei Ihrer Website vorausgefüllt.

Weitere Fragen, die bereits durch Ihr Manifest vorausgefüllt sein können, sind, wo die verschiedenen Icons Ihrer App zu finden sind (als Home-Bildschirm-Icon, Statusleisten-Icon usw.), welche Farbe der Splashscreen beim Öffnen der App haben soll und die Ausrichtung des Bildschirms, falls Sie Hoch- oder Querformat erzwingen möchten. Bubblewrap fragt auch, ob Sie die Erlaubnis für die Standortdaten Ihres Benutzers anfordern möchten und ob Sie sich für Play Billing anmelden.
Es gibt jedoch einige wichtige Fragen, die etwas verwirrend sein können, daher behandeln wir diese hier
- Application ID: Dies scheint eine Java-Konvention zu sein, aber jede App benötigt eine eindeutige ID-Zeichenfolge, die normalerweise aus 2–3 durch Punkte getrennten Abschnitten besteht (z. B.
collinsworth.quina.app). Es spielt eigentlich keine Rolle, was das ist; es ist nicht funktional, sondern nur eine Konvention. Wichtig ist nur, dass Sie es sich merken und dass es eindeutig ist. Beachten Sie jedoch, dass dies Teil der eindeutigen Google Play Store-URL Ihrer App wird. (Aus diesem Grund können Sie kein neues Bundle mit einer bereits verwendeten App-ID hochladen. Stellen Sie also sicher, dass Sie mit Ihrer ID zufrieden sind.) - Starting version: Das spielt im Moment keine Rolle, aber der Play Store verlangt, dass Sie die Version bei jedem Hochladen neuer Bundles erhöhen, und Sie können nicht dieselbe Version zweimal hochladen. Ich würde also empfehlen, mit 0 oder 1 zu beginnen.
- Display mode: Es gibt tatsächlich einige Möglichkeiten, wie TWA-Apps Ihre Website anzeigen können. Hier möchten Sie höchstwahrscheinlich entweder
standalone(Vollbild, aber mit der nativen Statusleiste oben) oderfullscreen(keine Statusleiste) wählen. Ich persönlich habe die Standardoptionstandalonegewählt, da ich keinen Grund sah, die Statusleiste des Benutzers in der App auszublenden, aber je nachdem, was Ihre App tut, könnten Sie anders entscheiden.
Der Signierschlüssel
Das letzte Puzzleteil ist der Signierschlüssel. Das ist der wichtigste Teil. Dieser Schlüssel verbindet Ihre progressive Web-App mit dieser Android-App. Wenn der Schlüssel, den die App erwartet, nicht mit dem in Ihrer PWA gefundenen übereinstimmt, funktioniert Ihre App erneut: sie funktioniert zwar, sieht aber nicht wie eine native App aus, wenn der Benutzer sie öffnet; es ist nur ein normales Browserfenster.
Es gibt zwei Ansätze, die hier zu komplex sind, um sie im Detail zu behandeln, aber ich werde versuchen, einige Hinweise zu geben
- Generieren Sie Ihren eigenen Keystore. Sie können Bubblewrap dies tun lassen oder ein CLI-Tool namens
keytool(passenderweise) verwenden, aber egal wie: Seien Sie sehr vorsichtig. Sie müssen den genauen Namen und die Passwörter für Ihre Keystores explizit verfolgen, und da Sie beide über die Kommandozeile erstellen, müssen Sie extrem vorsichtig mit Sonderzeichen sein, die den gesamten Prozess beeinträchtigen könnten. (Sonderzeichen können auf der Kommandozeile unterschiedlich interpretiert werden, auch wenn sie als Teil einer Passwortabfrage eingegeben werden.) - Lassen Sie Google Ihre Schlüssel verwalten. Das ist ehrlich gesagt nicht dramatisch einfacher nach meiner Erfahrung, aber es erspart einige Mühen bei der Verwaltung Ihrer eigenen Signierschlüssel, indem Sie in die Google Play Developer Console gehen und einen vordefinierten Schlüssel für Ihre App herunterladen können.

Welche Option Sie auch wählen, es gibt hier detaillierte Dokumentation zur App-Signierung (für Android-Apps geschrieben, aber die meisten davon ist noch relevant).
Der Teil, in dem Sie den Schlüssel auf Ihre persönliche Website bekommen, wird in dieser Anleitung zur Verifizierung von Android App Links behandelt. Um es grob zusammenzufassen: Google sucht nach einer Datei /.well-known/assetlinks.json unter diesem genauen Pfad auf Ihrer Website. Die Datei muss Ihren eindeutigen Schlüssel-Hash sowie einige andere Details enthalten
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target" : { "namespace": "android_app", "package_name": "your.app.id",
"sha256_cert_fingerprints": ["your:unique:hash:here"] }
}]
Was Sie über das Auflisten einer App wissen sollten
Bevor Sie beginnen, gibt es auch einige Hürden auf der App-Store-Seite, die Sie beachten sollten
- Zuallererst müssen Sie sich anmelden, bevor Sie im Google Play Store veröffentlichen können. Diese Berechtigung kostet eine einmalige Gebühr von 25 US-Dollar.
- Sobald Sie zugelassen sind, sollten Sie wissen, dass das Auflisten einer App weder schnell noch einfach ist. Es ist eher mühsam als schwierig oder technisch, aber Google prüft jede einzelne App und jedes Update im Store und verlangt, dass Sie viele Formulare und Informationen sowohl über sich selbst als auch über Ihre App ausfüllen, bevor Sie überhaupt mit dem Überprüfungsprozess beginnen können – der selbst viele Tage dauern kann, selbst wenn Ihre App noch nicht einmal öffentlich ist. (Freundlicher Hinweis: Es gibt seit mindestens sechs Monaten ein Warnbanner „Wir erleben längere als übliche Überprüfungszeiten“ in der Play Console-Dashboard.)
- Zu den mühsameren Teilen gehört, dass Sie mehrere Screenshots Ihrer App in Aktion hochladen müssen, bevor die Überprüfung beginnen kann. Dies werden später die Bilder sein, die in der Store-Auflistung angezeigt werden – und bedenken Sie, dass deren Änderung ebenfalls eine neue Überprüfung auslöst. Seien Sie also gut vorbereitet, wenn Sie die Bearbeitungszeit minimieren möchten.
- Sie müssen auch Links zu den Nutzungsbedingungen und der Datenschutzerklärung Ihrer App bereitstellen (was der einzige Grund ist, warum meine App sie überhaupt hat, da sie praktisch sinnlos sind).
- Es gibt viele Dinge, die Sie nicht rückgängig machen können. Zum Beispiel können Sie eine kostenlose App niemals in eine bezahlte umwandeln, selbst wenn sie noch nicht öffentlich gestartet wurde und/oder null Downloads hat. Sie müssen auch bei der Versionierung und Benennung dessen, was Sie hochladen, streng sein, da Google es Ihnen nicht erlaubt, Ihre Apps oder hochgeladenen Bundles zu überschreiben oder zu löschen, und Ihnen nicht immer erlaubt, andere Einstellungen im Dashboard zu ändern. Wenn Sie einen „einfach reinschauen und die Fehler später beheben“-Ansatz verfolgen (wie ich), müssen Sie möglicherweise ein- oder zweimal von Grund auf neu beginnen.
- Mit wenigen Ausnahmen hat Google extrem restriktive Richtlinien für das Sammeln von Zahlungen in einer App. Als ich Quina entwickelte, berechnete es eine Gebühr von 30 % für alle Transaktionen (sie haben diese inzwischen bedingt auf 15 % gesenkt – besser, aber immer noch fünfmal mehr als die meisten anderen Zahlungsanbieter verlangen würden). Google zwingt Entwickler (mit wenigen Ausnahmen) auch, seine eigene native Zahlungsplattform zu verwenden; keine Wahl von Square, Stripe, PayPal usw. in der App.
- Fun Fact: Diese Richtlinie wurde angekündigt, war aber noch nicht in Kraft, als ich versuchte, Quina zu veröffentlichen, und sie wurde trotzdem vom Prüfer wegen eines Verstoßes beanstandet. Sie nehmen diese Richtlinie also sehr ernst.
Monetarisierung, Freischaltungen und die Umgehung von Google
Obwohl mein Ziel mit Quina hauptsächlich persönlich war – mich selbst herauszufordern, zu beweisen, dass ich es kann, und mehr über das Vue-Ökosystem in einer komplexen realen Anwendung zu lernen – hoffte ich als sekundäres Ziel, dass meine Arbeit mir und meiner Familie etwas Geld einbringen könnte.
Nicht viel. Ich hatte nie die Illusion, das nächste Candy Crush zu bauen (noch die ethische Lücke, die nötig ist, um eine süchtig machende Mikrotransaktionsmaschine zu entwickeln). Aber da ich Hunderte von Stunden meiner Zeit und Energie in das Spiel investiert hatte, hoffte ich, vielleicht etwas als Gegenleistung zu bekommen, selbst wenn es nur ein bisschen Biergeld wäre.
Anfangs gefiel mir die Idee, die App zu verkaufen oder Inhalte zu sperren, nicht so sehr, also beschloss ich, nach einer bestimmten Anzahl von Spielen eine einfache Aufforderung „Möchten Sie Quina unterstützen, wenn es Ihnen gefällt?“ hinzuzufügen und einige Inhalte speziell für Unterstützer freischaltbar zu machen. (Wortsets sind standardmäßig begrenzt, und einige Spieleinstellungen sind ebenfalls anfangs gesperrt.) Die Aufforderung zur Unterstützung von Quina kann dauerhaft abgewiesen werden (ich bin kein Monster), und jede Spende schaltet alles frei; kein gestaffelter Zugang oder Vorteile.
Das alles war dank Stripe relativ einfach zu implementieren, sogar ohne Server; es ist alles komplett clientseitig. Ich importiere nur ein bisschen JavaScript auf der Seite /support und verwende die praktische head-Funktion von Nuxt (die Elemente speziell auf der gegebenen Seite zum <head>-Element hinzufügt)
// pages/support.vue
head() {
return {
script: [
{
hid: 'stripe',
src: 'https://js.stripe.com/v3',
defer: true,
callback: () => {
// Adds all Stripe methods like redirectToCheckout to page component
this.stripe = Stripe('your_stripe_id')
},
},
],
}
},
Mit diesem Teil (zusammen mit einer Prise Templating und Logik) können Benutzer ihren Spendenbetrag auswählen – als Produkte auf der Stripe-Seite eingerichtet – und werden zu Stripe weitergeleitet, um die Zahlung abzuschließen, und dann zurückgeleitet, wenn sie fertig sind. Für jede Stufe ist die Rückleitungs-URL über Abfrageparameter leicht unterschiedlich. Vue Router analysiert die URL, um die gespeicherte Spendenshistorie des Benutzers anzupassen und Funktionen entsprechend freizuschalten.

Sie fragen sich vielleicht, warum ich all das preisgebe, da es das System ziemlich einfach zu reverse-engineeren macht. Die Antwort ist: Es ist mir egal. Tatsächlich habe ich selbst eine kostenlose Stufe hinzugefügt, sodass Sie sich nicht einmal die Mühe machen müssen. Ich habe beschlossen, dass es in Ordnung ist, wenn jemand die Freischaltbares wirklich will, aber aus welchem Grund auch immer nicht dafür bezahlen kann oder will. Vielleicht ist es in einer Situation, in der 3 US-Dollar viel Geld sind. Vielleicht hat er schon auf einem anderen Gerät gespendet. Vielleicht tut er stattdessen etwas anderes Nettes. Aber ehrlich gesagt, auch wenn seine Absichten nicht gut sind: na und?
Ich schätze Unterstützung, aber das ist nicht mein Lebensunterhalt, und ich versuche nicht, eine Dopamin-Mautstation zu bauen. Außerdem fühle ich mich mit den ethischen Implikationen nicht wohl, eine Sammlung von völlig Open-Source- und/oder kostenloser Software (ganz zu schweigen von der begleitenden Berg von Dokumentation, Blogbeiträgen und Stack-Overflow-Antworten, die darüber geschrieben wurden) zu verwenden, um einen geschlossenen Garten für persönlichen Gewinn zu bauen.
Also, wenn Ihnen Quina gefällt und Sie es unterstützen können: aufrichtig, danke. Das bedeutet mir sehr viel. Ich sehe gerne, dass meine Arbeit genossen wird. Aber wenn nicht: Das ist in Ordnung. Wenn Sie die „kostenlose“ Option möchten, ist sie für Sie da.
Auf jeden Fall stieß dieser ganze Plan auf ein Hindernis, als ich von Googles neuer Monetarisierungsrichtlinie erfuhr, die ab diesem Jahr in Kraft tritt. Sie können sie selbst lesen, aber um es zusammenzufassen: Wenn Sie mit einer Google Play App Geld verdienen und kein gemeinnütziger Verein sind, müssen Sie über Google Pay gehen und eine saftige Gebühr zahlen – Sie dürfen keinen anderen Zahlungsanbieter verwenden.
Das bedeutete, dass ich die App nicht einmal auflisten konnte; sie wäre blockiert worden, nur weil sie eine „Support“-Seite mit Zahlungen hatte, die nicht über Google liefen. (Ich schätze, ich hätte das umgehen können, indem ich einen gemeinnützigen Verein gründe, aber das schien aus verschiedenen Gründen der falsche Weg zu sein.)
Meine endgültige Lösung war, die App selbst auf Google Play zu bepreisen, indem ich sie für 2,99 $ auflistete (anstatt meines zuvor geplanten Preises von „kostenlos“) und das App-Erlebnis für Android-Benutzer entsprechend anpasste.
Anpassen des App-Erlebnisses für Google Play
Glücklicherweise senden Android-Apps bei der Anfrage einer Website einen benutzerdefinierten Header mit der eindeutigen ID der App. Mit diesem Header war es einfach genug, das App-Erlebnis im Web und in der tatsächlichen Android-App zu unterscheiden.
Für jede Anfrage prüft die App auf die Android-ID; wenn vorhanden, setzt die App einen Vuex-Zustands-Boolean namens isAndroid auf true. Dieser Zustand kaskadiert durch die App und löst verschiedene Bedingungen aus, um Dinge wie das Ausblenden und Anzeigen verschiedener FAQ-Fragen zu tun, und (am wichtigsten) um die Support-Seite im Navigationsmenü auszublenden. Außerdem schaltet es alle Inhalte standardmäßig frei (da der Benutzer auf Android bereits „gespendet“ hat, indem er gekauft hat). Ich ging sogar so weit, einfache <WebOnly> und <AndroidOnly> Vue Wrapper-Komponenten zu erstellen, um Inhalte zu umschließen, die nur für eines von beiden bestimmt sind. (Offensichtlich sollten Benutzer unter Android, die die Support-Seite nicht besuchen können, keine FAQs zu diesem Thema sehen, als Beispiel.)
<!-- /src/components/AndroidOnly.vue -->
<template>
<div v-if="isAndroid">
<slot />
</div>
</template>
<script>
export default {
computed: {
isAndroid() {
return this.$store.state.isAndroid
},
},
}
</script>
Berücksichtigung von Konten
Eine Zeit lang hatte ich beim Erstellen von Quina Firebase für Logins und das Speichern von Benutzerdaten eingerichtet. Ich mochte die Idee sehr, Benutzern zu erlauben, auf allen ihren Geräten zu spielen und ihre Statistiken überall zu verfolgen, anstatt eine separate Historie auf jedem Gerät/Browser zu haben.
Letztendlich habe ich diese Idee jedoch aus ein paar Gründen verworfen. Einer war die Komplexität; es ist nicht einfach, ein sicheres Kontensystem und eine Datenbank zu pflegen, selbst mit einem guten System wie Firebase, und dieser Aufwand ist nichts, was ich leichtfertig auf mich genommen habe. Aber hauptsächlich: Die Entscheidung lief auf Sicherheit und Einfachheit hinaus.
Am Ende des Tages wollte ich nicht für die Daten der Benutzer verantwortlich sein. Ihre Privatsphäre und Sicherheit sind durch die Verwendung von localStorage gewährleistet, zum kleinen Preis der Portabilität. Ich hoffe, die Spieler stört die Möglichkeit, ihre Statistiken von Zeit zu Zeit zu verlieren, wenn es bedeutet, dass sie sich keine Sorgen um Login oder Daten machen müssen. (Und hey, es gibt ihnen auch die Chance, diese Auszeichnungen noch einmal zu verdienen.)
Außerdem fühlt es sich einfach gut an. Ich kann ehrlich sagen, dass meine App Ihre Sicherheit oder Daten nicht kompromittieren kann, weil sie buchstäblich nichts über Sie weiß. Und außerdem muss ich mich nicht um Compliance oder Cookie-Warnungen oder ähnliches kümmern.
Zusammenfassung
Die Erstellung von Quina war mein bisher ehrgeizigstes Projekt, und ich hatte genauso viel Spaß beim Entwerfen und Entwickeln wie daran, Spieler zu sehen, die es genießen.
Ich hoffe, diese Reise war für Sie hilfreich! Obwohl das Auflisten einer Web-App im Google Play Store viele Schritte und potenzielle Fallstricke hat, ist es für einen Front-End-Entwickler definitiv erreichbar. Ich hoffe, Sie nehmen diese Geschichte als Inspiration, und wenn ja, bin ich gespannt, was Sie mit Ihrem neu gewonnenen Wissen bauen werden.
Dieser Beitrag ist Gold!
Danke! Wirklich tolle Informationen, ich möchte es unbedingt mit React ausprobieren
Sehr interessant zu hören, wie Sie das mit Vue umgesetzt haben! Ich habe kürzlich genau dasselbe mit meiner React-App Crab Fit gemacht, obwohl ich, um das Spenden-IAP-Problem zu umgehen, die Digital Goods API verwende, um einen In-App-Kauf von der PWA aus durchzuführen. Vielleicht etwas zum Nachdenken, wenn Sie Ihre App kostenlos halten möchten, aber es erfordert derzeit auch Chrome und Sie müssen sich für den Origin Trial anmelden.
Wie viel Geld kann eine solche App im Monat oder Jahr einbringen?
Vielen Dank für diesen großartigen Beitrag.
Hey, Chris – das ist eine ziemlich schwierige Frage zu beantworten, da sie vollständig davon abhängt, wie beliebt die App ist. Ich bin sicher, dass einige Apps auf Google Play ihren Erstellern ein Auskommen ermöglichen und andere wenig bis gar nichts einbringen.
Ich glaube, ein ausreichend talentierter und motivierter Mensch könnte definitiv einen lohnenden Betrag mit einer guten App verdienen, gut vermarktet an die richtige Zielgruppe.
In meinem speziellen Fall habe ich jedoch nicht wirklich darauf optimiert. Was ich mit Quina verdient habe, könnte man besser als „Biergeld“ denn als „Mietgeld“ bezeichnen. Wenn Geld das Ziel gewesen wäre, wäre es für mich besser gewesen, mit diesen Stunden freiberuflich tätig zu sein. Aber jeder und jede App wird anders sein, und für mich war es die Erfahrung wert.
Gibt es einen Grund, warum sie nicht in allen Ländern verfügbar ist? Ich wollte testen, wie die App-Erfahrung im Vergleich zu nativen Apps ist, aber sie ist in meinem Land nicht verfügbar.
Hallo Dominik! Wenn ich mich richtig erinnere, hatte Google einige Einschränkungen bei der Veröffentlichung in allen Ländern, daher habe ich die App nur in Ländern mit einem überdurchschnittlichen Anteil englischsprachiger Bevölkerung gelistet.
Im Rückblick war das wahrscheinlich ein bisschen... gibt es ein Wort für „behindertengerecht“, aber in Bezug auf Sprachen? Zumindest anmaßend von mir.
Ich schaue aber gerne nach, ob ich sie in neuen Ländern hinzufüge, wenn Sie mir mitteilen, welche das sein könnten! :) In der Zwischenzeit würde vielleicht ein VPN funktionieren?
Ich bin nur vorbeigekommen, um zu sagen, dass Ihre Aussprache richtig ist. In Brasilien ist Quina auch der Name eines Lotteriespiels, bei dem man alle 5 Zahlen in der richtigen Reihenfolge erraten muss, um zu gewinnen. Es bedeutet auch 5 zusammen gruppierte Dinge. Es ist schön, dass Sie so weit gegangen sind, Ihr Spiel zu benennen, es zeigt, wie sehr Sie sich kümmern und wie enthusiastisch Sie sind. Ich werde es wahrscheinlich nur deswegen ausprobieren. Danke fürs Teilen!
Ehrlich, großartige Arbeit! Obwohl mein Interesse an anderen Technologien liegt, habe ich Ihren Beitrag bis zum Ende gelesen. Er ist gut geschrieben und erklärt das Thema App-Entwicklung gut für Uneingeweihte. Alles mit realistischen Erwartungen, Fallstricken und schwierigen Entscheidungen, die getroffen werden müssen.
Auf zum Play Store, um Ihre App auszuprobieren.
Sehr gute Lektüre, sehr gut aufbereitet ^_^
Sie könnten Privatsphäre und Sicherheit auch gewährleisten, indem Sie die Unterstützung für Solid aktivieren. Auf diese Weise könnten Benutzer auf ihre Daten über verschiedene Implementierungen hinweg zugreifen.
Bester Beitrag, den ich seit langem gelesen habe. Wirklich toller Artikel. Praktisch, klar & ansprechend. Danke, dass Sie Ihre Erfahrungen teilen.
Ich habe nach „fünf auf einmal auf Latein“ gegoogelt, und es scheint „quini“ zu sein?
quini auf Wiktionary
Sie haben ehrlich gesagt großartige Arbeit geleistet! Obwohl mein Interesse an anderen Technologien liegt, habe ich den gesamten Beitrag gelesen. Der Artikel ist gut geschrieben und bietet Einblicke in die App-Entwicklung für diejenigen, die damit nicht vertraut sind. Es gibt Herausforderungen, Fallstricke und Entscheidungen, die getroffen werden müssen.
Gehen wir zum Play Store, um Ihre App auszuprobieren.
Hallo Josh,
Ihre App Quina ist in Indien bei Google Play nicht verfügbar. Warum?
Bitte machen Sie sie verfügbar.
Ich möchte testen, wie Vue/Nuxt als Webview funktioniert, wie performant es ist. Ich mache auch viel in Vue
Danke
Hallo, Kumar. Ich habe gerade Indien zur Liste der Länder für die App hinzugefügt.
Was es wert ist, muss ich jedoch sagen: In letzter Zeit hat Google Play die App mehrmals fehlerhaft gesperrt, und wenn es weiter so geht, werde ich sie vielleicht ganz entfernen. Sie wird immer unter quina.app verfügbar sein, und aus meiner persönlichen Erfahrung funktioniert die Installation als PWA identisch mit der Installation als Android-App.