Bewährte Methoden für Android-Apps

Die in diesen Artikel vorgestellten bewährten Methoden dienen zur Verbesserung der Kompatibilität zwischen Citrix Endpoint Management und mobilen Apps für Android-Geräte.

MDX App SDK und Umschließen

Wenn Ihre App das MDX App SDK verwendet, müssen Sie sie mit der entsprechenden MDX Toolkit-Version umschließen. Ein Versionskonflikt zwischen den beiden Komponenten kann zu Betriebsfehlern führen.

Um dies zu verhindern, umschließen Sie die App als Premium- oder allgemeine App. Auf diese Weise können Sie eine umschlossene App bereitstellen. Der Kunde muss die App dann nicht selbst umschließen, wodurch ein Versionskonflikt beim MDX Toolkit vermieden wird. Einzelheiten über das Umschließen von Apps finden Sie unter Umschließen von mobilen Android-Apps.

Hauptthread nicht blockieren

Verwenden Sie keinen blockierenden Code beim Ausführen im Hauptthread. Dies ist eine Richtlinie von Google, die jedoch für Citrix Endpoint Management noch wichtiger ist. Einige Aktionen brauchen bei einer verwalteten App möglicherweise länger oder blockieren sogar das weitere Ausführen des Threads.

Blockierender Code kann u. a. folgende Elemente betreffen:

  • Datei- oder Datenbankvorgänge
  • Netzwerkvorgänge

Alle Lifecycle-Methoden, z. B. onCreate, werden auf dem Hauptthread ausgeführt.

Google bietet eine StrictMode-API zur Erkennung von blockierendem Code an. Weitere Informationen finden Sie in diesem Blogbeitrag: https://android-developers.blogspot.com/2010/12/new-gingerbread-api-strictmode.html

Robusten Code schreiben

Prüfen Sie insbesondere Rückgabewerte bzw. mögliche Ausnahmen von Framework-APIs. Diese bewährte Methode gilt allgemein bei der Programmierung, für verwaltete Apps ist sie jedoch besonders wichtig.

Verschiedene APIs, die normalerweise immer funktionieren, schlagen fehl, wenn die zugrunde liegende Funktionalität von Citrix Endpoint Management-Richtlinien blockiert wird. Als Beispiele können alle zuvor beschriebenen Funktionen gelten:

  • Netzwerk-APIs schlagen fehl, wenn kein Netzwerk verfügbar ist.
  • Sensor-APIs, z. B. GPS und Kamera, geben NULL-Werte zurück oder lösen eine Ausnahme aus.
  • Intents, die auf nicht verwaltete Apps abzielen, schlagen fehl.
  • Datei- und Datenbankzugriff kann bei Verwendung vom Hauptthread aus fehlschlagen. Weitere Informationen finden Sie unter “Sicherstellen der Datenverschlüsselungskompatibilität” und “Verschlüsselung und Benutzerentropie” weiter unten.

Fehler dürfen nicht zum Absturz der App führen, sondern müssen kontrolliert behandelt werden.

Einschränkungen für Hooks

MDX fügt Funktionalität in binäre Android-Apps durch Ändern des DEX-Codes in der APK ein. Es gelten mehrere Einschränkungen:

  • Citrix Endpoint Management verwaltet veraltete Framework-Klassen aus Android-SDK-Versionen vor 4.0 möglicherweise nicht. Vermeiden Sie diese veralteten Klassen.
  • Das Gros der Funktionalität wird in die Java-/Android-Framework-APIs eingefügt. Systemeigener (C/C++) Code wird in der Regel nicht verwaltet. Ausnahme bildet die Dateiverschlüsselung, die auch auf systemeigenen Code angewendet wird.
  • Systemeigener Code, der mithilfe von JNI auf Java-Funktionen zugreift, darf nur auf Code in der Benutzer-App abzielen. Sie dürfen JNI also nicht für den direkten Aufruf von Java- oder Android-Frameworkmethoden verwenden. Verwenden Sie das Proxy-Entwurfsmuster zum “Umschließen” der gewünschten Framework-Klasse in Ihrer eigenen Java-Klasse. Rufen Sie dann die Klasse über den systemeigenen Code auf.

