Anmerkung
Der Zugriff auf diese Seite erfordert eine Genehmigung. Du kannst versuchen, dich anzumelden oder die Verzeichnisse zu wechseln.
Der Zugriff auf diese Seite erfordert eine Genehmigung. Du kannst versuchen , die Verzeichnisse zu wechseln.
Abrufen von Diagnoseinformationen
Xamarin.Android gibt es mehrere Optionen zum Nachverfolgen verschiedener Fehler. Dazu gehören:
- Diagnoseausgabe von MSBuild
- Gerätebereitstellungsprotokolle
- Android-Debugprotokollausgabe
Diagnoseausgabe von MSBuild
Die MSBuild-Diagnose kann zusätzliche Informationen im Zusammenhang mit der Erstellung und Bereitstellung von Paketen enthalten.
So aktivieren Sie die Diagnoseausgabe von MSBuild in Visual Studio
- Klicken Sie auf Extras > Optionen...
- Wählen Sie in der linken Strukturansicht "Projekte und Lösungen > erstellen und ausführen" aus.
- Legen Sie im rechten Bereich das Dropdownelement „Ausführlichkeit der MSBuild-Buildausgabe“ auf „Diagnose“ fest.
- Klicken Sie auf OK.
- Bereinigen Sie Ihr Paket, und erstellen Sie es erneut.
- Die Diagnoseausgabe wird im Ausgabebereich angezeigt.
So aktivieren Sie die Diagnoseausgabe von MSBuild in Visual Studio für Mac/OS X
- Klicken Sie auf Visual Studio für Mac > Einstellungen...
- Wählen Sie in der linken Strukturansicht "Projekte erstellen" > aus.
- Legen Sie im rechten Bereich das Dropdownelement „Protokollausführlichkeit“ auf „Diagnose“ fest.
- Klicken Sie auf OK.
- Starten Sie Visual Studio für Mac neu.
- Bereinigen Sie Ihr Paket, und erstellen Sie es erneut.
- Die Diagnoseausgabe ist innerhalb des Fehlerpads > (Anzeigekreuzfehler>) sichtbar, indem Sie auf die Schaltfläche "Ausgabe erstellen" klicken.
Gerätebereitstellungsprotokolle
So aktivieren Sie die Protokollierung der Gerätebereitstellung in Visual Studio:
- Extras > Optionen...>
- Wählen Sie in der linken Strukturansicht Xamarin Android-Einstellungen aus > .
- Aktivieren Sie im rechten Bereich über das Kontrollkästchen [X] die Erweiterung für die Debugprotokollierung (speichert „monodroid.log“ auf dem Desktop).
- Protokollmeldungen werden in die Datei „monodroid.log“ auf dem Desktop geschrieben.
Von Visual Studio für Mac werden immer Gerätebereitstellungsprotokolle geschrieben. Das FInding ist etwas schwieriger; Eine AndroidUtils-Protokolldatei wird für jeden Tag + Uhrzeit erstellt, zu der eine Bereitstellung erfolgt, z. B . AndroidTools-2012-10-24_12-35-45.log.
- Unter Windows werden Protokolldateien in
%LOCALAPPDATA%\XamarinStudio-{VERSION}\Logsgeschrieben. - Unter OS X werden Protokolldateien in
$HOME/Library/Logs/XamarinStudio-{VERSION}geschrieben.
Android-Debugprotokollausgabe
Android schreibt viele Nachrichten in das Android-Debugprotokoll. Xamarin.Android verwendet Android-Systemeigenschaften, um die Generierung zusätzlicher Nachrichten im Android-Debugprotokoll zu steuern. Android-Systemeigenschaften können über den setprop-Befehl innerhalb der Android Debug Bridge (ADB) festgelegt werden:
adb shell setprop PROPERTY_NAME PROPERTY_VALUE
Systemeigenschaften werden während des Prozessstarts gelesen und müssen daher entweder vor dem Starten der Anwendung festgelegt werden, oder die Anwendung muss neu gestartet werden, nachdem die Systemeigenschaften geändert wurden.
Xamarin.Android-Systemeigenschaften
Xamarin.Android unterstützt die folgenden Systemeigenschaften:
debug.mono.debug: Wenn eine nicht leere Zeichenfolge ist, entspricht dies der
*mono-debug*.debug.mono.env: Eine pipetrennte ('|') Liste der Umgebungsvariablen, die während des Anwendungsstarts exportiert werden sollen, bevor Mono initialisiert wurde. Dies ermöglicht das Festlegen von Umgebungsvariablen, die die Mono-Protokollierung steuern.
Hinweis
Da der Wert "|"-getrennt ist, muss der Wert eine zusätzliche Quotierungsebene aufweisen, da der Befehl "adb shell" eine Reihe von Anführungszeichen entfernt.
Hinweis
Android-Systemeigenschaftswerte dürfen nicht länger als 92 Zeichen sein.
Beispiel:
adb shell setprop debug.mono.env "'MONO_LOG_LEVEL=info|MONO_LOG_MASK=asm'"debug.mono.log: Eine durch Trennzeichen getrennte Liste von Komponenten, die zusätzliche Nachrichten im Android-Debugprotokoll drucken sollen. Standardmäßig ist nichts festgelegt. Die Komponenten umfassen:
- alle: Alle Nachrichten drucken
- gc: Drucken von GC-bezogenen Nachrichten.
- gref: Drucken von (schwachen, globalen) Referenzzuweisungen und Deallocation-Nachrichten.
- lref: Drucken der lokalen Referenzzuweisung und Deallocation-Nachrichten.
Hinweis
Diese sind äußerst ausführlich. Aktivieren Sie diese Option nur, wenn es wirklich erforderlich ist.
debug.mono.trace: Ermöglicht das Festlegen der Mono-Trace-Einstellung
=PROPERTY_VALUE.
Löschen von bin und obj
Bei Xamarin.Android traten in der Vergangenheit u. a. folgende Probleme auf:
- Es tritt ein ungewöhnlicher Build- oder Laufzeitfehler auf.
- Sie führen
Clean-,Rebuild- oder manuelle Löschvorgänge fürbin- undobj-Verzeichnisse durch. - Das Problem wird behoben.
Wir haben uns intensiv mit der Lösung solcher Probleme beschäftigt, da sich diese negativ auf die Produktivität von Entwicklern auswirken.
Gehen Sie wie folgt vor, wenn ein solches Problem auftritt:
- Überlegen Sie: Was war die letzte Aktion, bevor Ihr Projekt in diesen Zustand gebracht wurde?
- Speichern Sie das aktuelle Buildprotokoll. Versuchen Sie erneut, einen Build zu initiieren, und zeichnen Sie ein Diagnosebuildprotokoll auf.
- Senden Sie einen Fehlerbericht.
Bevor Sie Ihre bin- und obj-Verzeichnisse löschen, zippen Sie sie, und speichern Sie sie zur späteren Diagnose, falls diese erforderlich ist. Sie müssen für Ihr Xamarin.Android-Anwendungsprojekt wahrscheinlich einen Clean-Vorgang durchführen, um mit der Arbeit fortfahren zu können.
Xamarin.Android cannot resolve System.ValueTuple (Auflösen von Systemwerttupel in Xamarin.Android nicht möglich.)
Dieser Fehler tritt bei einer Inkompatibilität mit Visual Studio auf.
Visual Studio 2017 Update 1 (Version 15.1 oder früher) ist nur mit System.ValueTuple NuGet 4.3.0 (oder früher) kompatibel.
Visual Studio 2017 Update 2 (Version 15.2 oder früher) ist nur mit System.ValueTuple NuGet 4.3.1 (oder früher) kompatibel.
Wählen Sie die Version von System.ValueTuple NuGet aus, die Ihrer Visual Studio 2017-Installation entspricht.
GC-Nachrichten
Die Nachrichten von GC-Komponenten können angezeigt werden, indem die debug.mono.log-Systemeigenschaft auf einen Wert festgelegt wird, der GC enthält.
GC-Nachrichten werden immer dann generiert, wenn die GC ausgeführt wird und Informationen dazu bereitgestellt werden, welche Workload die GC verarbeitet hat:
I/monodroid-gc(12331): GC cleanup summary: 81 objects tested - resurrecting 21.
Weitere GC-Informationen wie Zeitangaben können generiert werden, indem Sie die MONO_LOG_LEVEL-Umgebungsvariable auf debug festlegen.
adb shell setprop debug.mono.env MONO_LOG_LEVEL=debug
Dies führt zu (vielen) zusätzlichen Mono-Nachrichten, einschließlich der drei folgenden, die von Bedeutung sind:
D/Mono (15723): GC_BRIDGE num-objects 1 num_hash_entries 81226 sccs size 81223 init 0.00ms df1 285.36ms sort 38.56ms dfs2 50.04ms setup-cb 9.95ms free-data 106.54ms user-cb 20.12ms clenanup 0.05ms links 5523436/5523436/5523096/1 dfs passes 1104 6883/11046605
D/Mono (15723): GC_MINOR: (Nursery full) pause 2.01ms, total 287.45ms, bridge 225.60 promoted 0K major 325184K los 1816K
D/Mono ( 2073): GC_MAJOR: (user request) pause 2.17ms, total 2.47ms, bridge 28.77 major 576K/576K los 0K/16K
In der GC_BRIDGE-Nachricht gibt num-objects die Anzahl der Bridgeobjekte an, die für diesen Durchlauf berücksichtigt werden, und num_hash_entries gibt die Anzahl der Objekte an, die während dieses Aufrufs des Bridgecodes verarbeitet werden.
In den Nachrichten GC_MINOR und GC_MAJOR gibt total die Zeitspanne an, in der das Programm angehalten wird (es werden keine Threads ausgeführt), und bridge gibt die Zeitspanne an, die der Code für die Bridgeverarbeitung benötigt (bei der die Java-VM verarbeitet wird). Während der Bridgeverarbeitung wird das Programm nicht angehalten.
Im Allgemeinen gilt: Je höher der Wert von num_hash_entries ist, desto länger dauert die bridge-Sammlung und desto größer ist der Zeitaufwand für die Sammlung insgesamt (total).
Nachrichten zu globalen Verweisen
Zum Aktivieren der GREF-Protokollierung (Global Reference) muss die debug.mono.log-Systemeigenschaft gref enthalten, z. B.:
adb shell setprop debug.mono.log gref
Xamarin.Android verwendet globale Android-Verweise, um Zuordnungen zwischen Java-Instanzen und den zugeordneten verwalteten Instanzen bereitzustellen, da beim Aufrufen einer Java-Methode eine Java-Instanz für Java bereitgestellt werden muss.
Android-Emulatoren lassen nur 2.000 globale Verweise gleichzeitig zu. Die Grenze für Hardware liegt mit 52.000 globalen Verweisen deutlich höher. Der niedrige Grenzwert kann sich bei der Ausführung von Anwendungen auf dem Emulator als problematisch erweisen. Zu wissen, woher die Instanz stammt, kann deshalb sehr nützlich sein.
Hinweis
Die Anzahl globaler Verweise bezieht sich nur auf die internen in Xamarin.Android und berücksichtigt keine globalen Verweise, die von anderen in den Prozess geladenen nativen Bibliotheken stammen. Verwenden Sie Anzahl der globalen Verweise als Richtwert.
I/monodroid-gref(12405): +g+ grefc 108 gwrefc 0 obj-handle 0x40517468/L -> new-handle 0x40517468/L from at Java.Lang.Object.RegisterInstance(IJavaObject instance, IntPtr value, JniHandleOwnership transfer)
I/monodroid-gref(12405): at Java.Lang.Object.SetHandle(IntPtr value, JniHandleOwnership transfer)
I/monodroid-gref(12405): at Java.Lang.Object..ctor(IntPtr handle, JniHandleOwnership transfer)
I/monodroid-gref(12405): at Java.Lang.Thread+RunnableImplementor..ctor(System.Action handler, Boolean removable)
I/monodroid-gref(12405): at Java.Lang.Thread+RunnableImplementor..ctor(System.Action handler)
I/monodroid-gref(12405): at Android.App.Activity.RunOnUiThread(System.Action action)
I/monodroid-gref(12405): at Mono.Samples.Hello.HelloActivity.UseLotsOfMemory(Android.Widget.TextView textview)
I/monodroid-gref(12405): at Mono.Samples.Hello.HelloActivity.<OnCreate>m__3(System.Object o)
I/monodroid-gref(12405): handle 0x40517468; key_handle 0x40517468: Java Type: `mono/java/lang/RunnableImplementor`; MCW type: `Java.Lang.Thread+RunnableImplementor`
I/monodroid-gref(12405): Disposing handle 0x40517468
I/monodroid-gref(12405): -g- grefc 107 gwrefc 0 handle 0x40517468/L from at Java.Lang.Object.Dispose(System.Object instance, IntPtr handle, IntPtr key_handle, JObjectRefType handle_type)
I/monodroid-gref(12405): at Java.Lang.Object.Dispose()
I/monodroid-gref(12405): at Java.Lang.Thread+RunnableImplementor.Run()
I/monodroid-gref(12405): at Java.Lang.IRunnableInvoker.n_Run(IntPtr jnienv, IntPtr native__this)
I/monodroid-gref(12405): at System.Object.c200fe6f-ac33-441b-a3a0-47659e3f6750(IntPtr , IntPtr )
I/monodroid-gref(27679): +w+ grefc 1916 gwrefc 296 obj-handle 0x406b2b98/G -> new-handle 0xde68f4bf/W from take_weak_global_ref_jni
I/monodroid-gref(27679): -w- grefc 1915 gwrefc 294 handle 0xde691aaf/W from take_global_ref_jni
Es gibt vier Nachrichten, die von Bedeutung sind:
- Erstellte globale Verweise: Die Zeilen beginnen mit +g+ und stellen eine Stapelüberwachung für den erstellten Codepfad bereit.
- Gelöschte globale Verweise: Die Zeilen beginnen mit -g- und stellen möglicherweise eine Stapelüberwachung für den erstellten Codepfad zur Freigabe des globalen Verweises bereit. Wenn bei der GC ein globaler Verweis gelöscht wird, wird keine Stapelüberwachung bereitgestellt.
- Erstellte schwache globale Verweise: Die Zeilen beginnen mit +w+.
- Gelöschte schwache globale Verweise: Die Zeilen beginnen mit -w-.
In allen Nachrichten gibt der grefc-Wert die Anzahl der von Xamarin.Android erstellten globalen Verweise an, und der grefwc-Wert steht für die Anzahl der schwachen globalen Verweise, die Xamarin.Android erstellt hat. Der handle- oder obj-handle-Wert ist der Wert des JNI-Handles, und das Zeichen nach „/“ weist auf den Typ des Handlewerts hin: /L für lokale Verweise, /G für globale Verweise und /W für schwache globale Verweise.
Im Rahmen des GC-Prozesses werden globale Verweise (+g+) in schwache globale Verweise konvertiert (was zu „+w+“- and „-g-“-Verweisen führt), und eine Java-seitige GC wird gestartet. Anschließend wird der schwache globale Verweis überprüft, um festzustellen, ob er in der Sammlung miteinbezogen wurde. Wenn dieser immer noch aktiv ist, wird ein neuer globaler Verweis für den schwachen Verweis (+ g +,-w-) erstellt. Andernfalls wird der schwache Verweis gelöscht (-w).
Java instance is created and wrapped by a MCW (Java-Instanz wird von einem MCW erstellt und umschlossen.)
I/monodroid-gref(27679): +g+ grefc 2211 gwrefc 0 obj-handle 0x4066df10/L -> new-handle 0x4066df10/L from ...
I/monodroid-gref(27679): handle 0x4066df10; key_handle 0x4066df10: Java Type: `android/graphics/drawable/TransitionDrawable`; MCW type: `Android.Graphics.Drawables.TransitionDrawable`
A GC is being performed... (Eine GC wird ausgeführt...)
I/monodroid-gref(27679): +w+ grefc 1953 gwrefc 259 obj-handle 0x4066df10/G -> new-handle 0xde68f95f/W from take_weak_global_ref_jni
I/monodroid-gref(27679): -g- grefc 1952 gwrefc 259 handle 0x4066df10/G from take_weak_global_ref_jni
Object is still alive, as handle != null (Objekt ist noch aktiv, da Ziehpunkt = NULL.)
wref turned back into a gref (Schwacher Verweis wieder in globalen Verweis umgewandelt.)
I/monodroid-gref(27679): *try_take_global obj=0x4976f080 -> wref=0xde68f95f handle=0x4066df10
I/monodroid-gref(27679): +g+ grefc 1930 gwrefc 39 obj-handle 0xde68f95f/W -> new-handle 0x4066df10/G from take_global_ref_jni
I/monodroid-gref(27679): -w- grefc 1930 gwrefc 38 handle 0xde68f95f/W from take_global_ref_jni
Object is dead, as handle == null (Objekt ist inaktiv, da Ziehpunkt = NULL.)
wref is freed, no new gref created (Schwacher Verweis wurde freigegeben, es wurde kein neuer globaler Verweis erstellt.)
I/monodroid-gref(27679): *try_take_global obj=0x4976f080 -> wref=0xde68f95f handle=0x0
I/monodroid-gref(27679): -w- grefc 1914 gwrefc 296 handle 0xde68f95f/W from take_global_ref_jni
Hier gibt es einen problematischen Aspekt zu berücksichtigen: Auf Zielen, auf denen eine ältere Android-Version als 4.0 ausgeführt wird, ist der Wert des globalen Verweises mit der Adresse des Java-Objekts im Arbeitsspeicher der Android-Runtime identisch. (Das heißt, die GC ist ein nicht bewegender, konservativer, Sammelsammler und gibt direkte Verweise auf diese Objekte aus.) Daher hat der resultierende Gref nach einem +g+, +w+, -g-, -w-Sequenz denselben Wert wie der ursprüngliche Grefwert. Dies erleichtert das Durchsuchen von Protokollen.
Android 4.0 verfügt jedoch über einen beweglichen Collector und übergibt keine direkten Verweise auf Android Runtimeobjekte für die VM mehr. Folglich ist der Wert des globalen Verweises nach einer„+g+“-, „+w+“-, „-g“-, „+g+“-, „-w-“-Sequenz anders. Wenn das Objekt mehrere GCs überdauert, gibt es mehrere Werte des globalen Verweises, wodurch schwieriger festzustellen ist, woher die Zuweisung der Instanz tatsächlich stammt.
Programmgesteuerte Abfragen
Durch Abfragen des JniRuntime-Objekts können Sie sowohl die GREF- als auch die WREF-Anzahl abfragen.
Java.Interop.JniRuntime.CurrentRuntime.GlobalReferenceCount –Anzahl der globalen Verweise
Java.Interop.JniRuntime.CurrentRuntime.WeakGlobalReferenceCount – Anzahl der schwachen globalen Verweise
Android-Debugprotokolle
Die Android-Debugprotokolle können zusätzlichen Kontext in Bezug auf auftretende Laufzeitfehler bereitstellen.
Floating-Point performance is terrible! (Gleitkommaleistung ist mangelhaft.)
Alternativ: „My app runs 10x faster with the Debug build than with the Release build!“ (App wird mit dem Debugbuild zehnmal schneller ausgeführt als mit dem Releasebuild!)
Xamarin.Android unterstützt mehrere Geräte-ABIs: armeabi, armeabi-v7a und x86. Geräte-ABIs können auf der Registerkarte > "Project Properties > Application" unterstützte Architekturen angegeben werden.
Bei Debugbuilds wird ein Android-Paket verwendet, das alle ABIs bereitstellt, wodurch die schnellste ABI für das Zielgerät verwendet wird.
Releasebuilds enthalten nur die auf der Registerkarte "Projekteigenschaften" ausgewählten ABIs. Mehrere können ausgewählt werden.
armeabi ist die Standard-ABI und bietet die umfassendste Geräteunterstützung. armeabi bietet jedoch keine Unterstützung für u. a. mehrere CPU-Geräte und Gleitkommahardware. Folglich sind Apps, die die armeabi-Releaseruntime verwenden, an einen einzelnen Kern gebunden und verwenden eine soft-float-Implementierung. Beides kann zu einer deutlich langsameren Leistung Ihrer App beitragen.
Wenn Ihre App eine angemessene Gleitkommaleistung (z. B. für Spiele) erfordert, sollten Sie die ABI armeabi-v7a aktivieren. Sie sollten in diesem Fall nur die armeabi-v7a-Runtime unterstützen. Das bedeutet jedoch, dass Ihre App auf älteren Geräten, die nur armeabi unterstützen, nicht ausgeführt werden kann.
Android SDK wurde nicht gefunden
In Google sind zwei Downloads für das Android SDK für Windows verfügbar. Wenn Sie das Installationsprogramm (EXE-Datei) auswählen, werden Registrierungsschlüssel geschrieben, die Xamarin.Android angeben, wo es installiert wurde. Wenn Sie die ZIP-Datei auswählen und sie selbst entpacken, weiß Xamarin.Android nicht, wo nach dem SDK gesucht werden soll. Sie können Xamarin.Android mitteilen, wo sich das SDK in Visual Studio befindet, indem Sie zu tools Options > > Xamarin > Android Settings wechseln:
IDE zeigt Zielgerät nicht an
Es kann vorkommen, dass das Gerät, auf dem Sie Ihre Anwendung bereitstellen möchten, im Dialogfeld „Gerät auswählen“ nicht aufgeführt wird. Das kann der Fall sein, wenn die Android-Debugbrücke nicht ausgeführt wird.
Navigieren Sie zum ADB-Programm, und gehen Sie dann wie folgt vor, um dieses Problem zu diagnostizieren:
adb devices
Wenn Ihr Gerät nicht vorhanden ist, starten Sie den Server für die Android-Debugbrücke neu, um nach dem Gerät zu suchen:
adb kill-server
adb start-server
Die HTC-Synchronisierungssoftware verhindert ggf. das ordnungsgemäße Ausführen von adb start-server. Wenn der Befehl adb start-server nicht ausgibt, von welchem Port aus der Server gestartet wird, beenden Sie die HTC-Synchronisierungssoftware, und versuchen Sie, den ADB-Server neu zu starten.
The specified task executable "keytool" could not be run (Die angegebene ausführbare Datei „keytool“ der Aufgabe konnte nicht ausgeführt werden.).
Das bedeutet, dass der angegebene Pfad nicht das Verzeichnis enthält, in dem sich das Java SDK-Verzeichnis „bin“ befindet. Überprüfen Sie, ob Sie diese Schritte im Handbuch Installation befolgt haben.
monodroid.exe or aresgen.exe exited with code 1 („monodroid.exe“ oder „aresgen.exe“ wurde mit dem Code 1 beendet.)
Um dieses Problem zu debuggen, wechseln Sie zu Visual Studio, und ändern Sie die MSBuild-Ausführlichkeitsebene, um dies zu tun, wählen Sie folgendes aus: Tools > Options > Project and Solutions > Build and Run > MSBuild Project Build Output Verbosity , and set this value to Normal.
Initiieren Sie den Build erneut, und überprüfen Sie den Ausgabebereich von Visual Studio, in dem der vollständige Fehler angezeigt wird.
There is not enough storage space on the device to deploy the package (Auf dem Gerät ist nicht genügend Speicherplatz für die Bereitstellung des Pakets vorhanden.)
Dieser Fehler tritt auf, wenn Sie den Emulator nicht über Visual Studio starten. Wenn Sie den Emulator außerhalb von Visual Studio starten, müssen Sie z. B. die -partition-size 512-Optionen übergeben.
emulator -partition-size 512 -avd MonoDroid
Stellen Sie sicher, dass Sie den richtigen Simulatornamen, d. h. den Namen, den Sie beim Konfigurieren des Simulators angegeben haben, verwenden.
INSTALL_FAILED_INVALID_APK beim Installieren eines Pakets
Android-Paketnamen müssen einen Punkt („.“) enthalten. Fügen Sie dem Paketnamen einen Punkt hinzu.
- In Visual Studio:
- Klicken Sie mit der rechten Maustaste auf Die Projekteigenschaften >
- Klicken Sie links auf die Registerkarte „Android-Manifest“.
- Aktualisieren Sie das Feld mit dem Paketnamen.
- Wenn die Meldung "Es wurde keine AndroidManifest.xml gefunden. Klicken Sie hier, um einen hinzuzufügen.", klicken Sie auf den Link, und aktualisieren Sie dann das Feld "Paketname".
- Innerhalb Visual Studio für Mac:
- Klicken Sie mit der rechten Maustaste auf die Projektoptionen > .
- Navigieren Sie zum Abschnitt „Build > Android Application“ (Erstellen > Android-Anwendung).
- Fügen Sie dem Paketnamen einen Punkt („.“) hinzu.
INSTALL_FAILED_MISSING_SHARED_LIBRARY bei der Installation eines Pakets
„Freigegebene Bibliothek“ bezieht sich in diesem Kontext nicht auf eine native freigegebene Bibliotheksdatei (libfoo.so), sondern bezeichnet eine Bibliothek, die separat auf dem Zielgerät installiert werden muss, z. B. Google Maps.
Das Android-Paket gibt an, welche freigegebenen Bibliotheken für das <uses-library/>-Element erforderlich sind. Wenn auf dem Zielgerät keine erforderliche Bibliothek vorhanden ist (z. B. "true", d. h. //uses-library/@android:required "true"), schlägt die Paketinstallation mit INSTALL_FAILED_MISSING_SHARED_LIBRARY fehl.
Um zu ermitteln, welche freigegebenen Bibliotheken erforderlich sind, zeigen Sie die generierteAndroidManifest.xml Datei an (z. B. obj\Debug\android\AndroidManifest.xml), und suchen Sie nach den <uses-library/> Elementen. <uses-library/>Elemente können manuell in der Datei "Properties\AndroidManifest.xml" ihres Projekts und über das benutzerdefinierte Attribut "UsesLibraryAttribute" hinzugefügt werden.
Wenn Sie z. B. einen Assemblyverweis auf Mono.Android.GoogleMaps.dll hinzufügen, wird der freigegebenen Google Maps-Bibliothek implizit eine <uses-library/> hinzugefügt.
INSTALL_FAILED_UPDATE_INCOMPATIBLE bei der Installation eines Pakets
Für Android-Pakete gelten drei Anforderungen:
- Sie müssen einen Punkt „.“ enthalten (siehe vorheriger Eintrag).
- Der Paketname muss eine eindeutige Zeichenfolge aufweisen (daher die Reverse-Benennungskonvention mit TLD für Android-App-Namen, z. B. com.android.chrome für die Chrome-App).
- Beim Aktualisieren von Paketen muss das Paket denselben Signaturschlüssel aufweisen.
Stellen Sie sich dazu das folgende Szenario vor:
- Sie erstellen eine App und stellen diese als Debugging-App bereit.
- Sie ändern den Signaturschlüssel, um ihn als Release-App zu verwenden (oder weil Sie den standardmäßig verwendeten Signaturschlüssel zum Debuggen nicht verwenden möchten).
- Sie installieren Ihre App, ohne sie zuerst zu entfernen, z. B. Debuggen ohne Debuggen > in Visual Studio
In diesem Fall schlägt die Paketinstallation mit einem INSTALL_FAILED_UPDATE_INCOMPATIBLE Fehler fehl, da sich der Paketname nicht geändert hat, während der Signaturschlüssel ausgeführt wurde. Das Android-Debugprotokoll enthält auch eine Meldung ähnlich der folgenden:
E/PackageManager( 146): Package [PackageName] signatures do not match the previously installed version; ignoring!
Entfernen Sie die Anwendung vollständig von Ihrem Gerät, bevor Sie sie erneut installieren, um diesen Fehler zu beheben.
INSTALL_FAILED_UID_CHANGED beim Installieren eines Pakets
Wenn ein Android-Paket installiert wird, wird ihm eine Benutzer-ID (UID) zugewiesen.
In manchen Fällen schlägt die Installation über eine bereits vorhandene Anwendung aus derzeit unbekannten Gründen fehl (INSTALL_FAILED_UID_CHANGED):
ERROR [2015-03-23 11:19:01Z]: ANDROID: Deployment failed
Mono.AndroidTools.InstallFailedException: Failure [INSTALL_FAILED_UID_CHANGED]
at Mono.AndroidTools.Internal.AdbOutputParsing.CheckInstallSuccess(String output, String packageName)
at Mono.AndroidTools.AndroidDevice.<>c__DisplayClass2c.<InstallPackage>b__2b(Task`1 t)
at System.Threading.Tasks.ContinuationTaskFromResultTask`1.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
Sie können dieses Problem umgehen, indem Sie das Android-Paket vollständig deinstallieren und die App entweder über die GUI des Android-Ziels oder mithilfe der adb installieren:
$ adb uninstall @PACKAGE_NAME@
Verwenden sie nicht adb uninstall -k, da dadurch die Anwendungsdaten und damit die in Konflikt stehende UID auf dem Zielgerät beibehalten werden.
Release apps fail to launch on device (Auf dem Gerät können keine Release-Apps gestartet werden.)
Wenn die Ausgabe des Android-Debugprotokolls eine Meldung ähnlich der folgenden enthält,
D/AndroidRuntime( 1710): Shutting down VM
W/dalvikvm( 1710): threadid=1: thread exiting with uncaught exception (group=0xb412f180)
E/AndroidRuntime( 1710): FATAL EXCEPTION: main
E/AndroidRuntime( 1710): java.lang.UnsatisfiedLinkError: Couldn't load monodroid: findLibrary returned null
E/AndroidRuntime( 1710): at java.lang.Runtime.loadLibrary(Runtime.java:365)
gibt es dafür zwei mögliche Ursachen:
Die APK-Datei bietet keine ABI, die das Zielgerät unterstützt. Die APK-Datei enthält z. B. nur armeabi-v7a-Binärdateien, und das Zielgerät unterstützt nur armeabi.
Ein Android-Fehler. Deinstallieren Sie in diesem Fall die App, und installieren Sie sie erneut.
Bearbeiten Sie im ersten Fall die Projektoptionen/-eigenschaften, und fügen Sie der ABI-Liste Unterstützung für die erforderliche ABI hinzu. Sie können ermitteln, welche ABI Sie hinzufügen müssen, indem Sie den folgenden adb-Befehl für das Zielgerät ausführen:
adb shell getprop ro.product.cpu.abi
adb shell getprop ro.product.cpu.abi2
Die Ausgabe enthält die primären (und optional die sekundären) ABIs.
$ adb shell getprop | grep ro.product.cpu
[ro.product.cpu.abi2]: [armeabi]
[ro.product.cpu.abi]: [armeabi-v7a]
Die OutPath-Eigenschaft ist für das Projekt "MyApp.csproj" nicht festgelegt.
Dies bedeutet, dass Sie über einen HP-Computer verfügen und die Umgebungsvariable "Platform" auf etwas wie MCD oder HPD festgelegt wurde. Dies steht in Konflikt mit der MSBuild Platform-Eigenschaft, die in der Regel auf "Any CPU" oder "x86" festgelegt ist. Entfernen Sie diese Umgebungsvariable von Ihrem Computer, um MSBuild ausführen zu können. Wählen Sie hierzu folgende Optionen aus:
- > Systemsteuerung Erweiterten > Umgebungsvariablen des Systems >
Starten Sie Visual Studio neu, oder führen Sie Visual Studio für Mac erneut aus. Sie müssten jetzt mit Ihrer Arbeit fortfahren können.
java.lang.ClassCastException: mono.android.runtime.JavaObject cannot be cast to... (java.lang.ClassCastException: mono.android.runtime.JavaObject kann nicht umgewandelt werden in...)
In Xamarin.Android 4.x werden geschachtelte, generische Typen nicht richtig gemarshallt. Betrachten Sie beispielsweise den folgenden C#-Code mit SimpleExpandableListAdapter:
// BAD CODE; DO NOT USE
var groupData = new List<IDictionary<string, object>> () {
new Dictionary<string, object> {
{ "NAME", "Group 1" },
{ "IS_EVEN", "This group is odd" },
},
};
var childData = new List<IList<IDictionary<string, object>>> () {
new List<IDictionary<string, object>> {
new Dictionary<string, object> {
{ "NAME", "Child 1" },
{ "IS_EVEN", "This group is odd" },
},
},
};
mAdapter = new SimpleExpandableListAdapter (
this,
groupData,
Android.Resource.Layout.SimpleExpandableListItem1,
new string[] { "NAME", "IS_EVEN" },
new int[] { Android.Resource.Id.Text1, Android.Resource.Id.Text2 },
childData,
Android.Resource.Layout.SimpleExpandableListItem2,
new string[] { "NAME", "IS_EVEN" },
new int[] { Android.Resource.Id.Text1, Android.Resource.Id.Text2 }
);
Das Problem besteht darin, dass in Xamarin.Android geschachtelte, generische Typen nicht korrekt gemarshallt werden. List<IDictionary<string, object>> wird an eine java.lang.ArrayList gemarshallt, die ArrayList enthält jedoch mono.android.runtime.JavaObject-Instanzen (die auf die Dictionary<string, object>-Instanzen verweisen), weshalb java.util.Map nicht implementiert wird. Dies führt zu folgender Ausnahme:
E/AndroidRuntime( 2991): FATAL EXCEPTION: main
E/AndroidRuntime( 2991): java.lang.ClassCastException: mono.android.runtime.JavaObject cannot be cast to java.util.Map
E/AndroidRuntime( 2991): at android.widget.SimpleExpandableListAdapter.getGroupView(SimpleExpandableListAdapter.java:278)
E/AndroidRuntime( 2991): at android.widget.ExpandableListConnector.getView(ExpandableListConnector.java:446)
E/AndroidRuntime( 2991): at android.widget.AbsListView.obtainView(AbsListView.java:2271)
E/AndroidRuntime( 2991): at android.widget.ListView.makeAndAddView(ListView.java:1769)
E/AndroidRuntime( 2991): at android.widget.ListView.fillDown(ListView.java:672)
E/AndroidRuntime( 2991): at android.widget.ListView.fillFromTop(ListView.java:733)
E/AndroidRuntime( 2991): at android.widget.ListView.layoutChildren(ListView.java:1622)
Die Problemumgehung besteht darin, die bereitgestellten Java-Auflistungstypen anstelle der System.Collections.Generic Typen für die "inneren" Typen zu verwenden. Dies führt beim Marshalling der Instanzen zu entsprechenden Java-Typen. (Der folgende Code ist komplizierter als erforderlich, um die Lebensdauer von Gref zu reduzieren. Es kann vereinfacht werden, den ursprünglichen Code zu ändern, und s/List/JavaList/g s/Dictionary/JavaDictionary/g wenn gref lifetimes keine Sorge sind.)
// insert good code here
using (var groupData = new JavaList<IDictionary<string, object>> ()) {
using (var groupEntry = new JavaDictionary<string, object> ()) {
groupEntry.Add ("NAME", "Group 1");
groupEntry.Add ("IS_EVEN", "This group is odd");
groupData.Add (groupEntry);
}
using (var childData = new JavaList<IList<IDictionary<string, object>>> ()) {
using (var childEntry = new JavaList<IDictionary<string, object>> ())
using (var childEntryDict = new JavaDictionary<string, object> ()) {
childEntryDict.Add ("NAME", "Child 1");
childEntryDict.Add ("IS_EVEN", "This child is odd.");
childEntry.Add (childEntryDict);
childData.Add (childEntry);
}
mAdapter = new SimpleExpandableListAdapter (
this,
groupData,
Android.Resource.Layout.SimpleExpandableListItem1,
new string[] { "NAME", "IS_EVEN" },
new int[] { Android.Resource.Id.Text1, Android.Resource.Id.Text2 },
childData,
Android.Resource.Layout.SimpleExpandableListItem2,
new string[] { "NAME", "IS_EVEN" },
new int[] { Android.Resource.Id.Text1, Android.Resource.Id.Text2 }
);
}
}
Unerwartete NullReferenceExceptions
Gelegentlich erwähnt das Android-Debugprotokoll NullReferenceExceptions, die "nicht passieren" können, oder von Mono für Android-Laufzeitcode kurz vor dem Sterben der App stammen:
E/mono(15202): Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object
E/mono(15202): at Java.Lang.Object.GetObject (IntPtr handle, System.Type type, Boolean owned)
E/mono(15202): at Java.Lang.Object._GetObject[IOnTouchListener] (IntPtr handle, Boolean owned)
E/mono(15202): at Java.Lang.Object.GetObject[IOnTouchListener] (IntPtr handle, Boolean owned)
E/mono(15202): at Android.Views.View+IOnTouchListenerAdapter.n_OnTouch_Landroid_view_View_Landroid_view_MotionEvent_(IntPtr jnienv, IntPtr native__this, IntPtr native_v, IntPtr native_e)
E/mono(15202): at (wrapper dynamic-method) object:b039cbb0-15e9-4f47-87ce-442060701362 (intptr,intptr,intptr,intptr)
or
E/mono ( 4176): Unhandled Exception:
E/mono ( 4176): System.NullReferenceException: Object reference not set to an instance of an object
E/mono ( 4176): at Android.Runtime.JNIEnv.NewString (string)
E/mono ( 4176): at Android.Util.Log.Info (string,string)
Dies kann passieren, wenn sich die Android-Laufzeit entscheidet, den Prozess abzubrechen, was aus einer beliebigen Anzahl von Gründen geschehen kann, einschließlich der Überschreitung des GREF-Grenzwerts des Ziels oder das Ausführen eines "Falschen" mit JNI.
Sie können ermitteln, ob dies der Fall ist, indem Sie überprüfen, ob das Android-Debugprotokoll eine Meldung für Ihren Prozess enthält, die folgender ähnelt:
E/dalvikvm( 123): VM aborting
Abbruch aufgrund der Auslastung von globalen Verweisen
Die JNI-Ebene der Android Runtime unterstützt nur eine begrenzte Anzahl von JNI-Objektverweisen, die zu einem bestimmten Zeitpunkt gültig sind. Wenn dieser Grenzwert überschritten wird, tritt ein Fehler auf.
Der Grenzwert für GREF (globale Verweise) liegt bei 2.000 Verweisen im Emulator und ca. 52.000 Verweisen für Hardware.
Wenn im Android-Debugprotokoll Meldungen wie die folgende angezeigt werden, ist das ein Hinweis darauf, dass Sie gerade dabei sind, zu viele globale Verweise zu erstellen:
D/dalvikvm( 602): GREF has increased to 1801
Wenn Sie den Grenzwert für globale Verweise erreichen, wird eine Meldung wie die folgende ausgegeben:
D/dalvikvm( 602): GREF has increased to 2001
W/dalvikvm( 602): Last 10 entries in JNI global reference table:
W/dalvikvm( 602): 1991: 0x4057eff8 cls=Landroid/graphics/Point; (20 bytes)
W/dalvikvm( 602): 1992: 0x4057f010 cls=Landroid/graphics/Point; (28 bytes)
W/dalvikvm( 602): 1993: 0x40698e70 cls=Landroid/graphics/Point; (20 bytes)
W/dalvikvm( 602): 1994: 0x40698e88 cls=Landroid/graphics/Point; (20 bytes)
W/dalvikvm( 602): 1995: 0x40698ea0 cls=Landroid/graphics/Point; (28 bytes)
W/dalvikvm( 602): 1996: 0x406981f0 cls=Landroid/graphics/Point; (20 bytes)
W/dalvikvm( 602): 1997: 0x40698208 cls=Landroid/graphics/Point; (20 bytes)
W/dalvikvm( 602): 1998: 0x40698220 cls=Landroid/graphics/Point; (28 bytes)
W/dalvikvm( 602): 1999: 0x406956a8 cls=Landroid/graphics/Point; (20 bytes)
W/dalvikvm( 602): 2000: 0x406956c0 cls=Landroid/graphics/Point; (20 bytes)
W/dalvikvm( 602): JNI global reference table summary (2001 entries):
W/dalvikvm( 602): 51 of Ljava/lang/Class; 164B (41 unique)
W/dalvikvm( 602): 46 of Ljava/lang/Class; 188B (17 unique)
W/dalvikvm( 602): 6 of Ljava/lang/Class; 212B (6 unique)
W/dalvikvm( 602): 11 of Ljava/lang/Class; 236B (7 unique)
W/dalvikvm( 602): 3 of Ljava/lang/Class; 260B (3 unique)
W/dalvikvm( 602): 4 of Ljava/lang/Class; 284B (2 unique)
W/dalvikvm( 602): 8 of Ljava/lang/Class; 308B (6 unique)
W/dalvikvm( 602): 1 of Ljava/lang/Class; 316B
W/dalvikvm( 602): 4 of Ljava/lang/Class; 332B (3 unique)
W/dalvikvm( 602): 1 of Ljava/lang/Class; 356B
W/dalvikvm( 602): 2 of Ljava/lang/Class; 380B (1 unique)
W/dalvikvm( 602): 1 of Ljava/lang/Class; 428B
W/dalvikvm( 602): 1 of Ljava/lang/Class; 452B
W/dalvikvm( 602): 1 of Ljava/lang/Class; 476B
W/dalvikvm( 602): 2 of Ljava/lang/Class; 500B (1 unique)
W/dalvikvm( 602): 1 of Ljava/lang/Class; 548B
W/dalvikvm( 602): 1 of Ljava/lang/Class; 572B
W/dalvikvm( 602): 2 of Ljava/lang/Class; 596B (2 unique)
W/dalvikvm( 602): 1 of Ljava/lang/Class; 692B
W/dalvikvm( 602): 1 of Ljava/lang/Class; 956B
W/dalvikvm( 602): 1 of Ljava/lang/Class; 1004B
W/dalvikvm( 602): 1 of Ljava/lang/Class; 1148B
W/dalvikvm( 602): 2 of Ljava/lang/Class; 1172B (1 unique)
W/dalvikvm( 602): 1 of Ljava/lang/Class; 1316B
W/dalvikvm( 602): 1 of Ljava/lang/Class; 3428B
W/dalvikvm( 602): 1 of Ljava/lang/Class; 3452B
W/dalvikvm( 602): 1 of Ljava/lang/String; 28B
W/dalvikvm( 602): 2 of Ldalvik/system/VMRuntime; 12B (1 unique)
W/dalvikvm( 602): 10 of Ljava/lang/ref/WeakReference; 28B (10 unique)
W/dalvikvm( 602): 1 of Ldalvik/system/PathClassLoader; 44B
W/dalvikvm( 602): 1553 of Landroid/graphics/Point; 20B (1553 unique)
W/dalvikvm( 602): 261 of Landroid/graphics/Point; 28B (261 unique)
W/dalvikvm( 602): 1 of Landroid/view/MotionEvent; 100B
W/dalvikvm( 602): 1 of Landroid/app/ActivityThread$ApplicationThread; 28B
W/dalvikvm( 602): 1 of Landroid/content/ContentProvider$Transport; 28B
W/dalvikvm( 602): 1 of Landroid/view/Surface$CompatibleCanvas; 44B
W/dalvikvm( 602): 1 of Landroid/view/inputmethod/InputMethodManager$ControlledInputConnectionWrapper; 36B
W/dalvikvm( 602): 1 of Landroid/view/ViewRoot$1; 12B
W/dalvikvm( 602): 1 of Landroid/view/ViewRoot$W; 28B
W/dalvikvm( 602): 1 of Landroid/view/inputmethod/InputMethodManager$1; 28B
W/dalvikvm( 602): 1 of Landroid/view/accessibility/AccessibilityManager$1; 28B
W/dalvikvm( 602): 1 of Landroid/widget/LinearLayout$LayoutParams; 44B
W/dalvikvm( 602): 1 of Landroid/widget/LinearLayout; 332B
W/dalvikvm( 602): 2 of Lorg/apache/harmony/xnet/provider/jsse/TrustManagerImpl; 28B (1 unique)
W/dalvikvm( 602): 1 of Landroid/view/SurfaceView$MyWindow; 36B
W/dalvikvm( 602): 1 of Ltouchtest/RenderThread; 92B
W/dalvikvm( 602): 1 of Landroid/view/SurfaceView$3; 12B
W/dalvikvm( 602): 1 of Ltouchtest/DrawingView; 412B
W/dalvikvm( 602): 1 of Ltouchtest/Activity1; 180B
W/dalvikvm( 602): Memory held directly by tracked refs is 75624 bytes
E/dalvikvm( 602): Excessive JNI global references (2001)
E/dalvikvm( 602): VM aborting
Im obigen Beispiel (das übrigens aus Fehler 685215 stammt) besteht das Problem darin, dass zu viele Android.Graphics.Point-Instanzen erstellt werden; siehe Kommentar Nr. 2 für eine Liste der Korrekturen für diesen bestimmten Fehler.
In der Regel besteht eine nützliche Lösung darin, zu finden, welcher Typ zu viele Instanzen zugeordnet ist – Android.Graphics.Point im obigen Dump – und dann finden Sie, wo sie in Ihrem Quellcode erstellt werden und entsorgen sie entsprechend (sodass ihre Java-Objektlebensdauer gekürzt wird). Dies ist nicht immer geeignet (#685215 ist multithreaded, sodass die triviale Lösung den Dispose-Aufruf vermeidet), aber es ist das erste, was Sie berücksichtigen sollten.
Sie können die Protokollierung von globalen Verweisen aktivieren, um zu verfolgen, wann globale Verweise erstellt werden und wie viele vorhanden sind.
Abbruch aufgrund von nicht übereinstimmenden JNI-Typen
Wenn Sie den JNI-Code manuell erstellen, stimmen die Typen möglicherweise nicht miteinander überein, z. B. wenn Sie versuchen, java.lang.Runnable.run für einen Typ aufzurufen, der java.lang.Runnable nicht implementiert hat. In diesem Fall wird im Android-Debugprotokoll eine Meldung ähnlich der folgenden angezeigt:
W/dalvikvm( 123): JNI WARNING: can't call Ljava/Type;;.method on instance of Lanother/java/Type;
W/dalvikvm( 123): in Lmono/java/lang/RunnableImplementor;.n_run:()V (CallVoidMethodA)
...
E/dalvikvm( 123): VM aborting
Unterstützung für dynamischen Code
Dynamischer Code wird nicht kompiliert
Um C# dynamisch in Ihrer Anwendung oder Bibliothek zu verwenden, müssen Sie Ihrem Projekt System.Core.dll, Microsoft.CSharp.dll und Mono.CSharp.dll hinzufügen.
Im Releasebuild tritt der Fehler „MissingMethodException“ bei dynamischem Code zur Laufzeit auf.
Es ist wahrscheinlich, dass das Anwendungsprojekt keine Verweise auf „System.Core.dll“, „Microsoft.CSharp.dll“ oder „Mono.CSharp.dll“ enthält. Stellen Sie sicher, dass auf diese Assemblys verwiesen wird.
- Denken Sie daran, dass dynamischer Code immer mit Kosten verbunden ist. Wenn Sie effizienten Code benötigen, sollten Sie keinen dynamischen Code verwenden.
In der ersten Vorschau wurden diese Assemblys ausgeschlossen, es sei denn, die Typen in den einzelnen Assemblys werden explizit vom Anwendungscode verwendet. Unter dem folgenden Link finden Sie eine Problemumgehung: http://lists.ximian.com/pipermail/mo...il/009798.html
Mit AOT+LLVM erstellte Projekte stürzen auf x86-Geräten ab
Beim Bereitstellen einer App, die mit AOT+LLVM auf x86-basierten Geräten erstellt wurde, wird möglicherweise eine Ausnahmefehlermeldung ähnlich der folgenden angezeigt:
Assertion: should not be reached at /Users/.../external/mono/mono/mini/tramp-x86.c:124
Fatal signal 6 (SIGABRT), code -6 in tid 4051 (Xamarin.bug56111)
Dabei handelt es sich um ein bekanntes Problem. Die Problemumgehung besteht darin, LLVM zu deaktivieren.
