Android 10 oder 11 – die Sache mit der Artikeldatei.
Oder: die URI lebt kürzer als Mancher glaubt
Ich habe das Verfahren seit Jahren und in unzähligen Anwendungen verwendet: der Benutzer lädt (per USB / FTP o.ä) Artikeldatei / Artikelliste in sein Android Gerät – und die App hat sofort Zugriff auf die dort gespeicherten Informationen.
Nach Eingabe einer Artikelnummer können so z.b. Artikeltexte, Lagerorte, Bestände uvam angezeigt werden und stehen dem User bei der Nutzung der App zur Verfügung. Voraussetzung: Name der Artikeldatei muss der Anwendung bekannt sien. Beispiel: Wenn die App z.b. eine Liste mit dem Namen ARTIKEL.TXT erwartet, lädt der Anwender diese Liste per USB in das Smartphone – und die App kann jederzeit nachschauen.
Der Vorteil dieser Konstruktion: Die Artikelliste kann jederzeit im lfd Betrieb ausgetauscht werden, ohne dass der Benutzer es merkt. Die App greift jeweils zur Laufzeit auf die Informationen zu und präsentiert so immer einen stabilen Zustand.
Bis Android 10 bot sich hierfür das leicht erreichbare Verzeichnis \DOWNLOADS an. Der Anwender kann es per USB / FTP schnell adressieren. Die App kann die Daten lesen und nutzen. In der App Programmierung waren das lediglich im Manifest zu berücksichtigen.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />android:requestLegacyExternalStorage="true"
Mit Einführung Android 11 gibt es bei diesem Konzept Schwierigkeiten. Zuallererst: den ganzen o.a. Permission-Krempel im Manifest benötigt man nicht mehr! Das Sicherheitskonzept ab Android 11 (eine Anwendung hat keinen Zugriff auf Daten u. Dateien, die von einer anderen Anwendung erstellt wurden) verhindert, dass eine separat per USB / FTP gespeicherte Datei ARTIKEL.TXT von der Anwendung genutzt werden kann.
Um die Artikelliste auch in Android 11 zu verwenden, wird zukünftig das Google Storage Access Frame Network SAF verwendet. Hierbei sind Intent für die Aktionen ACTION_OPEN_DOCUMENT
, ACTION_CREATE_DOCUMENT
und Uri notwendig, die von der Anwendung für Dateiopperationen bereit gestellt wird.
In der Praxis kann dann der App Benutzer seine Artikelliste erst mal selbst auswählen und so für die Anwendung freigeben. Der Vorteil außer Datensicherheit: man muss sich nicht mehr nur auf lokale Dateien beschränken, sondern kann auch Daten in der Cloud auswählen und freigeben / mit anderen Dateinamen oder Speicherverzeichnissen arbeiten.
Doch für meine aktuelle Aufgabe ist der Vorteil erst mal keiner.
Mein bisheriges Verfahren läuft nicht mehr. Ich könnte jetzt auf die Idee kommen: Unterm Strich ist die Uri nur ein String. Also einmal irgendwo im Programm die Datei freigeben, dann den String nehmen, speichern und ihn in der App in den Activities verwenden, wo er benötigt wird. Bsp: in einer Activity A Settings wählt der Nutzer die Artikeldatei aus, die Uri wird erzeugt, in Preferences gespeichert und in einer Activity B Datenerfassung verwendet.
Nette Idee. Speichern in Activity A in geht auch:
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences.Editor e = prefs.edit(); e.putString("Uri4ArtFile", uri.toString()); e.apply();
Laden in Activity B dann z.B:
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); Uri uri = Uri.parse (prefs.getString("URIArtFile", ""));
Doch das Ergebnis in der Praxis: Geht nicht! Zur Laufzeit gibt es einen Absturz. In Activity B erhält die Anwendung ein Permission Denied Problem! Die Artikeldaten stehen nicht zu Verfügung.
Fakt: Die normale Uri schafft es nicht über die Lebensdauer einer Activity hinaus! Mit diesem Problem haben sich schon andere beschäftigt, z.b. in diesem Text hier: https://commonsware.com/blog/2016/08/10/uri-access-lifetime-shorter-than-you-might-think.html
Wenn also aktuelle Artikeldaten benötigt werden, müssen unter Android 11 andere Konzepte erstellt werden! (Die der Übersichtlichkeit halber in anderen Beiträgen aufgeführt werden.) Was bis dato aber noch funktioniert, zumindest solange ich die betreffende App nicht im App Store veröffentliche: für Dateien konsequent ein eigenes Verzeichnis verwenden und in der App Target SDK29 eintragen. Dann klappt es mit Android 10 Funktionen auch auf Android 11 Geräten. Und die Lösungen für SDK30 (Android 11) kommen dann später.
compileSdkVersion 29
minSdkVersion 19
targetSdkVersion 29
Text und Entwurf. (c) AE SYSTEME Testcenter, Hans-J. Walter
Hans-J. Walter ist Programmierer für Windows DOT.NET und Android und als Senior Chef Entwickler bei AE SYSTEME www.terminal-systems.de in Burgdorf / Hannover tätig. hjw@terminal-systems.de
Für diese und alle nachfolgenden Seiten gilt ebenso der obligatorische Hinweis: Alle Angaben ohne Gewähr. Bilder und Codes zeigen Beispiele. Diese Beschreibung bezieht sich auf unsere Installation und stellt keine Bewertung der verwendeten Techniken da. Fehler und Irrtümer vorbehalten!