Product Documentation

Bewährte Methoden für Android-Apps

Mar 16, 2018

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

Worx App SDK und Umschließung

Wenn Ihre App das Worx 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 in der MDX Toolkit-Dokumentation.

Hauptthread nicht blockieren

Bei Ausführung auf dem Hauptthread verwenden Sie keinen blockierenden Code. Dies ist eine Richtlinie von Google, die jedoch für XenMobile noch wichtiger ist. Einige Aktionen brauchen bei einer verwalteten App möglicherweise länger oder blockieren sogar die weitere Threadausführung.

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 Blog-Beitrag: http://android-developers.blogspot.com/2010/12/new-gingerbread-api-strictmode.html

Schreiben Sie robusten Code

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 XenMobile-Richtlinien blockiert wird. Als Beispiele können alle zuvor beschriebenen Funktionen gelten:

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:

  • XenMobile 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 XenMobile-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 XenMobile-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 XenMobile-Clienteigenschaft "Encrypt secrets using Passcode" fügt Benutzerentropie hinzu. Die Eigenschaft ist standardmäßig deaktiviert und kann über die XenMobile-Konsole unter Konfigurieren > Einstellungen > Mehr > Clienteigenschaften konfiguriert werden.

Netzwerk und Micro VPN

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

  • Standardmäßig ist das Netzwerk für Apps vollständig blockiert. Wenn die Netzwerkzugriffsrichtlinie auf Blockiert festgelegt ist, schlagen von der App verwendete Netzwerk-APIs fehl. Ein solcher Fehler sollte gemäß der o. a. Richtlinie durch ein kontrolliertes Beenden der App behandelt werden.
  • Wenn die Netzwerkzugriffrichtlinie auf Uneingeschränkt festgelegt ist, werden alle Netzwerkaufrufe direkt und nicht durch den Tunnel geroutet.
  • Wenn die Netzwerkzugriffrichtlinie auf Tunnel zum internen Netzwerk festgelegt ist, werden alle Netzwerkaufrufe über NetScaler Gateway geroutet. Das Tunneling unter dieser Richtlinie wird über die Richtlinie "Bevorzugter VPN-Modus" gesteuert.

Die Richtlinie "Bevorzugter VPN-Modus" bestimmt den Anfangsmodus für Verbindungen mit einem Tunnel zum internen Netzwerk:

  • Ist die Richtlinie "Bevorzugter VPN-Modus" auf Secure Browse festgelegt, wird die http/https-URL neu geschrieben. Mit "Secure Browse" ist nur ein Tunneling von http- und https-Datenverkehr möglich. Große Vorteile von Secure Browse sind Single Sign-On (SSO) für http- und https-Datenverkehr und die PKINIT-Authentifizierung. Unter Android ist die Einrichtung von Secure Browse mit geringem Mehraufwand verbunden, es bildet daher die bevorzugte Option für Webbrowsing-Vorgänge.
  • Wenn die Richtlinie "Bevorzugter VPN-Modus" auf Vollständiger VPN-Tunnel festgelegt ist, wird der gesamte Datenverkehr der verwalteten App über NetScaler Gateway getunnelt. Unter Android wird in diesem Modus eine geräteübergreifendes VPN ausgeführt, dessen Verwendung jedoch auf die verwalteten Apps eingeschränkt ist.

Einschränkung: XenMobile 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 den NetScaler Gateway-Tunnel geroutet.

Unterstützung von Frameworks zur Entwicklung mobiler Apps

Bei einigen App-Frameworks bestehen Kompatibilitätsprobleme mit XenMobile:

  • 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 XenMobile-Administrator muss die Richtlinie über die XenMobile-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 XenMobile-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