[Proposal] Add an API to Track App Versions (#124)

* Add an API to track app versions

* Using the new Preferences model

* Made a few changes and updated the sample

* Added docs
This commit is contained in:
Matthew Leibowitz 2018-04-05 19:17:24 +02:00 коммит произвёл James Montemagno
Родитель 267edd1c88
Коммит 64f6130493
5 изменённых файлов: 378 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,118 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Microsoft.Caboodle
{
public static class VersionTracking
{
const string versionTrailKey = "VersionTracking.Trail";
const string versionsKey = "VersionTracking.Versions";
const string buildsKey = "VersionTracking.Builds";
static readonly string sharedName = $"{AppInfo.PackageName}.caboodle";
static Dictionary<string, List<string>> versionTrail;
static VersionTracking()
{
IsFirstLaunchEver = !Preferences.ContainsKey(versionsKey, sharedName) || !Preferences.ContainsKey(buildsKey, sharedName);
if (IsFirstLaunchEver)
{
versionTrail = new Dictionary<string, List<string>>
{
{ versionsKey, new List<string>() },
{ buildsKey, new List<string>() }
};
}
else
{
versionTrail = new Dictionary<string, List<string>>
{
{ versionsKey, ReadHistory(versionsKey).ToList() },
{ buildsKey, ReadHistory(buildsKey).ToList() }
};
}
IsFirstLaunchForCurrentVersion = !versionTrail[versionsKey].Contains(CurrentVersion);
if (IsFirstLaunchForCurrentVersion)
{
versionTrail[versionsKey].Add(CurrentVersion);
}
IsFirstLaunchForCurrentBuild = !versionTrail[buildsKey].Contains(CurrentBuild);
if (IsFirstLaunchForCurrentBuild)
{
versionTrail[buildsKey].Add(CurrentBuild);
}
if (IsFirstLaunchForCurrentVersion || IsFirstLaunchForCurrentBuild)
{
WriteHistory(versionsKey, versionTrail[versionsKey]);
WriteHistory(buildsKey, versionTrail[buildsKey]);
}
}
public static bool IsFirstLaunchEver { get; private set; }
public static bool IsFirstLaunchForCurrentVersion { get; private set; }
public static bool IsFirstLaunchForCurrentBuild { get; private set; }
public static string CurrentVersion => AppInfo.VersionString;
public static string CurrentBuild => AppInfo.BuildString;
public static string PreviousVersion => GetPrevious(versionsKey);
public static string PreviousBuild => GetPrevious(buildsKey);
public static string FirstInstalledVersion => versionTrail[versionsKey].FirstOrDefault();
public static string FirstInstalledBuild => versionTrail[buildsKey].FirstOrDefault();
public static IEnumerable<string> VersionHistory => versionTrail[versionsKey].ToArray();
public static IEnumerable<string> BuildHistory => versionTrail[buildsKey].ToArray();
public static bool IsFirstLaunchForVersion(string version)
=> CurrentVersion == version && IsFirstLaunchForCurrentVersion;
public static bool IsFirstLaunchForBuild(string build)
=> CurrentBuild == build && IsFirstLaunchForCurrentBuild;
internal static string GetStatus()
{
var sb = new StringBuilder();
sb.AppendLine();
sb.AppendLine("VersionTracking");
sb.AppendLine($" IsFirstLaunchEver: {IsFirstLaunchEver}");
sb.AppendLine($" IsFirstLaunchForCurrentVersion: {IsFirstLaunchForCurrentVersion}");
sb.AppendLine($" IsFirstLaunchForCurrentBuild: {IsFirstLaunchForCurrentBuild}");
sb.AppendLine();
sb.AppendLine($" CurrentVersion: {CurrentVersion}");
sb.AppendLine($" PreviousVersion: {PreviousVersion}");
sb.AppendLine($" FirstInstalledVersion: {FirstInstalledVersion}");
sb.AppendLine($" VersionHistory: [{string.Join(", ", VersionHistory)}]");
sb.AppendLine();
sb.AppendLine($" CurrentBuild: {CurrentBuild}");
sb.AppendLine($" PreviousBuild: {PreviousBuild}");
sb.AppendLine($" FirstInstalledBuild: {FirstInstalledBuild}");
sb.AppendLine($" BuildHistory: [{string.Join(", ", BuildHistory)}]");
return sb.ToString();
}
static string[] ReadHistory(string key)
=> Preferences.Get(key, null, sharedName)?.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries) ?? new string[0];
static void WriteHistory(string key, IEnumerable<string> history)
=> Preferences.Set(key, string.Join("|", history), sharedName);
static string GetPrevious(string key)
{
var trail = versionTrail[key];
return (trail.Count >= 2) ? trail[trail.Count - 2] : null;
}
}
}