Sicherstellen der Datenverschlüsselungskompatibilität

Eines der primären Features von MDX ist die transparente Verschlüsselung aller persistenten Daten. Sie brauchen Ihre App zur Nutzung dieses Features nicht zu ändern, es lässt sich sogar nicht direkt umgehen. Der Administrator kann die Verschlüsselung selektiv oder vollständig deaktivieren, die App kann das nicht.

Dies ist eines der wichtigeren Merkmale von MDX und erfordert die Kenntnis folgender Punkte:

  • Die Dateiverschlüsselung gilt für den gesamten Java- und systemeigenen Code, der in verwalteten Prozessen ausgeführt wird.

  • Einige Framework-APIs, z. B. Mediaplayer und Druckunterstützung, werden in separaten Betriebssystemprozessen ausgeführt. Bei Verwendung einer solchen API können Probleme auftreten.

    • Beispiel: Ihre App speichert eine Datei (verschlüsselt) auf einem Datenträger und übergibt einen Verweis auf die Datei an eine Medien-API. Die Medien-API versucht, die Datei zu lesen, kann dies aber nicht, da der Inhalt verschlüsselt ist. Es tritt ein Fehler auf oder die App stürzt sogar ab.
    • Beispiel: Sie erstellen ein Dateihandle (zum Starten einer verschlüsselten Datei) und übergeben es der Kamera-API. Der Kameraprozess schreibt direkt in die verschlüsselte Datei unverschlüsselte Daten. Wenn die App versucht, die Daten zu lesen, werden diese entschlüsselt und sind unlesbar.
  • Eine Möglichkeit zum Umgang mit separaten Prozessen besteht im Entschlüsseln von Dateien, bevor sie der entsprechenden API übergeben werden. Werden von der API Daten geschrieben, können Sie auch den Schreibvorgang abschließen lassen und die Daten dann verschlüsseln. Es sind einige Schritte erforderlich:

    1. Bestimmen Sie einen Bereich, der unverschlüsselt bleibt. Sie müssen dies für Ihren Kunden dokumentieren, denn ein Citrix Endpoint Management-Administrator muss eine Richtlinie für Ausnahmen von der Verschlüsselung erstellen.
    2. Zum Entschlüsseln kopieren Sie die Datei einfach aus dem normalen (verschlüsselten) Speicherort in den entschlüsselten Speicherort. Verwenden Sie hierfür einen Byte Copy-Vorgang, keinen File Move-Vorgang.
    3. Zum Verschlüsseln kehren Sie die Richtung um. Kopieren Sie die Datei aus dem unverschlüsselten in den verschlüsselten Speicherort.
    4. Löschen Sie die unverschlüsselte Datei, wenn sie nicht mehr gebraucht wird.
  • Die Speicherzuordnung wird für verschlüsselte Dateien nicht unterstützt. Wenn Sie eine API aufrufen, die eine Speicherzuordnung durchführt, tritt ein Fehler auf. Sie müssen eine Fehlerbehandlung vorsehen. Vermeiden Sie, falls möglich, sämtliche direkte oder indirekte Speicherzuordnung. Ein nennenswertes Beispiel der Verwendung der indirekten Speicherzuordnung ist die Drittanbieter-Bibliothek SqlCipher.

    Wenn Sie die Speicherzuordnung nicht vermeiden können, muss der Administrator eine Richtlinie zum Ausnehmen der betroffenen Dateien von der Verschlüsselung erstellen. Sie müssen diese Richtlinie für Ihren Kunden dokumentieren.

  • Verschlüsselung erzeugt spürbaren Mehraufwand. Optimieren Sie die Datei-E/A, um Leistungseinbußen zu verhindern. Es kann beispielsweise ein Cache auf App-Ebene implementiert werden, da wiederholt die gleichen Informationen gelesen und geschrieben werden.

  • Datenbanken sind lediglich Dateien und werden daher auch verschlüsselt. Es kann auch hier zu Leistungsproblemen kommen. Die Standardgröße des Datenbankcaches ist 2000 Seiten bzw. 8 MB. Wenn die Datenbank groß ist, empfiehlt sich ggf. eine Erhöhung dieses Werts.

    Der SQLite-WAL-Modus wird aufgrund der Einschränkung im Hinblick auf die Speicherzuordnung nicht unterstützt.

