{"id":203,"date":"2021-04-16T18:41:05","date_gmt":"2021-04-16T18:41:05","guid":{"rendered":"http:\/\/erdbeerbeet.com\/?p=203"},"modified":"2021-09-06T13:41:48","modified_gmt":"2021-09-06T13:41:48","slug":"meine-flutter-fahrt-was-gibts-neues-nachrichten","status":"publish","type":"post","link":"https:\/\/erdbeerbeet.com\/de\/meine-flutter-fahrt-was-gibts-neues-nachrichten","title":{"rendered":"Meine Flutter-Fahrt &#8211; &#8220;Was gibt&#8217;s Neues&#8221; Nachrichten"},"content":{"rendered":"\n<p>Ich habe diese Idee eine ganze Weile mit mir herum getragen; Wenn ich ein neues Update f\u00fcr meine App ver\u00f6ffentliche, will ich meinen Benutzern mit einem schicken Dialog mitteilen, was es Neues gibt.<br>Au\u00dferdem bekomme ich wiederholt Nachfragen zu grundlegenden Funktionalit\u00e4ten, die sich gut in einem Tutorial machen w\u00fcrden. Schlie\u00dflich will ich meine App auch nicht mit Infotexten zukleistern.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Das Problem<\/h2>\n\n\n\n<p>F\u00fcr Erstbenutzer will ich ein kurzes Tutorial anzeigen, in dem die etwas versteckten Funktionalit\u00e4ten vorgestellt werden (Wischgesten sind offenbar noch immer nicht intuitiv). Das soll Frustration und h\u00e4ufige Nachfragen verhindern.<br>Entsprechend soll beim ersten \u00d6ffnen der App eine Serie von Dialogen angezeigt werden, um diese Funktionen zu erkl\u00e4ren. Aber auch nur beim ersten \u00d6ffnen.<\/p>\n\n\n\n<p>Zus\u00e4tzlich m\u00f6chte ich einen Dialog anzeigen, der die zugef\u00fcgten Datens\u00e4tze oder Funktionalit\u00e4ten eines neuen Updates anzeigt. Diese Informationen stehen zwar auch in den App-Store-Eintr\u00e4gen, aber die werden nicht sonderlich h\u00e4ufig gelesen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Die Lehrbuch-L\u00f6sung<\/h2>\n\n\n\n<p>Ich brauchte <a href=\"https:\/\/stackoverflow.com\/questions\/60226374\/flutter-display-change-log-release-notes-whats-new-after-upgrade-to-new\">Stackoverflow<\/a> um auf die richtige Idee zu kommen. Einfacher als gedacht.<\/p>\n\n\n\n<p>Kurz gesagt wird die Version der App abgespeichert und dann mit der aktuellen verglichen, sobald die App gestartet wird. Ein neuer Versionscode wird sich vom abgespeicherten unterscheiden und wenn noch keine Version gespeichert ist, dann haben wir einen neuen Nutzer vor uns und zeigen das Tutorial.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Das Programmieren<\/h2>\n\n\n\n<p>Dieser Code kommt in die <strong>main.dart<\/strong>, wo die App initial geladen und gebaut wird. Hier ist wichtig zu bedenken, dass die Preferences geladen sein m\u00fcssen, bevor man sie abfragt. Anderenfalls bekommt man immer null zur\u00fcck (und zeigt entsprechend das Tutorial an).<\/p>\n\n\n\n<p>Je nach Aufbau der konkreten App muss dieser Schritt nicht unbedingt notwendig sein.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Preferences prefs;\nPackageInfo packageInfo;\n\n@override\n void initState() {\n   super.initState();\n   _loading();\n }\n\nFuture&lt;void&gt; _loading() async {\n   try {\n     await prefs.load();\n     _checkVersion();\n     return;\n   } on Exception catch (e) {\n      \/\/ TODO handle exception\n   }\n  \nFuture&lt;void&gt; _checkVersion() async {\n   String savedVersion = prefs.getVersion();\n   packageInfo = await PackageInfo.fromPlatform();\n   String runningVersion = packageInfo.version;\n   if (savedVersion == null) {\n     _showTutorial();\n   } else if (savedVersion != runningVersion) {\n     _showUpdates();\n   }\n }<\/code><\/pre>\n\n\n\n<p>Die Version muss in <strong>Preferences.dart<\/strong> abgespeichert werden. Wenn kein Wert gesetzt ist (initialer Zustand), dann soll <code>null<\/code> die Anzeige des Tutorials ansto\u00dfen.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  String version;\n\n  \/*\n    returns null when no version is set yet\n   *\/\n  String getVersion() {\n    return version; \/\/ returning null is a valid option\n  }\n\n  void setVersion(String newVersion) {\n    version = newVersion;\n    sharedPreferences.setString('version', newVersion);\n  }\n\n  void _load() async {\n    sharedPreferences = await SharedPreferences.getInstance();\n    version = sharedPreferences.getString('version');\n  }\n<\/code><\/pre>\n\n\n\n<p>Die Versionscodes um die es hier geht kommen aus dem Projekt &#8211; abh\u00e4ngig von der Platform, f\u00fcr die gebaut wird. <\/p>\n\n\n\n<p>W\u00e4hrend des Debuggens ist der Eintrag <code>version: 2.0.0+1<\/code> (oder so \u00e4hnlich) aus der <strong>pubspec.yaml<\/strong> relevant. Hier muss die Versionsnummer f\u00fcr den Test angepasst werden.<\/p>\n\n\n\n<p>Die Versionsnummer wird f\u00fcr das eigentliche Release \u00fcberschrieben. F\u00fcr Android in <strong>local.properties<\/strong>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>flutter.buildMode=debug\nflutter.versionName=<mark>2.0.0<\/mark>\nflutter.sdk=\/Library\/flutter\nsdk.dir=\/Users\/erdbaerchen\/Library\/Android\/sdk\nflutter.versionCode=1<\/code><\/pre>\n\n\n\n<p>F\u00fcr iOS innerhalb von XCode, im General Reiter des Runners.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized wp-duotone-duotone-2\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/erdbeerbeet.com\/wp-content\/uploads\/2021\/04\/xcode-versionnumber-1024x340.png\" alt=\"\" class=\"wp-image-204\" width=\"487\" height=\"162\" srcset=\"https:\/\/erdbeerbeet.com\/wp-content\/uploads\/2021\/04\/xcode-versionnumber-1024x340.png 1024w, https:\/\/erdbeerbeet.com\/wp-content\/uploads\/2021\/04\/xcode-versionnumber-300x100.png 300w, https:\/\/erdbeerbeet.com\/wp-content\/uploads\/2021\/04\/xcode-versionnumber-768x255.png 768w, https:\/\/erdbeerbeet.com\/wp-content\/uploads\/2021\/04\/xcode-versionnumber.png 1036w\" sizes=\"auto, (max-width: 487px) 100vw, 487px\" \/><\/figure>\n\n\n\n<p>F\u00fcr mich war zum Debugging das Anpassen der Versionsnummer in der pubspec.yaml stets die passende Option.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Das Ergebnis<\/h2>\n\n\n\n<p>Die Methoden _showTutorial() und _showUpdates() nutzen in meinem Fall showDialog() und zeigen einen Text an, den ich je nach Update anpasse.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized wp-duotone-duotone-2\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/erdbeerbeet.com\/wp-content\/uploads\/2021\/04\/Bildschirmfoto-2021-04-15-um-22.04.01.png\" alt=\"\" class=\"wp-image-205\" width=\"306\" height=\"242\" srcset=\"https:\/\/erdbeerbeet.com\/wp-content\/uploads\/2021\/04\/Bildschirmfoto-2021-04-15-um-22.04.01.png 562w, https:\/\/erdbeerbeet.com\/wp-content\/uploads\/2021\/04\/Bildschirmfoto-2021-04-15-um-22.04.01-300x237.png 300w\" sizes=\"auto, (max-width: 306px) 100vw, 306px\" \/><\/figure>\n\n\n\n<p>Ich muss sagen, dass ich von diesem Feature so begeistert bin, dass ich es jetzt \u00fcberall einbauen werde.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>For first time users and after an update, I want to display information to my users. A tutorial or release notes.<\/p>\n","protected":false},"author":1,"featured_media":384,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[48,13,12],"tags":[14],"class_list":["post-203","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-companero","category-flutter","category-programming","tag-flutter"],"translation":{"provider":"WPGlobus","version":"3.0.0","language":"de","enabled_languages":["en","de"],"languages":{"en":{"title":true,"content":true,"excerpt":true},"de":{"title":true,"content":true,"excerpt":false}}},"_links":{"self":[{"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/posts\/203","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/comments?post=203"}],"version-history":[{"count":9,"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/posts\/203\/revisions"}],"predecessor-version":[{"id":299,"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/posts\/203\/revisions\/299"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/media\/384"}],"wp:attachment":[{"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/media?parent=203"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/categories?post=203"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/tags?post=203"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}