Bewertung [ Bewertung abgeben ] Artikel geschrieben am 11.06.2025 um 23:40 Uhr, aktualisiert am 12.06.2025, um 00:00 Uhr.
Jedes Mobile Betriebssystem bietet eine Möglichkeit für Unternehmen die Geräte zu verwalten. Software wie Microsoft Intune oder Jamf Pro sind dabei nur zwei von vielen Anbietern. Mit einigen Ausnahmen, die vorwiegend in den günstigen und kostenlosen Angeboten vorkommen, lässt sich aber in jeder dieser Software für Apps einen Schwung an Konfigurationsparameter hinterlegen.
Einige bieten eine AppConfig an, was es leichter in der Einrichtung macht, aber sofern eine Liste der Möglichen Parameter vorliegt ist das für eine Konfiguration nicht notwendig. Diese AppConfig ist nichts anderes als ein XML-Schema, dass die möglichen Parameter und eine Eingabe-Struktur enthält, womit die Software eine schöne Oberfläche erzeugen kann, anstatt Key-Value-Pair-Eingabefelder mit einem Datentyp anzubieten. Nett von den Entwicklern, aber im Zweifel möchte man von der eigenen Software nicht nach außen publizieren, welche Parameter es überhaupt gibt. Das sei aber nur der vollständigkeitshalber erwähnt. Damit die eigene App in den übertragenen Einstellungen lesen kann, benötigt sie kein Schema.
Wichtig: Wird reden in diesem Fall vorwiegend für die Plattform iOS / iPadOS. Da alle Apple-Plattformen ähnlich oder in diesen Teilen sogar identisch aufgebaut sind, lassen sich natürlich diese Parameter auch auf diesen auslesen, sofern die MDM-Software diese Plattform verwalten kann. Für Android gibt es auch eine Möglichkeit, wird aber hier nicht beleuchtet.
Zunächst müssen wir kurz über das NSUserDefaults-Objekt sprechen. Jeder Apple-Entwickler kommt früher oder später mit diesem Datenspeicher in Berührung. Er dient seit jeher einer Anwendung zum Speichern von Einstellungen und kann als Ersatz für die Registry unter Windows angesehen werden. Nur das wir hier von einer eindeutigen Datei reden, die der Anwendung zugeordnet wird und auch nur von dieser (sofern wir von der Sandbox reden) gelesen werden kann. Normalerweise schreibt man in diese Datei die letzte Fensterposition, die zuletzt geöffnete Datei oder das vom Benutzer gewünschte Theme. Da diese plist-Datei allerdings nicht direkt gelesen wird, sondern immer mithilfe des NSUserDefaults-Objekt, dass uns das Betriebssystem zur Verfügung stellt, gibt es Besonderheiten.
Sofern eine MDM-Software auf ein Gerät nämlich für die App Einstellungen verteilt, taucht in diesem Shared Object der neue Schlüssel com.apple.configuration.managed auf. Wie schon erwähnt, überträgt man oft eine Sammlung von Key-Value-Pairs. Das bedeutet, dass unter diesem Schlüssel ein NSDictionary-Objekt zu finden ist, das über die eingestellten Werte verfügt. Auf genau diese Werte wollen wir zugreifen, idealerweise beim starten unserer App. Beispielhaft hinterlegen wir eine Skalierung, damit unsere Anwendung für den jeweiligen Einsatzzweck vorkonfiguriert werden kann. Den Schlüssel nennen wir schlicht skalierung.
In Swift lässt sich auf diesen Wert relativ leicht zugreifen, mit ein paar wenigen Zeilen:
if let managedConf = UserDefaults.standard.object(forKey: "com.apple.configuration.managed") as? [String:Any?] {
if let skalierung = managedConf["skalierung"] as? Int {
return skalierung
}
}
Während die Abfrage über Swift sogar als Einzeiler geschrieben werden kann, ist es unter Delphi nicht ganz so einfach, weil es mehrere Möglichkeiten gibt und tatsächlich der Debugger einen sogar dabei auf die falsche Fährte locken kann. Es sind nicht unbedingt mehr Zeilen, allerdings muss man genau wissen, welche es sind. Dokumentationen zu diesem Thema sind leider meist sehr rar und die Beispiele, die man finden kann, oft nicht einfach in Delphi zu übersetzen. Selbst die tolle KI fantasiert gerne sehr viel Code zusammen, der am Ende nicht die gewünschten Ergebnisse liefert.
Aber der Reihe nach: Zuerst benötigen wir das NSUserDefaults-Objekt, welches wir mit folgender Zeile leicht erhalten:
nUserDefaults := TNSUserDefaults.Wrap(TNSUserDefaults.OCClass.standardUserDefaults);
wobei nUserDefaults als Varialbe vom Typ NSUserDefaults definiert ist.
Im nächsten Schritt erfolgt der Zugriff auf den virtuellen Schlüssel des Betriebssystems, indem die Einstellungen der MDM-Software abgelegt werden. Dafür holen wir uns das vorhandene Dictionary mit folgendem Befehl: nMDMDictionary := nUserDefaults.dictionaryForKey(StrToNSStr('com.apple.configuration.managed'));. Hierbei ist nMDMDictionary vom Typ NSDictionary.
Achtung: Es gibt auch den Zugriff objectForKey(), der ebenfalls ein Ergebnis liefert. Außerdem lässt sich im Debugger beobachten, dass dort auch die Struktur "hinterlegt" ist als Liste von Key-Value-Pairs. Dummerweise laufen Typumwandlungen an dieser Stelle gegen die Wand und zurück bleiben Zugriffsfehler und Programmabstürze. Bei dictionaryForKey() ist hingegen im Debugger nur ein Pointer zu einer Adresse sichtbar, doch damit können die weiteren Methoden anstandslos arbeiten.
Der nächste Zugriff ist die komplette Magie, um den gewünschten Wert zu lesen. Das Objekt besitzt die Methode valueForKey() und man erhält einen Pointer zurück. Wichtig hierbei ist, dass die lokale Variable nicht vom Typ Pointer angelegt wird! Es sollte stattdessen ein typisierter Pointer sein, wie er in der Zeiger-Arithmetik von Delphi vorkommen darf. Gesamt ist die Zeile also iValueP := nMDMDictionary.valueForKey(StrToNSStr('skalierung'));, wobei iValueP vom Typ ^NSNumber definiert ist.
(Natürlich kann an dieser Stelle auch NSString für Texte genutzt werden, aber Achtung: Bool-Werte sind ebenfalls in der Apple-Welt vom Typ NSNumber, denn diese besitzen auch die Eigenschaft boolValue!)
Danach lässt sich der Wert einfach über iValue := TNSNumber.Wrap(iValueP).integerValue; umwandeln.
Ob man die Werte einmalig lädt oder bei jedem Start, bleibt einem selbst überlassen. Es empfiehlt sich allerdings, je nach Aufbau der eigenen Anwendung, eine klare Struktur vorzugeben. Aus Erfahrung kann ich auch eine (optionale) Einstellung "version" als reine Ganzzahl empfehlen, die ein MDM-Verwalter im Zweifel hochzählen kann. Ist sie nicht vorhanden, ist der Standardwert schlicht "1", aber wenn sie vorhanden ist, kann dieser Wert lokal abgespeichert werden (z.B. in den normalen NSUserDefaults).
Der Vorteil liegt klar auf der Hand. Ist die Versionsnummer beim Start der App gegenüber der aktuell gespeicherten höher, kann für andere Schlüssel definiert sein, dass diese einmalig erneut gelesen und gesetzt werden. Das ist in diversen Situationen sinnvoll, sofern man den Verwaltern die Möglichkeit geben möchte, dass Werte, die vom Benutzer im Alltag angepasst werden dürfen, zu definierten Zeitpunkten trotzdem bei großen Änderungen zentral wieder verteilt werden können. Die Anwender können es danach anpassen, aber die Admins können sicher sein, einen funktionierenden Wert auf alle Geräte zu verteilen für die Anwender, die sich damit nicht auseinandersetzen.
Fazit: Die Unterstützung für MDM-Parameter ist durchaus vorteilhaft und bringt einem Pluspunkte ein. Auch ohne ein offizielles AppConfig-Schema, ist es wertvoll für Unternehmen und steigert die Atraktivität. Trotzdem sollte man überlegen, welche Einstellungen sinnvoll über eine zentrale Verwaltung sind und was auf den Geräten umgestellt werden darf. Auch wie hoch die Dynamik beim Einlesen ist entscheidet über Komplexität, Aufwand und Nutzen.