Verschlüsselung und Benutzerentropie

Eine Citrix Endpoint Management-Verschlüsselungsoption macht es erforderlich, dass Benutzer eine PIN eingeben, bevor der Verschlüsselungsschlüssel generiert werden kann. Diese Option wird als “Benutzerentropie” bezeichnet. Sie kann für Apps bestimmte Probleme verursachen.

Insbesondere ist vor Eingabe einer PIN kein Zugriff auf Dateien oder Datenbanken möglich. Entsprechende E/A-Vorgänge, die ausgeführt werden müssen, bevor das PIN-Eingabe-UI angezeigt werden kann, schlagen fehl. Es gibt einige Punkte zu beachten:

  • Datei- und Datenbankvorgänge müssen Hauptthread-extern bleiben. Das Lesen einer Datei aus der onCreate ()-Methode des App-Objekts schlägt grundsätzlich fehlt.
  • Hintergrundvorgänge, z. B. Dienste oder Inhaltsanbieter, werden u. U. auch dann ausgeführt, wenn keine App-Aktivität vorhanden ist. Solche Hintergrundkomponenten können keinen PIN-UI anzeigen und daher keinen Datei- oder Datenbankzugriff ausführen. Sobald in der App eine Aktivität ausgeführt wird, können Hintergrundvorgänge E/A-Vorgänge ausführen.

Es gibt mehrere Fehlermechanismen für ein Szenario, in dem der Schlüssel aufgrund von Benutzerentropie nicht verfügbar ist:

  • Greift der Hauptthread auf eine Datenbank zu, bevor die PIN verfügbar ist, wird der Abbruch der App erzwungen.
  • Greift ein anderer Thread auf eine Datenbank zu, bevor die PIN verfügbar ist, wird der Thread gesperrt, bis die PIN eingegeben wurde.
  • Ein Zugriff auf ein anderes Element als eine Datenbank, der gestartet wird, bevor die PIN verfügbar ist, schlägt fehl. Auf C-Ebene wird ein EACCES-Fehler zurückgegeben. In Java wird eine Ausnahme ausgelöst.

Um sicherzustellen, dass dieses Problem bei Ihrer App nicht auftritt, testen Sie diese mit aktivierter Benutzerentropie. Die Citrix Endpoint Management-Clienteigenschaft “Encrypt secrets using Passcode” fügt Benutzerentropie hinzu. Die Eigenschaft ist standardmäßig deaktiviert und kann über die Citrix Endpoint Management-Konsole unter Konfigurieren > Einstellungen > Mehr > Clienteigenschaften konfiguriert werden.

Netzwerk und Micro VPN

Mehrere Citrix Endpoint Management-Richtlinienoptionen stehen Administratoren für das Netzwerk zur Verfügung. Mit der Netzwerkzugriffsrichtlinie kann die Netzwerkaktivität einer App verhindert, zugelassen oder umgeleitet werden:

Wichtig:

Das MDX Toolkit Version 18.12.0 enthält neue Richtlinien, die ältere Richtlinien kombinieren oder ersetzen. Die Richtlinie “Netzwerkzugriff” kombiniert “Netzwerkzugriff”, “Bevorzugter VPN-Modus” und “VPN-Moduswechsel zulassen”. Die Richtlinie “Ausschlussliste” ersetzt “Split-Tunnelausschlussliste”. Die Richtlinie “Micro-VPN-Sitzung erforderlich” ersetzt “Onlinesitzung erforderlich”. Einzelheiten finden Sie unter Was ist neu in früheren Releases.

