应用解决方案部署中的试用功能设计与实现
1. 应用内购买与发布注意事项
在应用的试用版本期间,不可以提供应用内购买功能。在将应用发布到 Windows 应用商店之前,需要实现所有计划通过应用内购买向用户提供的功能和产品。若在应用发布后想添加新功能或产品,则需向 Windows 应用商店提交应用的更新版本。
2. 探索应用的许可状态
可以使用
Windows.ApplicationModel.Store
命名空间提供的许可 API 来确定应用或应用内购买功能的许可状态。这些 API 能实现以下操作:
- 检查应用的当前许可状态
- 检查试用期限的到期日期
- 检查应用的某个功能是否已通过应用内购买获得
- 执行应用内购买
3. 许可信息属性
CurrentApp
类的
LicenseInformation
属性可用于访问应用当前许可状态以及用户进行应用内购买时启用的其他产品或功能的相关信息。
LicenseInformation
类具有以下只读属性:
| 属性 | 描述 |
| ---- | ---- |
|
IsActive
| 描述应用的当前许可状态。值为
true
表示许可有效,无论应用是否处于试用模式;值为
false
表示应用许可状态无效,可能是许可缺失、过期或已被撤销。 |
|
IsTrial
| 指示应用是否处于试用模式。值为
false
表示用户已购买应用的完整版本;值为
true
表示应用仍处于试用模式。需注意,即使试用期已过,该属性仍会返回
true
,因此应始终结合
IsActive
属性进行检查。 |
|
ExpirationDate
| 指示试用的到期日期,日期必须采用 ISO 8601 格式(yyyy - mm - ddThh:mm:ss.ssZ)。例如,2014 - 06 - 19T09:00:00.00Z 表示试用将在 2014 年 6 月 19 日上午 9 点到期。 |
|
ProductLicenses
| 包含可通过应用内购买获得的应用功能的许可列表。 |
由于
CurrentApp
类包含从 Windows 应用商店检索的数据和信息,因此只有在应用发布到 Windows 应用商店后才能访问这些信息。而且,在本地环境中使用
CurrentApp
类测试应用的不同行为会很困难,因为这需要与实际的 Windows 应用商店进行交互。在处理试用和应用内购买时,应使用
CurrentAppSimulator
类,它定义的方法和属性与
CurrentApp
类相似,但在模拟环境中运行。可以使用
CurrentAppSimulator
类的方法和属性获取模拟的许可信息(如应用 ID 和许可元数据),以便在开发环境中测试应用的行为。
注意
:在将应用提交到 Windows 应用商店之前,记得将
CurrentAppSimulator
类替换为
CurrentApp
类,否则应用将无法通过认证过程。
以下是通过
CurrentAppSimulator
对象检索模拟许可状态并显示在屏幕上的代码:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.DisplayLicenseInfo();
}
private async void DisplayLicenseInfo()
{
var licenseInfo = CurrentAppSimulator.LicenseInformation;
if (licenseInfo.IsActive)
{
if (licenseInfo.IsTrial)
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
() =>
{
LicenseState.Text = "License current status: Trial license";
var remainingDays = (licenseInfo.ExpirationDate - DateTime.Now).Days;
LicenseRemainingDays.Text = String.Format(
"Expiration date: {0:MM/dd/yyyy} - Remaining days: {1}",
licenseInfo.ExpirationDate, remainingDays);
});
}
else
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
() =>
{
LicenseState.Text = "License current status: Full license";
LicenseRemainingDays.Text = "no expiration";
});
}
}
else
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
LicenseState.Text = "License current status: license is expired. Please buy the app!";
});
}
}
接下来,需要添加一些 Extensible Application Markup Language (XAML) 控件来显示检索到的信息。以下是默认页面的 XAML 定义:
<Page
x:Class="Demo.Chapter6.TimedTrial.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Demo.Chapter6.TimedTrial"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<StackPanel Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<TextBlock x:Name="LicenseState" FontSize="20" Margin="20, 5" Width="Auto" />
<TextBlock x:Name="LicenseRemainingDays" FontSize="20, 5" Margin="20"
Width="Auto" />
</StackPanel>
</Page>
当使用
CurrentAppSimulator
类时,应用的初始许可状态由位于
%userprofile%\appdata\local\packages\<package - moniker>\localstate\microsoft\Windows Store\Apidata
文件夹中的
WindowsStoreProxy.xml
文件定义。以下是自动生成的
WindowsStoreProxy.xml
文件示例:
<?xml version="1.0" encoding="utf-16" ?>
<CurrentApp>
<ListingInformation>
<App>
<AppId>00000000-0000-0000-0000-000000000000</AppId>
<LinkUri>
http://apps.microsoft.com/webpdp/app/00000000-0000-0000-0000-000000000000
</LinkUri>
<CurrentMarket>en-US</CurrentMarket>
<AgeRating>3</AgeRating>
<MarketData xml:lang="en-us">
<Name>AppName</Name>
<Description>AppDescription</Description>
<Price>1.00</Price>
<CurrencySymbol>$</CurrencySymbol>
<CurrencyCode>USD</CurrencyCode>
</MarketData>
</App>
<Product ProductId="1" LicenseDuration="0">
<MarketData xml:lang="en-us">
<Name>Product1Name</Name>
<Price>1.00</Price>
<CurrencySymbol>$</CurrencySymbol>
<CurrencyCode>USD</CurrencyCode>
</MarketData>
</Product>
</ListingInformation>
<LicenseInformation>
<App>
<IsActive>true</IsActive>
<IsTrial>true</IsTrial>
</App>
<Product ProductId="1">
<IsActive>true</IsActive>
</Product>
</LicenseInformation>
</CurrentApp>
<ListingInformation>
部分包含应用的一般信息以及可单独购买的其他功能和产品的信息。其中一些信息可以通过
CurrentApp
类(或模拟环境中的
CurrentAppSimulator
类)的相应属性访问,如
AppId
属性表示应用在 Windows 应用商店中的唯一 ID,
Link
属性表示应用在商店中的列表页面链接。该部分还包含应用在商店中的名称、年龄评级、当前市场、应用价格等信息,这些信息可以通过
CurrentApp
类(或模拟环境中的
CurrentAppSimulator
类)的
LoadListingInformationAsync
方法从 Windows 应用商店检索,该方法返回一个
ListingInformation
类的实例。
以下是显示部分列表信息的 C# 代码:
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
this.DisplayListingInformation();
this.DisplayLicenseInfo();
}
private async void DisplayListingInformation()
{
AppId.Text = String.Format("App ID: {0}", CurrentAppSimulator.AppId);
StoreLink.Text = String.Format("Store Link: {0}", CurrentAppSimulator.LinkUri);
try
{
ListingInformation listingInfo = await
CurrentAppSimulator.LoadListingInformationAsync();
AppName.Text = String.Format("App’s Name on the Store: {0}", listingInfo.Name);
}
catch (Exception ex)
{
AppName.Text = String.Format(
"Listing information unavailable. Exception: {0}", ex.Message);
}
}
为了在屏幕上显示应用列表信息,需要修改页面的 XAML 代码,添加三个
TextBlock
控件:
<StackPanel Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<TextBlock x:Name="AppId" FontSize="20" Margin="20, 5" Width="Auto" />
<TextBlock x:Name="StoreLink" FontSize="20" Margin="20, 5" Width="Auto" />
<TextBlock x:Name="AppName" FontSize="20" Margin="20, 5" Width="Auto" />
<TextBlock x:Name="LicenseState" FontSize="20" Margin="20, 5" Width="Auto" />
<TextBlock x:Name="LicenseRemainingDays" FontSize="20" Margin="20, 5"
Width="Auto" />
</StackPanel>
4. 使用自定义许可信息
为了在不同的许可选项下测试应用,可以编写自己的 XML 定义文件,并使用
ReloadSimulatorAsync
静态方法将其提供给
CurrentAppSimulator
对象。以下是自定义许可信息文件
timed - trial.xml
的示例:
<?xml version="1.0" encoding="utf-16"?>
<CurrentApp>
<ListingInformation>
<App>
<AppId>01234567-1234-1234-1234-0123456789AB</AppId>
<LinkUri>
http://apps.windows.microsoft.com/app/2B14D306-D8F8-4066-A45B-0FB3464C67F2
</LinkUri>
<CurrentMarket>en-US</CurrentMarket>
<AgeRating>5</AgeRating>
<MarketData xml:lang="en-us">
<Name>Basic Timed Trial</Name>
<Description>Basic Timed trial sample</Description>
<Price>0.99</Price>
<CurrencySymbol>$</CurrencySymbol>
</MarketData>
</App>
</ListingInformation>
<LicenseInformation>
<App>
<IsActive>true</IsActive>
<IsTrial>true</IsTrial>
<ExpirationDate>2014-06-19T09:00:00.00Z</ExpirationDate>
</App>
</LicenseInformation>
</CurrentApp>
要加载和显示自定义许可信息,需要修改之前的代码,具体如下:
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
await this.LoadCustomSimulator();
this.DisplayListingInformation();
this.DisplayLicenseInfo();
}
private async Task LoadCustomSimulator()
{
StorageFolder proxyDataFolder = await
Package.Current.InstalledLocation.GetFolderAsync("trial-configs");
StorageFile proxyFile = await proxyDataFolder.GetFileAsync("timed-trial.xml");
await CurrentAppSimulator.ReloadSimulatorAsync(proxyFile);
}
5. 购买应用
在应用中启用试用功能后,下一步是让用户能够购买应用的完整版本。
CurrentApp
(或
CurrentAppSimulator
)类的
RequestAppPurchaseAsync
静态方法可用于创建异步操作,使用户能够购买(或模拟购买,在
CurrentAppSimulator
对象的情况下)当前应用的完整许可。该方法接受一个布尔值作为参数,用于指示是否应返回表示购买收据的字符串。以下是使用
RequestAppPurchaseAsync
方法购买应用的代码:
private async void BuyButton_Click(object sender, RoutedEventArgs e)
{
try
{
await CurrentAppSimulator.RequestAppPurchaseAsync(false);
}
catch (Exception ex)
{
PurchaseErrorMessage.Text = String.Format("Unable to buy: {0}", ex.Message);
PurchaseErrorMessage.Visibility = Windows.UI.Xaml.Visibility.Visible;
}
}
在 XAML 页面中添加以下代码:
<Page
x:Class=" Demo.Chapter6.TimedTrial.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TimedTrialStep"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<StackPanel Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<TextBlock x:Name="AppId" FontSize="20" Margin="20, 5" Width="Auto" />
<TextBlock x:Name="StoreLink" FontSize="20" Margin="20, 5" Width="Auto" />
<TextBlock x:Name="AppName" FontSize="20" Margin="20, 5" Width="Auto" />
<TextBlock x:Name="LicenseState" FontSize="20" Margin="20, 5" Width="Auto" />
<TextBlock x:Name="LicenseRemainingDays" FontSize="20" Margin="20, 5"
Width="Auto" />
<Button x:Name="BuyButton" Click="BuyButton_Click" Content="Buy app" Width="300"
Height="50" Margin="20, 5" />
<TextBlock x:Name="PurchaseErrorMessage" FontSize="20" Margin="20, 5"
Width="Auto" Visibility="Collapsed" />
</StackPanel>
</Page>
当用户购买应用的完整版本后,需要更新许可信息以显示新状态。
LicenseInformation
类的
LicenseChanged
事件会在应用许可状态更改时触发。以下是处理该事件以更新屏幕上显示的许可状态的代码:
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
await this.LoadCustomSimulator();
this.DisplayListingInformation();
this.DisplayLicenseInfo();
CurrentAppSimulator.LicenseInformation.LicenseChanged +=
LicenseInformation_LicenseChanged;
}
private void LicenseInformation_LicenseChanged()
{
this.DisplayLicenseInfo();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
CurrentAppSimulator.LicenseInformation.LicenseChanged -=
LicenseInformation_LicenseChanged;
}
6. 不同类型试用的处理
6.1 限时试用
在限时试用中,
IsActive
属性用于判断试用期是否已过(或在极少数情况下,许可是否缺失或已被撤销)。如果该属性返回
false
,表示评估期已过,在最简单的情况下,应用应停止工作;如果返回
true
,表示评估期尚未结束,应用可以正常继续工作。同时,应检查
IsTrial
属性以验证用户是否已购买应用的完整版本或应用仍处于试用模式。若处于试用模式,应告知用户应用停止工作前剩余的天数。示例代码如下:
if (licenseInfo.IsActive)
{
if (licenseInfo.IsTrial)
{
// 应用仍处于试用模式。
// 记得告知用户应用停止工作前的剩余时间。
}
else
{
// 用户已购买应用的完整许可版本。
}
}
else
{
// 应用的许可已过期(或许可缺失或已被撤销)。
// 这意味着应用应停止工作。
// 记得邀请用户购买应用的完整版本。
}
6.2 基于功能的试用
在基于功能的试用中,由于没有需要检查的到期日期,因此需要修改之前的代码模式。在这种情况下,
IsActive
属性通常应返回
true
(除非出现问题,也需要处理这种情况)。在这种试用类型中,需要知道用户是否已购买应用的完整版本,以决定启用哪些功能。示例代码如下:
if (licenseInfo.IsActive)
{
if (licenseInfo.IsTrial)
{
// 应用处于试用模式。仅启用试用模式下可用的功能。
}
else
{
// 用户已购买应用的完整许可。现在可以启用所有功能。
}
}
else
{
// 出现问题:许可缺失或已被撤销
}
7. 错误处理
在应用中使用
CurrentApp
类时,调用任何访问 Windows 应用商店 API 的方法都可能引发异常。因此,对这些方法的调用应包装在
try/catch
块中,确保应用能够优雅地处理这些错误。
在本地环境中,可以使用
CurrentAppSimulator
类来确保代码至少覆盖了最常见的失败场景。有两种方法可以实现这一目标:
-
简单方法
:利用 Windows 应用商店对话框返回不同的错误代码。但此过程可能比较耗时,且不能用于自动化测试策略。
-
使用自定义 XML 定义
:在为
CurrentAppSimulator
对象提供自定义 XML 许可状态定义时,可以使用
<Simulation>
元素指定每个方法应返回的错误代码。
以下是修改后的
timed - trial.xml
文件示例(部分代码):
<?xml version="1.0" encoding="utf-16"?>
<CurrentApp>
<ListingInformation>
<App>
<AppId>01234567-1234-1234-1234-0123456789AB</AppId>
<LinkUri>
http://apps.windows.microsoft.com/app/2B14D306-D8F8-4066-A45B-0FB3464C67F2
</LinkUri>
<CurrentMarket>en-US</CurrentMarket>
<AgeRating>5</AgeRating>
<MarketData xml:lang="en-us">
<!-- 其他信息 -->
</MarketData>
</App>
</ListingInformation>
<!-- 其他部分 -->
</CurrentApp>
通过以上步骤和代码示例,可以在应用开发过程中有效地设计和实现试用功能,并处理各种可能的情况和错误。
应用解决方案部署中的试用功能设计与实现
8. 试用功能设计与实现流程总结
为了更清晰地展示整个试用功能设计与实现的过程,下面通过一个 mermaid 流程图来进行总结:
graph TD;
A[开始] --> B[应用内购买与发布准备];
B --> C[探索应用许可状态];
C --> D[获取许可信息属性];
D --> E{使用 CurrentApp 还是 CurrentAppSimulator};
E -- CurrentAppSimulator --> F[使用模拟环境测试];
E -- CurrentApp --> G[发布到应用商店后使用];
F --> H[显示模拟许可状态];
H --> I[添加 XAML 控件显示信息];
I --> J{是否使用自定义许可信息};
J -- 是 --> K[编写自定义 XML 文件并加载];
J -- 否 --> L[使用默认 WindowsStoreProxy.xml];
K --> M[加载和显示自定义许可信息];
L --> M;
M --> N[启用试用功能];
N --> O[提供购买完整版本功能];
O --> P[处理购买事件和更新许可信息];
P --> Q{试用类型};
Q -- 限时试用 --> R[处理限时试用逻辑];
Q -- 基于功能的试用 --> S[处理基于功能的试用逻辑];
R --> T[处理错误情况];
S --> T;
T --> U[结束];
G --> O;
这个流程图展示了从应用内购买准备到最终处理不同试用类型和错误情况的完整流程,帮助开发者更好地理解和实施试用功能。
9. 关键技术点分析
-
许可状态检查
:通过
LicenseInformation类的属性(如IsActive和IsTrial)来判断应用的许可状态,这是实现试用功能的基础。在不同的试用类型下,这些属性的含义和使用方式有所不同,需要开发者根据具体情况进行处理。 -
模拟环境测试
:
CurrentAppSimulator类提供了一个模拟环境,使得开发者可以在本地环境中测试应用的试用和购买功能,而无需与实际的 Windows 应用商店进行交互。这大大提高了开发效率,同时也方便了对各种错误情况的测试。 -
自定义许可信息
:通过编写自定义的 XML 文件并使用
ReloadSimulatorAsync方法,可以模拟不同的许可状态和场景,进一步增强了测试的灵活性。 -
错误处理
:在调用 Windows 应用商店 API 的方法时,使用
try/catch块来捕获并处理可能出现的异常,确保应用在遇到错误时能够优雅地处理,提供良好的用户体验。
10. 实际应用中的注意事项
-
提交应用前的替换
:在将应用提交到 Windows 应用商店之前,务必将
CurrentAppSimulator类替换为CurrentApp类,否则应用将无法通过认证过程。这是一个容易被忽略但非常重要的步骤。 -
XML 文件的影响范围
:任何对许可状态的修改只影响内存中的对象,不会改变提供给
CurrentAppSimulator对象的 XML 文件。这意味着每次启动应用时,原始 XML 文件的内容不会改变,开发者需要注意这一点。 - 用户提示 :在试用模式下,应及时、清晰地向用户告知试用期限或试用功能的限制,让用户了解应用的使用情况。例如,在限时试用中,告知用户剩余天数;在基于功能的试用中,明确指出哪些功能不可用。
11. 代码优化建议
-
代码复用
:在处理许可信息显示、购买事件等功能时,可以将一些通用的代码封装成方法,提高代码的复用性和可维护性。例如,可以将
DisplayLicenseInfo方法进一步封装,使其可以在不同的页面或场景中复用。 -
异步操作的优化
:虽然在当前的示例中,
async/await模式在某些方法中不是必需的,但在实际应用中,当涉及到与外部资源(如 Windows 应用商店 API)的交互时,异步操作可以避免阻塞 UI 线程,提高应用的响应性能。因此,建议在合适的地方使用异步操作。 - 错误信息的处理 :在捕获异常时,可以记录更详细的错误信息,以便在调试和维护过程中更容易定位问题。例如,可以将异常的堆栈跟踪信息记录到日志文件中。
12. 总结与展望
通过以上的介绍和示例代码,我们详细了解了在应用中设计和实现试用功能的方法,包括应用内购买的限制、许可状态的检查、模拟环境的测试、不同试用类型的处理以及错误处理等方面。在实际开发中,开发者可以根据自己的需求和应用的特点,灵活运用这些技术和方法,为用户提供更好的试用体验。
未来,随着应用市场的不断发展和用户需求的变化,试用功能可能会变得更加多样化和个性化。例如,可能会出现更多基于用户行为的试用策略,或者与社交网络、广告等相结合的试用模式。开发者需要不断关注这些趋势,及时调整和优化应用的试用功能,以适应市场的变化。
同时,随着技术的不断进步,Windows 应用商店 API 可能会不断更新和完善,提供更多的功能和更好的性能。开发者应及时关注这些更新,利用新的特性来提升应用的质量和竞争力。
总之,设计和实现一个良好的试用功能对于应用的推广和用户留存至关重要。通过合理运用本文介绍的技术和方法,开发者可以为应用的成功奠定坚实的基础。
超级会员免费看
8678

被折叠的 条评论
为什么被折叠?



