{"id":1902,"date":"2021-01-26T15:03:01","date_gmt":"2021-01-26T15:03:01","guid":{"rendered":"https:\/\/www.art-events.de\/weblog\/?p=1902"},"modified":"2021-10-03T18:10:53","modified_gmt":"2021-10-03T18:10:53","slug":"android-app-kann-nicht-speichern","status":"publish","type":"post","link":"https:\/\/www.art-events.de\/weblog\/android-app-kann-nicht-speichern\/","title":{"rendered":"Android App kann nicht speichern"},"content":{"rendered":"<p><a href=\"https:\/\/www.art-events.de\/weblog\/wp-content\/uploads\/2021\/01\/210126android.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-1909\" src=\"https:\/\/www.art-events.de\/weblog\/wp-content\/uploads\/2021\/01\/210126android-1024x674.jpg\" alt=\"\" width=\"640\" height=\"421\" srcset=\"https:\/\/www.art-events.de\/weblog\/wp-content\/uploads\/2021\/01\/210126android-1024x674.jpg 1024w, https:\/\/www.art-events.de\/weblog\/wp-content\/uploads\/2021\/01\/210126android-300x197.jpg 300w, https:\/\/www.art-events.de\/weblog\/wp-content\/uploads\/2021\/01\/210126android-768x505.jpg 768w, https:\/\/www.art-events.de\/weblog\/wp-content\/uploads\/2021\/01\/210126android.jpg 1271w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>oder warum die Sache mit Scope Storage wichtig ist!<\/p>\n<p>Bei mir kommt es h\u00e4ufig vor: wir haben eine Excel Tabelle \/ XLS CSV Datei, die der Benutzer per USB Transfer ins \/Download Verzeichnis des Android Ger\u00e4tes schiebt. Die Anwendung nimmt die Datei, arbeitet sie ab und stellt sie f\u00fcr den R\u00fccktransport bereit. Oder zum Beispiel die AE Simple Barcode App &#8211; Strichcode einfach mit der Cam Eures Smartphones erfassen und zusammen mit Mengeneingabe als XLS CSV Datei f\u00fcr Excel speichern. So lassen sich leicht Bestellungen \/ Inventuren oder Warenbewegungen aller Art vor Ort erfassen. (<a href=\"https:\/\/www.terminal-systems.de\/wp\/home-2\/mobile1\/simplebarcode-app\/\" target=\"_blank\" rel=\"noopener noreferrer\">AE Simple App hier.<\/a>)<\/p>\n<p>Damit das Ganze l\u00e4uft war das bisher doch mehr oder minder einfach: Als Android Entwickler m\u00fcsst Ihr im Manifest Eurer Anwendung die Rechte entsprechend anfordern. Nach der Installation Eurer Software muss der Benutzer Eurer App die Rechte auch gew\u00e4hren! Nur wenn diese beiden Bedingungen erf\u00fcllt sind ist z.B der Zugriff auf Camera oder Speicher m\u00f6glich.<\/p>\n<p>Bild: Im Manifest Eurer Anwendung &#8211; die Rechte zum Schreiben und Lesen anfordern:<\/p>\n<blockquote>\n<pre>&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\r\n&lt;manifest xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"\r\n    package=\"de.terminalsystems.aedonxiestorageapp\"&gt;\r\n\r\n    &lt;uses-permission android:name=\"android.permission.WRITE\\_EXTERNAL\\_STORAGE\" \/&gt;\r\n    &lt;uses-permission android:name=\"android.permission.READ\\_EXTERNAL\\_STORAGE\" \/&gt;<\/pre>\n<pre>    &lt;uses-permission android:name=\"android.permission.CAMERA\" \/&gt;<\/pre>\n<\/blockquote>\n<p>Bild: Der Benutzer muss die Rechte gew\u00e4hren<\/p>\n<p><a href=\"https:\/\/www.art-events.de\/weblog\/wp-content\/uploads\/2021\/01\/210120android4a.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1893\" src=\"https:\/\/www.art-events.de\/weblog\/wp-content\/uploads\/2021\/01\/210120android4a.png\" alt=\"\" width=\"308\" height=\"600\" srcset=\"https:\/\/www.art-events.de\/weblog\/wp-content\/uploads\/2021\/01\/210120android4a.png 308w, https:\/\/www.art-events.de\/weblog\/wp-content\/uploads\/2021\/01\/210120android4a-154x300.png 154w\" sizes=\"auto, (max-width: 308px) 100vw, 308px\" \/><\/a><\/p>\n<p>Nun schleppten uns unsere Kollegen ein Ger\u00e4t mit Android 10 an &#8211; und Essig war es mit dem Speichern! Obwohl der Benutzer die Speicherberechtigung erteilt hat &#8211; die App weigerte sich\u00a0 hartn\u00e4ckig Daten zu speichern.<\/p>\n<p>Bei n\u00e4herem Suchen stellt sich heraus: Unsere L\u00f6sung war bisher g\u00e4ngige Praxis bis Android Version 9 \/ API Level 28. Ab Android Version 10 \/ API Level 29 hat Google sich etwas Neues \u00fcberlegt: Das SCOPED STORAGE, zu deutsch: abgegrenztes Speichern.<\/p>\n<p>In d\u00fcrren Worten: Die Manifest Anweisung android.permission.WRITE\\_EXTERNAL\\_STORAGE&#8230; hat dabei keine relevante Wirkung mehr. Das Speichern wird verweigert, vollkommen egal ob der User die Rechte entsprechend vergeben hat. Ihr m\u00fcsst nun in Eurer Anwendung je nachdem verfahren, ob ihr Media Daten oder NON Media Dateien speichern wollt. Wie das im Detail geht erfahrt ihr bei Google hier:<\/p>\n<p><a href=\"https:\/\/developer.android.com\/training\/data-storage\/use-cases\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/developer.android.com\/training\/data-storage\/use-cases<\/a><\/p>\n<p>Wir haben das zum Zeitpunkt dieser Zeilen noch nicht eingearbeitet. Deshalb belassen wir es mal bei dem Link. Stattdessen:<\/p>\n<p>\u00dcbergangsweise, d.h. nur f\u00fcr Versionen bis Android 10 k\u00f6nnt Ihr dieses Verfahren noch tempor\u00e4r durch folgenden Eintrag im Manifest umgehen:<\/p>\n<blockquote>\n<pre>android:requestLegacyExternalStorage=\"true\"&gt;<\/pre>\n<\/blockquote>\n<p>Der Application Bereich in Eurem Manifest sieht dann so oder \u00e4hnlich aus:<\/p>\n<blockquote>\n<pre>&lt;application\r\n    android:allowBackup=\"true\"\r\n    android:icon=\"@mipmap\/ic_launcher\"\r\n    android:label=\"@string\/app_name\"\r\n    android:roundIcon=\"@mipmap\/ic_launcher_round\"\r\n    android:supportsRtl=\"true\"\r\n    android:theme=\"@style\/Theme.AEDonxieStorageApp\"\r\n    android:requestLegacyExternalStorage=\"true\"&gt;<\/pre>\n<\/blockquote>\n<p>Eure App sollte dann wieder in der Lage sein die Dateien zu speichern!<\/p>\n<p>Allerdings Vorsicht: Diese L\u00f6sung ist lt Google nur tempor\u00e4r m\u00f6glich, d.h. ab Android 11 wird der Parameter requestLagecaExternalStorage=&#8220;true&#8220; ignoriert und ihr m\u00fcsst (!) Eure Anwendung dann auf Scope Storage umgestellt haben bzw. das Storage Access Frame Network SAF f\u00fcr Dateioperationen verwenden.<\/p>\n<p>Text und Entwurf. (c) AE SYSTEME Testcenter<br \/>\nHans-J. Walter\u00a0<a href=\"mailto:hjw@terminal-systems.de\">hjw@terminal-systems.de<\/a><\/p>\n<p><em>Hinweis: Alle Angaben ohne Gew\u00e4hr. Diese Beschreibung bezieht sich auf unsere Installation und stellt keine Bewertung der verwendeten Techniken da.\u00a0<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>oder warum die Sache mit Scope Storage wichtig ist! Bei mir kommt es h\u00e4ufig vor: wir haben eine Excel Tabelle \/ XLS CSV Datei, die der Benutzer per USB Transfer ins \/Download Verzeichnis des Android Ger\u00e4tes schiebt. Die Anwendung nimmt die Datei, arbeitet sie ab und stellt sie f\u00fcr den R\u00fccktransport bereit. Oder zum Beispiel [&hellip;]<\/p>\n","protected":false},"author":6,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[33,34,18],"tags":[],"class_list":["post-1902","post","type-post","status-publish","format-standard","hentry","category-android","category-programmierung","category-software-technical-view","entry"],"_links":{"self":[{"href":"https:\/\/www.art-events.de\/weblog\/wp-json\/wp\/v2\/posts\/1902","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.art-events.de\/weblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.art-events.de\/weblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.art-events.de\/weblog\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/www.art-events.de\/weblog\/wp-json\/wp\/v2\/comments?post=1902"}],"version-history":[{"count":0,"href":"https:\/\/www.art-events.de\/weblog\/wp-json\/wp\/v2\/posts\/1902\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.art-events.de\/weblog\/wp-json\/wp\/v2\/media?parent=1902"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.art-events.de\/weblog\/wp-json\/wp\/v2\/categories?post=1902"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.art-events.de\/weblog\/wp-json\/wp\/v2\/tags?post=1902"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}