Die folgenden Optionen stehen zur Auswahl:

  • Vorherige Einstellungen verwenden: Standardmäßig werden die Werte aus früheren Richtlinien verwendet. Wenn Sie diese Option ändern, sollten Sie nicht auf Vorherige Einstellungen verwenden zurückkehren. Beachten Sie auch, dass Änderungen an den neuen Richtlinien erst wirksam werden, nachdem der Benutzer die App auf Version 18.12.0 oder später aktualisiert.
  • Blockiert: Netzwerk-APIs, die von Ihrer App verwendet werden, schlagen fehl. Ein solcher Fehler sollte gemäß der o. a. Richtlinie durch ein kontrolliertes Beenden der App behandelt werden.
  • Uneingeschränkt: Alle Netzwerkaufrufe gehen direkt und sind nicht getunnelt.
  • Tunnel - Vollständiges VPN: Der gesamte Datenverkehr der verwalteten App wird über den Citrix Gateway-Tunnel geleitet.

Einschränkung: Citrix Endpoint Management unterstützt Socket Server nicht. Wenn in der umschlossenen App ein Socket Server ausgeführt wird, wird der Netzwerk-Datenverkehr zum Socket Server nicht über Citrix Gateway getunnelt.

Unterstützung von Frameworks zum Entwickeln mobiler Apps

Bei einigen App-Frameworks bestehen Kompatibilitätsprobleme mit Citrix Endpoint Management:

  • Bei PhoneGap wird der Ortungsdienst nicht gesperrt.
  • SQLCipher funktioniert nicht mit Verschlüsselung, da es die Speicherzuordnung verwendet. Eine Lösung besteht darin, SQLCipher nicht zu verwenden. Eine zweite Lösung besteht darin, die Datenbankdatei über eine entsprechende Richtlinie von der Verschlüsselung auszunehmen. Ein Citrix Endpoint Management-Administrator muss die Richtlinie über die Citrix Endpoint Management-Konsole konfigurieren.

Tipps zum Debuggen

