Während der Entwicklung einer App kann schnell das Bedürfnis aufkommen, dass man neben der eigentlichen Version der App auch eine Beta- oder Preview-Version erstellen möchte. So können zum Beispiel neue Features zuerst von Beta-Testern getestet werden, bevor diese in die öffentliche Version einfliessen.
In folgendem Beispiel wird gezeigt, wie man mit Hilfe einer zweiten Build Konfiguration eine zusätzliche Version einer App erstellt. Beide Versionen sollen den gleichen Source Code und dieselbe Solution verwenden. Trotzdem sollen sie sich aber in folgenden Punkten unterscheiden:
- Beide App Versionen sollen sich parallel installieren lassen und sich in ihrem Namen unterscheiden.
- Die App Icons sollen sich unterscheiden, damit man die beiden Apps leicht auseinanderhalten kann.
- Die Apps sollen je nach Version einen anderen API Endpoint Ansprechen.
Das fertiggestellte Beispiel ist hier abgelegt.
Zusätzliche Build Konfiguration erstellen
- Als erstes muss eine neue Build Konfiguration erstellt werden. Dazu öffnet man den Configuration Manager der Solution.
- Nun muss ein neuer Name eingegeben werden. Es ist sinnvoll die Einstellungen der bestehenden Release Konfiguration zu übernehmen.
- Anschliessen ist oben in der Toolbar die neu erstellte Konfiguration auswählbar
Parallele Installation und unterschiedliche App Namen
Der Package Name ist ein eindeutiges Identifikationsmerkmal für eine App. Möchte man eine zweite App Version parallel installieren, so muss diese zwingend einen anderen Package Namen besitzen. Aus diesem Grund, erstellt man zuerst ein neues AndroidManifest und kopiert den Inhalt des bereits bestehenden Manifests hinein. In diesem Beispiel wird dieses AndroidManifest.Preview.xml genannt. Anschliessend kann der Packange Name sowie das Application Label angepasst werden.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.demo.app.preview" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="16" /> <application android:label="My App (Preview) "></application> </manifest>
Damit nun das neue Manifest auch verwendet wird, muss die neue Build Konfiguration im der .csproj Datei des Android Projektes angepasst werden (AndroidManifest Attribut):
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release_Preview|AnyCPU'"> <DebugSymbols>true</DebugSymbols> <OutputPath>bin\Release_Preview\</OutputPath> <DefineConstants>TRACE</DefineConstants> <Optimize>true</Optimize> <DebugType>pdbonly</DebugType> <PlatformTarget>AnyCPU</PlatformTarget> <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies> <ErrorReport>prompt</ErrorReport> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <AndroidManifest>Properties\AndroidManifest.Preview.xml</AndroidManifest> </PropertyGroup>
Unterschiedliche App Icons
Damit man die beiden App Versionen auf einen Blick unterscheiden kann, ist es wünschenswert, dass diese unterschiedlichen Icons besitzen. Dazu passt man ebenfalls die csproj-Datei des Android Projektes an, sodass je nach Build Konfiguration ein unterschiedliches Icon verwendet wird. Damit die Datei trotz des unterschiedlichen Namens korrekt eingebunden wird, muss zusätzlich das LogicalName-Attribut verwendet werden.
<ItemGroup Condition="'$(Configuration)'!='Release_Preview'"> <AndroidResource Include="Resources\drawable\Icon.png" /> </ItemGroup> <ItemGroup Condition="'$(Configuration)'=='Release_Preview'"> <AndroidResource Include="Resources\drawable\Icon.preview.png"> <LogicalName>drawable\Icon.png</LogicalName> </AndroidResource> </ItemGroup>
Man kann nun jeweils ein APK in der Release Konfiguration und in der Release Preview Konfiguration erstellen und beide APKs auf einem Android Smartphone installieren. Dabei sollten die beide Apps nun einen unterschiedlichen Namen sowie unterschiedliche Icons besitzen (siehe Screenshot).
Unterschiedliche API Endpoints ansprechen
Neben unterschiedlichen App-Namen und Icon ist es oft auch erforderlich, dass sich die Apps in anderen Belangen unterscheiden. Möglicherweise möchte man in der Beta-Version der App nicht den API Endpoint der produktiven Umgebung verwenden, sondern jener der Beta- oder Integrationsumgebung.
Eine Möglichkeit dies zu implementieren, kann unter anderem das Verwenden von Compiler-Anweisungen sein. Diese können jedoch schnell über mehrere Dateien verteilt sein und zu unübersichtlichem Code führen.
Eine andere Option ist das Verwenden von XML-Konfigurationsdateien. Dadurch liegen alle Konfigurationen an einem zentralen Ort. Ausserdem kann eine XML Datei relativ einfach innerhalb eines automatisierten Build Prozess mit Hilfe von Build Scripts angepasst werden und bietet daher zusätzliche Flexibilität, wenn man Continuous Integration einsetzt.
Um den zusätzliche Aufwand möglichst gering zu halten, werden in diesem Beispiel zwei XML-Konfigurationsdateien erstellt, welche als String-Ressourcen im Android Projekt abgelegt werden. Diese heissen Configuration.xml sowie Configuration.Preview.xml. Zusätzlich muss wiederum die csproj-Datei des Android Projektes angepasst werden:
<ItemGroup Condition="'$(Configuration)'!='Release_Preview'"> <AndroidResource Include="Resources\values\Configuration.xml" /> <AndroidResource Include="Resources\drawable\Icon.png" /> </ItemGroup> <ItemGroup Condition="'$(Configuration)'=='Release_Preview'"> <AndroidResource Include="Resources\values\Configuration.Preview.xml" /> <AndroidResource Include="Resources\drawable\Icon.preview.png"> <LogicalName>drawable\Icon.png</LogicalName> </AndroidResource> </ItemGroup>
Anschliessend kann die Konfiguration auch im Code verfügbar gemacht werden, indeman eine zusätzliche eine Service-Klasse erstellt:
internal class AndroidDefaultConfiguration : IDefaultConfiguration { public string ApiBaseUrl => Application.Context.GetString(Resource.String.ApiBaseUrl); }
Fazit
Mit Hilfe einer zusätzliche Build Konfiguration kann man ohne grossen Aufwand eine zusätzliche Beta- oder Preview-Version einer App erstellen. Weiter kann das zusätzliche Einbinden einer XML-Konfigurationsdatei eine elegante Lösung sein, um zusätzliche Unterscheidungsmerkmale einfach zu implementieren.