Просмотреть файл

@ -45,6 +45,7 @@ The following cross-platform APIs are planned for our first release:
- [x] Secure Storage
- [x] SMS
- [ ] Text-to-Speech
- [x] Version Tracking
- [x] Vibrate
## Contributing

Просмотреть файл

@ -1,11 +1,15 @@
using System.Collections.ObjectModel;
using System.Linq;
using Caboodle.Samples.Model;
using Caboodle.Samples.View;
using Microsoft.Caboodle;
namespace Caboodle.Samples.ViewModel
{
public class HomeViewModel : BaseViewModel
{
private bool alreadyAppeared;
public HomeViewModel()
{
Items = new ObservableCollection<SampleItem>
@ -35,5 +39,25 @@ namespace Caboodle.Samples.ViewModel
}
public ObservableCollection<SampleItem> Items { get; }
public override void OnAppearing()
{
base.OnAppearing();
if (!alreadyAppeared)
{
alreadyAppeared = true;
if (VersionTracking.IsFirstLaunchEver)
{
DisplayAlert("Welcome to the Caboodle samples!");
}
else if (VersionTracking.IsFirstLaunchForCurrentVersion)
{
var count = VersionTracking.VersionHistory.Count();
DisplayAlert($"Welcome to the NEW Caboodle samples! You have tried {count} versions.");
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,234 @@
<Type Name="VersionTracking" FullName="Microsoft.Caboodle.VersionTracking">
<TypeSignature Language="C#" Value="public static class VersionTracking" />
<TypeSignature Language="ILAsm" Value=".class public auto ansi abstract sealed VersionTracking extends System.Object" />
<AssemblyInfo>
<AssemblyName>Microsoft.Caboodle</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>System.Object</BaseTypeName>
</Base>
<Interfaces />
<Docs>
<summary>Provides an easy way to track an app's version on a device.</summary>
<remarks></remarks>
</Docs>
<Members>
<Member MemberName="BuildHistory">
<MemberSignature Language="C#" Value="public static System.Collections.Generic.IEnumerable&lt;string&gt; BuildHistory { get; }" />
<MemberSignature Language="ILAsm" Value=".property class System.Collections.Generic.IEnumerable`1&lt;string&gt; BuildHistory" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Collections.Generic.IEnumerable&lt;System.String&gt;</ReturnType>
</ReturnValue>
<Docs>
<summary>Gets the collection of build numbers of the app that ran on this device.</summary>
<value></value>
<remarks></remarks>
</Docs>
</Member>
<Member MemberName="CurrentBuild">
<MemberSignature Language="C#" Value="public static string CurrentBuild { get; }" />
<MemberSignature Language="ILAsm" Value=".property string CurrentBuild" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>Gets the current build of the app.</summary>
<value></value>
<remarks></remarks>
</Docs>
</Member>
<Member MemberName="CurrentVersion">
<MemberSignature Language="C#" Value="public static string CurrentVersion { get; }" />
<MemberSignature Language="ILAsm" Value=".property string CurrentVersion" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>Gets the current version number of the app.</summary>
<value></value>
<remarks></remarks>
</Docs>
</Member>
<Member MemberName="FirstInstalledBuild">
<MemberSignature Language="C#" Value="public static string FirstInstalledBuild { get; }" />
<MemberSignature Language="ILAsm" Value=".property string FirstInstalledBuild" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>Gets the build number of first version of the app that was installed on this device.</summary>
<value></value>
<remarks></remarks>
</Docs>
</Member>
<Member MemberName="FirstInstalledVersion">
<MemberSignature Language="C#" Value="public static string FirstInstalledVersion { get; }" />
<MemberSignature Language="ILAsm" Value=".property string FirstInstalledVersion" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>Gets the version number of the first version of the app that was installed on this device.</summary>
<value></value>
<remarks></remarks>
</Docs>
</Member>
<Member MemberName="IsFirstLaunchEver">
<MemberSignature Language="C#" Value="public static bool IsFirstLaunchEver { get; }" />
<MemberSignature Language="ILAsm" Value=".property bool IsFirstLaunchEver" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Boolean</ReturnType>
</ReturnValue>
<Docs>
<summary>Gets a value indicating whether this is the first time this app has ever been launched on this device.</summary>
<value></value>
<remarks></remarks>
</Docs>
</Member>
<Member MemberName="IsFirstLaunchForBuild">
<MemberSignature Language="C#" Value="public static bool IsFirstLaunchForBuild (string build);" />
<MemberSignature Language="ILAsm" Value=".method public static hidebysig bool IsFirstLaunchForBuild(string build) cil managed" />
<MemberType>Method</MemberType>
<AssemblyInfo>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Boolean</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="build" Type="System.String" />
</Parameters>
<Docs>
<param name="build">The build number.</param>
<summary>Determines if this is the first launch of the app for a specified build number.</summary>
<returns>Returns true if this is the first launch of the app for the specified build number; otherwise false.</returns>
<remarks></remarks>
</Docs>
</Member>
<Member MemberName="IsFirstLaunchForCurrentBuild">
<MemberSignature Language="C#" Value="public static bool IsFirstLaunchForCurrentBuild { get; }" />
<MemberSignature Language="ILAsm" Value=".property bool IsFirstLaunchForCurrentBuild" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Boolean</ReturnType>
</ReturnValue>
<Docs>
<summary>Gets a value indicating if this is the first launch of the app for the current build number.</summary>
<value></value>
<remarks></remarks>
</Docs>
</Member>
<Member MemberName="IsFirstLaunchForCurrentVersion">
<MemberSignature Language="C#" Value="public static bool IsFirstLaunchForCurrentVersion { get; }" />
<MemberSignature Language="ILAsm" Value=".property bool IsFirstLaunchForCurrentVersion" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Boolean</ReturnType>
</ReturnValue>
<Docs>
<summary>Gets a value indicating if this is the first launch of the app for the current version number.</summary>
<value></value>
<remarks></remarks>
</Docs>
</Member>
<Member MemberName="IsFirstLaunchForVersion">
<MemberSignature Language="C#" Value="public static bool IsFirstLaunchForVersion (string version);" />
<MemberSignature Language="ILAsm" Value=".method public static hidebysig bool IsFirstLaunchForVersion(string version) cil managed" />
<MemberType>Method</MemberType>
<AssemblyInfo>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Boolean</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="version" Type="System.String" />
</Parameters>
<Docs>
<param name="version">The version number.</param>
<summary>Determines if this is the first launch of the app for a specified version number.</summary>
<returns>Returns true if this is the first launch of the app for the specified version number; otherwise false.</returns>
<remarks></remarks>
</Docs>
</Member>
<Member MemberName="PreviousBuild">
<MemberSignature Language="C#" Value="public static string PreviousBuild { get; }" />
<MemberSignature Language="ILAsm" Value=".property string PreviousBuild" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>Gets the build number for the previously run version.</summary>
<value></value>
<remarks></remarks>
</Docs>
</Member>
<Member MemberName="PreviousVersion">
<MemberSignature Language="C#" Value="public static string PreviousVersion { get; }" />
<MemberSignature Language="ILAsm" Value=".property string PreviousVersion" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>Gets the version number for the previously run version.</summary>
<value></value>
<remarks></remarks>
</Docs>
</Member>
<Member MemberName="VersionHistory">
<MemberSignature Language="C#" Value="public static System.Collections.Generic.IEnumerable&lt;string&gt; VersionHistory { get; }" />
<MemberSignature Language="ILAsm" Value=".property class System.Collections.Generic.IEnumerable`1&lt;string&gt; VersionHistory" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Collections.Generic.IEnumerable&lt;System.String&gt;</ReturnType>
</ReturnValue>
<Docs>
<summary>Gets the collection of version numbers of the app that ran on this device.</summary>
<value></value>
<remarks></remarks>
</Docs>
</Member>
</Members>
</Type>

Просмотреть файл

@ -122,6 +122,7 @@
<Type Name="ShareTextRequest" Kind="Class" />
<Type Name="Sms" Kind="Class" />
<Type Name="SmsMessage" Kind="Class" />
<Type Name="VersionTracking" Kind="Class" />
<Type Name="Vibration" Kind="Class" />
</Namespace>
</Types>