Beachten Sie beim Debuggen einer umschlossenen App die folgenden Tipps.

  • Prüfen Sie, ob das Problem auch bei einer nicht umschlossenen Version der App auftritt. Ist dies der Fall, verwenden Sie die üblichen Debugging-Methoden.
  • Deaktivieren Sie verschiedene Citrix Endpoint Management-Richtlinien.
    • Dies kann bei der Suche nach Kompatibilitätsproblemen helfen. Durch Deaktivieren einer Richtlinie erzwingt MDX nicht mehr die zugehörige Einschränkung, sodass Sie diese Features so testen können, als wäre die App nicht umschlossen.
    • Wird das Problem durch Deaktivieren einer Richtlinie behoben, kann die Ursache darin liegen, dass die App in den zugeordneten APIs keine Überprüfung auf Fehler durchführt.
  • Wenn eine unveränderte App nach einer erneuten Signierung nicht ausgeführt wird, führen Sie folgende Schritte durch:
    1. Extrahieren Sie den Inhalt der APK-Datei mit JAR:

      jar xvf {some.apk}

    2. Löschen Sie den Ordner “META-INF”:

      rm -rf META-INF

    3. Packen Sie den Inhalt in eine neue APK-Datei mit JAR:

      jar cvf {/tmp/new.apk} *

    4. Signieren Sie die neue APK-Datei mit JARSIGNER:

      jarsigner -keystore {some.keystore} -storepass {keystorepassword} -keypass {keypassword} {/tmp/new.apk} {keyalias}

    5. Wenn die App immer noch nicht ausgeführt wird, können Sie sie nicht mit einem anderen Zertifikat umschließen als das für die ursprüngliche APK-Version verwendete.

  • Wenn eine dekompilierte oder erneut kompilierte APK-Datei nicht ausgeführt wird, führen Sie folgende Schritte aus:
    1. Dekompilieren Sie sie und kompilieren Sie sie erneut mit APKTOOL:

      apktool d {some.apk} -o {some.directory}

      apktool b {some.directory} -o {new.apk}

    2. Signieren Sie die APK-Datei mit JARSIGNER (siehe oben).

    3. Wenn die App noch immer nicht ausgeführt werden, handelt es sich um einen Fehler im Drittanbieter-APKTOOL.

  • Wenn das Umschließen einer App nicht funktioniert, führen Sie folgende Schritte durch:
    1. Entfernen Sie das APKTOOL-Framework und umschließen Sie die App neu.
      • Mac/Linux: rm -rf ~/Library/apktool/framework
      • Windows: del /q /s C:\Users\{username}\apktool\framework
    2. Prüfen Sie, welches APKTOOL von dem Wrapper verwendet wird, mit dem Sie die Dekompilierung und Neukompilierung im vorherigen Schritt durchgeführt haben.
      • Handelt es sich um die gleiche APKTOOL-Version, liegt ein Fehler im Wrapper vor.
      • Handelt es sich um eine andere APKTOOL-Version, liegt möglicherweise ein Fehler in dem im MDX Toolkit integrierten APKTOOL vor.
        1. Extrahieren Sie den Inhalt der Datei ManagedAppUtility.jar.
        2. Überschreiben Sie ihn mit dem Inhalt der APKTOOL.jar-Datei, mit der Sie die App im vorhergehenden Schritt erfolgreich umschlossen haben.
        3. Packen Sie den Inhalt in eine neue ManagedAppUtility.jar.
        4. Umschließen Sie die App, um das integrierte APKTOOL als Fehlerursache zu bestätigen.
  • Führen Sie die umschlossene App aus und zeichnen Sie Protokolle auf.
    1. Prüfen Sie mit grep, was App-intern passiert.

      Zum Verfolgen der App-Aktivitäten: grep “MDX-Activity”

      Zum Verfolgen der MDX-Sperrung der App: grep “MDX-Locked”

      Zum Anzeigen beider Protokolle: egrep “MDX-Act MDX-Loc”
    2. Wird der Fehler “Anwendung reagiert nicht” gemeldet, zeichnen Sie mit ADB die ANR-Ablaufverfolgung auf.

  • Wenn ein Problem bei der Interaktion mit mehreren Apps (z. B. bei “Öffnen in”) auftritt, führen Sie folgende Schritte aus:
    1. Prüfen Sie, ob die Verschlüsselungsrichtlinien und Sicherheitsgruppeneinstellungen für alle Apps gleich sind.
    2. Versuchen Sie es mit einer anderen App. Es kann sich um einen Fehler in einer der getesteten Apps handeln.
    3. Zeichnen Sie Protokolle für alle beteiligten Apps auf. Mit Secure Hub lassen sich Protokolle bündeln und Protokolle von einzelnen Apps per E-Mail versenden. Wischen Sie auf der Seite “Eigene Apps” nach rechts, um den Supportbildschirm anzuzeigen. Tippen Sie dann unten auf die Schaltfläche “Support?”.

Neben den oben genannten Tools sind evtl. die folgenden hilfreich:

  • AAPT zum Sichern von Informationen über die App

    aapt dump badging {some.apk}

  • DUMPSYS-Befehl auf dem Gerät

    adb shell dumpsys 2>&1 | tee {dumpsys.out}

  • DEX2JAR für die Neukompilierung von Klassen in Pseudo-Java

    dex2jar {some.apk}

    Konvertieren von Klassen aus Dual-Dex-umschlossenen Apps:

    apktool d {some.apk} -o {some.dir}

    dex2jar {some.dir}/assets/secondary-1.dex

  • JD-GUI zum Anzeigen von Pseudo-Java-Code

  • BAKSMALI zum Dekompilieren von Klassen aus Dual-Dex-umschlossenen Apps:

    • Dekompilieren der umschlossenen APK:

      apktool d {some.apk} -o {some.dir}

    • Dekompilieren der App-Klassen, die nicht über den obigen Aufruf dekompiliert werden:

      baksmali {some.dir}/assets/secondary-1.dex -o {some.dir}/smali