Xamarin.Android
Uw Xamarin.Android APK publiceren
Zoeken…
Invoering
Dit onderwerp toont informatie over het voorbereiden van uw Xamarin.Android-app voor de releasemodus en hoe deze te optimaliseren.
Uw APK voorbereiden in Visual Studio
U hebt uw app voltooid, getest in de foutopsporingsmodus en deze werkt perfect. Nu wilt u het voorbereiden om te publiceren in de Google Play Store.
Xamarin-documentatie biedt hier goede informatie:
Android-manifest
Klik eerst in Visual Studio met de rechtermuisknop op uw Xamarin.Android-project in Solution Explorer en selecteer Eigenschappen. Ga vervolgens naar het tabblad Android Manifest om dit scherm te bekijken:
Anders dan in Android Studio of Eclipse, hoeft u het bestand AndroidManifest.xml niet schriftelijk in te stellen; Xamarin en Visual Studio doen dat voor u. Activiteiten, BroadcastReceivers en Services worden in Android Manifest ingevoegd door specifieke kenmerken in hun klassen aan te geven .
In dit scherm zijn de opties:
- Applicatienaam : dit is de app-naam die zichtbaar is voor de gebruiker.
- Pakketnaam : dit is de pakketnaam. Het moet uniek zijn, wat betekent dat het niet dezelfde pakketnaam van andere apps in de Google Play Store mag gebruiken.
- Toepassingspictogram : dit is het pictogram dat zichtbaar is voor de gebruiker, gelijk aan de @ drawable / ic_launcher die wordt gebruikt in Android Studio- of Eclipse-projecten.
- Versienummer : het versienummer wordt door Google Play gebruikt voor versiebeheer. Als u een APK wilt publiceren voor een bijgewerkte versie van uw app, moet u 1 toevoegen aan dit nummer voor elke nieuwe upgrade.
- Versienaam : dit is de versienaam die aan de gebruiker wordt getoond.
- Installatielocatie : dit bepaalt waar uw APK wordt geïnstalleerd in de apparaatopslag of SD-kaart.
- Vereiste rechten : hier bepaalt u welke machtigingen nodig zijn voor uw app.
Android-opties
In het onderstaande scherm kunt u de compileropties configureren. Met de juiste opties hier kunt u uw APK-grootte aanzienlijk verminderen en ook fouten voorkomen.
- Configuratie : Actief (release) .
- Platform : Actief (elke CPU) . Deze zijn nodig om uw APK te bouwen voor de Google Play Store. Als de configuratie is ingesteld op Foutopsporing, wordt deze niet geaccepteerd door Google Play.
- Gebruik Shared Runtime : false . Als u dit instelt op true, gebruikt de APK Mono Runtime om uit te voeren. De Mono Runtime wordt automatisch geïnstalleerd bij het debuggen via USB, maar niet in de Release APK. Als Mono Runtime niet op het apparaat is geïnstalleerd en deze optie is ingesteld op true in de Release APK, crasht de app.
- Genereer één pakket (.apk) per geselecteerde ABI : false . Maak uw APK voor zoveel mogelijk platforms, vanwege compatibiliteitsredenen.
- Multi-Dex inschakelen : waar , maar u kunt het instellen op onwaar als uw app niet erg complex is (dat wil zeggen, heeft minder dan 65536 methoden, zie hier ).
- Proguard inschakelen : waar . Dit maakt de Proguard-tool mogelijk die de Java-code in uw app verdoezelt. Merk op dat het niet van toepassing is op .NET-code; als u .NET-code wilt verbergen , moet u Dotfuscator gebruiken . Meer informatie over Proguard voor Xamarin.Android kan worden gevonden hier .
- Instrumentatie voor ontwikkelaars inschakelen (foutopsporing en profilering) : false voor release APK.
- Koppeling : SDK en gebruikersassemblages . Hierdoor zal de Xamarin Linker alle ongebruikte klassen van SDK en uw code verwijderen, waardoor de APK-grootte wordt verkleind.
Belangrijk
Xamarin.Linker verwijdert soms klassen die niet door uw code lijken te worden gebruikt, vooral als ze zich in de Core (PCL-bibliotheek) van het project bevinden. Om dat te voorkomen, kunt u de koppeling instellen op "Alleen Sdk-merken" of het kenmerk Behouden in uw klassen gebruiken, bijvoorbeeld:
PreserveAttribute.cs
namespace My_App_Core.Models
{
public sealed class PreserveAttribute : System.Attribute
{
public bool AllMembers;
public bool Conditional;
}
}
In een klas:
using System;
namespace My_App_Core.Models
{
[Preserve(AllMembers = true)]
public class ServiceException : Exception
{
public int errorCode;
[Preserve(AllMembers = true)]
public ServiceException() { }
[Preserve(AllMembers = true)]
public ServiceException(int errorCode)
{
this.errorCode = errorCode;
}
}
}
- Ondersteunde architecturen : selecteer alles om redenen van compatibiliteit.
Nadat u alles hebt geconfigureerd, bouwt u het project opnieuw op om ervoor te zorgen dat het succesvol wordt opgebouwd.
De APK maken voor de vrijgavemodus
U bent klaar met het configureren van uw Android-project voor release. De onderstaande zelfstudie laat zien hoe de APK in Visual Studio wordt gegenereerd. Een volledige tutorial van Xamarin-documentatie is hier te vinden:
Om het APK-bestand te maken, klikt u met de rechtermuisknop op het Xamarin.Android-project in Solution Explorer en selecteert u Archiveren ...
Dit opent de archiefbeheerder en begint met het archiveren van het project, waarbij het APK-bestand wordt voorbereid.
Wanneer het archiveren van het project is voltooid, klikt u op Distribueren ... om door te gaan.
Het scherm Distribueren biedt u twee opties: Ad-hoc en Google Play. De eerste maakt een APK en slaat deze op uw computer op. De tweede publiceert de app rechtstreeks in Google Play.
Het wordt aanbevolen om de eerste te kiezen, zodat u de APK op andere apparaten kunt testen als u dat wilt.
In het volgende scherm is een Android Key Store nodig om de APK te ondertekenen. Als je er al een hebt, kun je deze gebruiken door te klikken op Importeren ...; Als u dat niet doet, kunt u een nieuwe Android Key Store maken door in + te klikken.
Een nieuw Android Key Store-scherm maken:
Klik op Opslaan als om de APK te maken. U wordt mogelijk gevraagd om het Key Store-wachtwoord te typen.
Wanneer het is voltooid, kunt u klikken op Map openen op het scherm Archieven om uw gegenereerde APK-bestand te bekijken.
MultiDex inschakelen in uw Xamarin.Android APK
MultiDex is een bibliotheek in de Android APK waarmee de app meer dan 65.536 methoden kan hebben.
De Android APK's hebben Dalvik Executable-bestanden (.dex) die de gegenereerde bytecodes bevatten die zijn gecompileerd uit uw Java-code. Elk .dex-bestand kan maximaal 65.536 methoden bevatten (2 ^ 16).
Android OS-versies vóór Android 5.0 Lollipop (API 21) gebruiken de Dalvik-runtime, die slechts één .dex-bestand per APK ondersteunt, beperkt tot 65.536 methoden per APK. Vanaf Android 5.0 gebruikt het Android-besturingssysteem ART-runtime, dat meer dan één .dex-bestand per APK kan ondersteunen, waarbij de limiet wordt vermeden.
Om de limiet van 65k methoden in Android-versies onder API 21 te overtreffen, moeten de ontwikkelaars de MultiDex-ondersteuningsbibliotheek gebruiken. De MultiDex maakt extra klassen.dex-bestanden (klassen2.dex, klassen3.dex, ...) waarnaar wordt verwezen in het bestand klassen.dex. Wanneer de app begint te laden, gebruikt deze een MultiDexApplication-klasse om de extra .dex-bestanden te laden.
Als uw Android-app streeft naar een minimale SDK-versie hoger dan of gelijk aan API 21 (Android 5.0 Lollipop), is het niet nodig om de MultiDex-bibliotheek te gebruiken, omdat het besturingssysteem native de extra .dex-bestanden verwerkt. Als de ontwikkelaar echter om compatibiliteitsredenen ouder Android-besturingssysteem wil ondersteunen, moet hij / zij de MultiDex-bibliotheek gebruiken.
Hoe MultiDex te gebruiken in uw Xamarin.Android-app
Ga eerst naar MultiDex in uw Xamarin.Android-app en ga naar uw project Eigenschappen -> Android-opties -> Verpakking -> Multi-Dex inschakelen, zoals in het onderstaande afdrukscherm:
Vervolgens moet u een MultiDexApplication-klasse in uw app maken. Maak in de root van het project een nieuwe klasse (klik in de Solution Explorer met de rechtermuisknop in het project, Toevoegen ... -> Klasse of Shift + Alt + C). Kopieer in het nieuwe klassenbestand de volgende code, waarbij u de naamruimte Sample vervangt door de naam van uw Xamarin.Android-projectnaamruimte.
using System;
using Android.App;
using Android.Runtime;
using Java.Interop;
namespace Sample
{
[Register("android/support/multidex/MultiDexApplication", DoNotGenerateAcw = true)]
public class MultiDexApplication : Application
{
internal static readonly JniPeerMembers _members =
new XAPeerMembers("android/support/multidex/MultiDexApplication", typeof (MultiDexApplication));
internal static IntPtr java_class_handle;
private static IntPtr id_ctor;
[Register(".ctor", "()V", "", DoNotGenerateAcw = true)]
public MultiDexApplication()
: base(IntPtr.Zero, JniHandleOwnership.DoNotTransfer)
{
if (Handle != IntPtr.Zero)
return;
try
{
if (GetType() != typeof (MultiDexApplication))
{
SetHandle(
JNIEnv.StartCreateInstance(GetType(), "()V"),
JniHandleOwnership.TransferLocalRef);
JNIEnv.FinishCreateInstance(Handle, "()V");
return;
}
if (id_ctor == IntPtr.Zero)
id_ctor = JNIEnv.GetMethodID(class_ref, "<init>", "()V");
SetHandle(
JNIEnv.StartCreateInstance(class_ref, id_ctor),
JniHandleOwnership.TransferLocalRef);
JNIEnv.FinishCreateInstance(Handle, class_ref, id_ctor);
}
finally
{
}
}
protected MultiDexApplication(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
}
internal static IntPtr class_ref
{
get { return JNIEnv.FindClass("android/support/multidex/MultiDexApplication", ref java_class_handle); }
}
protected override IntPtr ThresholdClass
{
get { return class_ref; }
}
protected override Type ThresholdType
{
get { return typeof (MultiDexApplication); }
}
}
}
Als u ontwikkelt in Visual Studio voor Windows, is er ook een fout in de Android SDK-buildtools die u moet repareren om de klassen.dex-bestanden correct te maken bij het bouwen van uw project.
Ga naar je Android SDK-map, open de map build-tools en er zullen mappen zijn met de nummers van de Android SDK-compilers, zoals:
C: \ android-sdk \ build-instrumenten \ 23.0.3 \
C: \ android-sdk \ build-instrumenten \ 24.0.1 \
C: \ android-sdk \ build-instrumenten \ 25.0.2 \
Binnen elk van die mappen bevindt zich een bestand met de naam mainClassesDex.bat , een batch-script dat wordt gebruikt om de klassen.dex-bestanden te maken. Open elk mainClassesDex.bat-bestand met een teksteditor (Kladblok of Kladblok ++) en zoek en vervang in zijn script het blok:
if DEFINED output goto redirect
call "%java_exe%" -Djava.ext.dirs="%frameworkdir%" com.android.multidex.MainDexListBuilder "%disableKeepAnnotated%" "%tmpJar%" "%params%"
goto afterClassReferenceListBuilder
:redirect
call "%java_exe%" -Djava.ext.dirs="%frameworkdir%" com.android.multidex.MainDexListBuilder "%disableKeepAnnotated%" "%tmpJar%" "%params%" 1>"%output%"
:afterClassReferenceListBuilder
Met het blok:
SET params=%params:'=%
if DEFINED output goto redirect
call "%java_exe%" -Djava.ext.dirs="%frameworkdir%" com.android.multidex.MainDexListBuilder %disableKeepAnnotated% "%tmpJar%" %params%
goto afterClassReferenceListBuilder
:redirect
call "%java_exe%" -Djava.ext.dirs="%frameworkdir%" com.android.multidex.MainDexListBuilder %disableKeepAnnotated% "%tmpJar%" %params% 1>"%output%"
:afterClassReferenceListBuilder
Sla elke mainClassesDex.bat op in de teksteditor na wijzigingen.
Na de bovenstaande stappen zou u uw Xamarin.Android-app met MultiDex moeten kunnen bouwen.
ProGuard inschakelen in uw Xamarin.Android APK
ProGuard is een hulpmiddel dat wordt gebruikt in het bouwproces om de Java-code van uw APK te optimaliseren en te verbergen en ook ongebruikte klassen te verwijderen. De resulterende APK bij gebruik van ProGuard zal kleiner zijn en moeilijker te reverse-engineeren (decompilatie).
ProGuard kan ook worden gebruikt in Xamarin.Android-apps en zal ook de APK-bestandsgrootte verkleinen en de Java-code verdoezelen. Houd er echter rekening mee dat de obstructie van ProGuard alleen van toepassing is op Java-code. Om .NET-code te verdoezelen, moet de ontwikkelaar Dotfuscator of vergelijkbare hulpmiddelen gebruiken.
Hoe ProGuard in uw Xamarin.Android-app te gebruiken
Om ProGuard in te schakelen in uw Xamarin.Android-app, gaat u eerst naar uw project Eigenschappen -> Android-opties -> Verpakking -> ProGuard inschakelen, zoals in het onderstaande afdrukscherm:
Dit maakt ProGuard mogelijk bij het bouwen van uw app.
Xamarin.Android stelt standaard zijn eigen configuraties voor ProGuard in, die te vinden zijn in de mappen obj/Debug/proguard
of obj/Release/proguard
, in de bestanden proguard_project_primary.cfg
, proguard_project_references.cfg
en proguard_xamarin.cfg
. De drie bestanden worden gecombineerd als configuraties voor ProGuard en ze worden automatisch gemaakt door Xamarin tijdens het bouwen.
Als de ontwikkelaar de ProGuard-opties verder wil aanpassen, kan hij / zij een bestand maken in de root van het project met de naam proguard.cfg
(andere namen zijn ook geldig zolang de extensie .cfg is) en de Build Action instellen op ProguardConfiguration, zoals op de onderstaande afbeelding:
In het bestand kunnen aangepaste ProGuard-opties worden ingevoegd, zoals -dontwarn
, -keep class
en andere .
Belangrijk
Zoals nu (april / 2017), heeft de Android SDK die meestal wordt gedownload een oude versie van ProGuard, die fouten kan veroorzaken bij het bouwen van de app met Java 1.8. Tijdens het bouwen geeft de foutenlijst het volgende bericht weer:
Error
Can't read [C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v7.0\mono.android.jar]
(Can't process class [android/app/ActivityTracker.class] (Unsupported class version number [52.0] (maximum 51.0, Java 1.7))) [CREATEMULTIDEXMAINDEXCLASSLIST]
Om dit probleem op te lossen, moet u de meest recente versie van ProGuard downloaden ( hier ) en de inhoud van het .zip-bestand naar android-sdk\tools\proguard\
. Dat zal de ProGuard updaten en het bouwproces zou zonder problemen moeten verlopen.
Daarna zou u uw Xamarin.Android-app met ProGuard moeten kunnen bouwen.
"Mysterieuze" bugs gerelateerd aan ProGuard en Linker
Je hebt een geweldige app gemaakt en deze in Debug getest, met goede resultaten. Alles werkte prima!
Maar toen besloot je je app voor te bereiden voor release. U hebt MultiDex, ProGuard en Linker ingesteld en het werkte niet meer.
Deze tutorial is bedoeld om u te helpen bij het vinden van veelvoorkomende problemen met betrekking tot ProGuard en Linker die mysterieuze bugs kunnen veroorzaken.
Inzicht in Xamarin.Linker
Xamarin.Linker is een hulpmiddel in het bouwproces dat ongebruikte code en klassen verwijdert uit uw .NET-code (geen Java-code) . In de eigenschappen van uw project -> Android-opties -> Linker, is er een selectievak Linking met de opties:
Geen : er wordt geen code verwijderd.
Alleen SDK-assemblages : met deze optie controleert de Xamarin.Linker alleen ongebruikte code in de Xamarin-bibliotheken. Deze optie is veilig.
Sdk- en gebruikersassemblages : met deze optie controleert de Xamarin.Linker op ongebruikte code in de Xamarin-bibliotheken en in de projectcode (inclusief PCL's, Xamarin-componenten en NuGet-pakketten). Deze optie is niet altijd veilig!
Bij het gebruik van de optie Sdk en gebruikersassemblages, kan Xamarin.Linker denken dat delen van de code ongebruikt zijn terwijl ze eigenlijk heel veel worden gebruikt! Dat kan ertoe leiden dat sommige bibliotheken niet meer goed werken en bugs in uw app veroorzaken.
Om de Xamarin.Linker code niet te laten verwijderen, zijn er 3 opties:
- De koppelingsoptie instellen op Geen of Alleen SD-merken;
- Koppelingen overslaan;
- Het kenmerk Behouden gebruiken.
Voorbeeld voor 2. Koppelingen overslaan:
In het onderstaande voorbeeld veroorzaakte het gebruik van Xamarin.Linker een NuGet-pakket ( Octokit ) dat goed werkt om te stoppen met werken, omdat het geen verbinding meer kon maken met internet:
[0:] ERROR
[0:] SOURCE: mscorlib
[0:] MESSAGE: Object reference not set to an instance of an object.
[0:] STACK TRACE: at Octokit.PocoJsonSerializerStrategy.DeserializeObject (System.Object value, System.Type type) [0x003d8] in D:\repos\octokit.net\Octokit\SimpleJson.cs:1472
at Octokit.Internal.SimpleJsonSerializer+GitHubSerializerStrategy.DeserializeObject (System.Object value, System.Type type) [0x001c3] in D:\repos\octokit.net\Octokit\Http\SimpleJsonSerializer.cs:165
at Octokit.SimpleJson.DeserializeObject (System.String json, System.Type type, Octokit.IJsonSerializerStrategy jsonSerializerStrategy) [0x00007] in D:\repos\octokit.net\Octokit\SimpleJson.cs:583
at Octokit.SimpleJson.DeserializeObject[T] (System.String json, Octokit.IJsonSerializerStrategy jsonSerializerStrategy) [0x00000] in D:\repos\octokit.net\Octokit\SimpleJson.cs:595
at Octokit.Internal.SimpleJsonSerializer.Deserialize[T] (System.String json) [0x00000] in D:\repos\octokit.net\Octokit\Http\SimpleJsonSerializer.cs:21
at Octokit.Internal.JsonHttpPipeline.DeserializeResponse[T] (Octokit.IResponse response) [0x000a7] in D:\repos\octokit.net\Octokit\Http\JsonHttpPipeline.cs:62
at Octokit.Connection+<Run>d__54`1[T].MoveNext () [0x0009c] in D:\repos\octokit.net\Octokit\Http\Connection.cs:574
--- End of stack trace from previous location where exception was thrown ---
Om de bibliotheek weer te laten werken, was het noodzakelijk om de pakketreferentienaam toe te voegen in het veld Koppelingsmontages overslaan, in project -> Eigenschappen -> Android-opties -> Linker, zoals in de onderstaande afbeelding:
Daarna begon de bibliotheek probleemloos te werken.
Voorbeeld voor 3. Gebruik van het kenmerk Behouden:
Xamarin.Linker beschouwt als ongebruikte code meestal code uit modelklassen in de kern van uw project.
Om de klasse tijdens het koppelingsproces te behouden, kunt u het kenmerk Behouden gebruiken.
Maak eerst in de kern van uw project een klasse met de naam PreserveAttribute.cs , voer de volgende code in en vervang de naamruimte door de naamruimte van uw project:
PreserveAttribute.cs:
namespace My_App_Core.Models
{
public sealed class PreserveAttribute : System.Attribute
{
public bool AllMembers;
public bool Conditional;
}
}
Voeg in elke modelklasse van de kern van uw project het kenmerk Behoud in, zoals in het onderstaande voorbeeld:
Country.cs:
using System;
using System.Collections.Generic;
namespace My_App_Core.Models
{
[Preserve(AllMembers = true)]
public class Country
{
public String name { get; set; }
public String ISOcode { get; set; }
[Preserve(AllMembers = true)]
public Country(String name, String ISOCode)
{
this.name = name;
this.ISOCode = ISOCode;
}
}
}
Daarna zal het koppelingsproces de bewaarde code niet meer verwijderen.
ProGuard begrijpen
ProGuard is een hulpmiddel in het bouwproces dat ongebruikte code en klassen uit uw Java-code verwijdert . Het verduistert en optimaliseert ook de code.
ProGuard kan echter soms code verwijderen die het als ongebruikt beschouwt, wanneer dit niet het geval is. Om dat te voorkomen, moet de ontwikkelaar de app debuggen (in Android Device Monitor en in Visual Studio Debug) en detecteren welke klasse is verwijderd, om vervolgens het configuratiebestand van ProGuard te configureren om de klasse te behouden.
Voorbeeld
In het onderstaande voorbeeld heeft ProGuard twee klassen verwijderd (Android.Support.V7.Widget.FitWindowsLinearLayout en Android.Support.Design.Widget.AppBarLayout) gebruikt in AXML-layoutbestanden, maar die in de code als ongebruikt werden beschouwd. De verwijdering veroorzaakte ClassNotFoundException in de Java-code bij het renderen van de activiteitslay-out:
layout_activitymain.axml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activitymain_drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true" <!-- ### HERE ### -->
tools:openDrawer="start">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!-- ### HERE ## -->
<android.support.design.widget.AppBarLayout
android:id="@+id/activitymain_appbarlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
...
LogCat geeft foutmelding bij het maken van de lay-out in SetContentView:
Om deze fout te verhelpen, was het noodzakelijk om de volgende regels toe te voegen aan het ProGuard-configuratiebestand van het project:
-keep public class android.support.v7.widget.FitWindowsLinearLayout
-keep public class android.support.design.widget.AppBarLayout
Daarna werden geen fouten meer getoond bij het maken van de lay-out.
ProGuard-waarschuwingen
ProGuard toont soms waarschuwingen in de foutenlijst na het bouwen van uw project. Hoewel ze de vraag oproepen of je app OK is of niet, duiden niet alle waarschuwingen op problemen, vooral als je app met succes is gebouwd.
Een voorbeeld hiervan is het gebruik van de Picasso- bibliotheek: bij het gebruik van ProGuard kan dit waarschuwingen zoals okio.Okio: can't find referenced class (...)
of can't write resource [META-INF/MANIFEST.MF] (Duplicate zip entry [okhttp.jar:META-INF/MANIFEST.MF]) (...)
, maar de app bouwt en de bibliotheek werkt zonder problemen.