Skip to content

Commit 760205a

Browse files
feat: In app review on Android
1 parent f9b0475 commit 760205a

File tree

6 files changed

+109
-17
lines changed

6 files changed

+109
-17
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using Android.App;
8+
using Android.Content;
9+
using Android.Content.PM;
10+
using Android.OS;
11+
using Android.Print;
12+
using Uno.Foundation.Logging;
13+
using Windows.Foundation.Metadata;
14+
using Windows.Services.Store;
15+
using Windows.Services.Store.Internal;
16+
using Xamarin.Google.Android.Play.Core.Review;
17+
using Xamarin.Google.Android.Play.Core.Review.Testing;
18+
using Xamarin.Google.Android.Play.Core.Tasks;
19+
20+
namespace Uno.UI.GooglePlay;
21+
22+
internal class StoreContextExtension : IStoreContextExtension
23+
{
24+
public async Task<StoreRateAndReviewResult> RequestRateAndReviewAsync(CancellationToken token)
25+
{
26+
TaskCompletionSource<StoreRateAndReviewResult>? inAppRateTcs;
27+
28+
inAppRateTcs = new();
29+
30+
using var reviewManager = WinRTFeatureConfiguration.StoreContext.TestMode
31+
? new FakeReviewManager(Application.Context)
32+
: ReviewManagerFactory.Create(Application.Context);
33+
34+
using var request = reviewManager.RequestReviewFlow();
35+
36+
request.AddOnCompleteListener(new InAppReviewListener(reviewManager, inAppRateTcs));
37+
38+
return await inAppRateTcs.Task;
39+
}
40+
41+
private class InAppReviewListener : Java.Lang.Object, IOnCompleteListener
42+
{
43+
private IReviewManager _reviewManager;
44+
private TaskCompletionSource<StoreRateAndReviewResult>? _inAppRateTcs;
45+
private Xamarin.Google.Android.Play.Core.Tasks.Task? _launchTask;
46+
private bool _forceReturn;
47+
48+
public InAppReviewListener(IReviewManager reviewManager, TaskCompletionSource<StoreRateAndReviewResult>? inAppRateTcs)
49+
{
50+
_reviewManager = reviewManager;
51+
_inAppRateTcs = inAppRateTcs;
52+
}
53+
54+
public void OnComplete(Xamarin.Google.Android.Play.Core.Tasks.Task task)
55+
{
56+
var context = ContextHelper.Current;
57+
var activity = (Activity)context;
58+
59+
if (!task.IsSuccessful)
60+
{
61+
_inAppRateTcs?.TrySetResult(new StoreRateAndReviewResult(StoreRateAndReviewStatus.Error));
62+
63+
_launchTask?.Dispose();
64+
65+
return;
66+
}
67+
68+
try
69+
{
70+
var reviewInfo = (ReviewInfo?)task.GetResult(Java.Lang.Class.FromType(typeof(ReviewInfo)));
71+
72+
_forceReturn = true;
73+
_launchTask = _reviewManager?.LaunchReviewFlow(activity, reviewInfo!);
74+
75+
_launchTask?.AddOnCompleteListener(this);
76+
}
77+
catch (Exception ex)
78+
{
79+
if (this.Log().IsEnabled(LogLevel.Error))
80+
{
81+
this.Log().LogError("Error", "There was an error launching in-app review. Please try again.");
82+
}
83+
84+
_inAppRateTcs?.TrySetResult(new(StoreRateAndReviewStatus.Error));
85+
86+
System.Diagnostics.Debug.WriteLine($"Error message: {ex.Message}");
87+
System.Diagnostics.Debug.WriteLine($"Stacktrace: {ex}");
88+
}
89+
}
90+
}
91+
}

src/AddIns/Uno.UI.GooglePlay/Uno.UI.GooglePlay.netcoremobile.csproj

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,29 +28,19 @@
2828
</ItemGroup>
2929

3030
<ItemGroup>
31-
<ProjectReference Include="..\..\Uno.UI\Uno.UI.netcoremobile.csproj" />
32-
</ItemGroup>
33-
34-
<ItemGroup>
35-
<PackageReference Include="Newtonsoft.Json" />
31+
<PackageReference Include="Xamarin.Google.Android.Play.Core" Version="1.10.3.14" />
3632

37-
<PackageReference Include="SkiaSharp.Skottie" />
38-
39-
<PackageReference Include="SkiaSharp.Views.Uno" Condition="'$(UNO_UWP_BUILD)'=='true'" />
40-
<PackageReference Include="SkiaSharp.Views.Uno.WinUI" Condition="'$(UNO_UWP_BUILD)'!='true'" />
41-
42-
<!-- Explicitly included to remove all assets from Uno dependencies coming from SkiaSharp.Views.* -->
43-
<PackageReference Include="Uno.UI" Version="4.4.5" ExcludeAssets="all" IncludeAssets="none" PrivateAssets="all" Condition="'$(UNO_UWP_BUILD)'=='true'"/>
44-
<PackageReference Include="Uno.WinUI" Version="4.4.5" ExcludeAssets="all" IncludeAssets="none" PrivateAssets="all" Condition="'$(UNO_UWP_BUILD)'!='true'" />
33+
<ProjectReference Include="..\..\Uno.Foundation.Logging\Uno.Foundation.Logging.csproj" />
34+
<ProjectReference Include="..\..\Uno.UI\Uno.UI.netcoremobile.csproj" />
4535
</ItemGroup>
4636

4737
<Import Project="..\..\SourceGenerators\Uno.UI.SourceGenerators\Content\Uno.UI.SourceGenerators.props" />
4838

4939
<Target Name="_CleanupReferences" BeforeTargets="CoreCompile">
5040
<!-- Required when building under VS to remove analyzer references coming from the Uno.UI/Uno.WinUI transitive references -->
5141
<ItemGroup>
52-
<Analyzer Remove="@(Analyzer)" Condition="'%(Analyzer.NugetPackageId)'=='Uno.UI'"/>
53-
<Analyzer Remove="@(Analyzer)" Condition="'%(Analyzer.NugetPackageId)'=='Uno.WinUI'"/>
42+
<Analyzer Remove="@(Analyzer)" Condition="'%(Analyzer.NugetPackageId)'=='Uno.UI'" />
43+
<Analyzer Remove="@(Analyzer)" Condition="'%(Analyzer.NugetPackageId)'=='Uno.WinUI'" />
5444
</ItemGroup>
5545
</Target>
5646

src/Uno.Foundation.Logging/AssemblyInfo.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
[assembly: InternalsVisibleTo("Uno.UI.FluentTheme")]
1818
[assembly: InternalsVisibleTo("Uno.UI.FluentTheme.v1")]
1919
[assembly: InternalsVisibleTo("Uno.UI.FluentTheme.v2")]
20+
[assembly: InternalsVisibleTo("Uno.UI.GooglePlay")]
2021
[assembly: InternalsVisibleTo("Uno.UI.Lottie")]
2122
[assembly: InternalsVisibleTo("Uno.UI.Svg")]
2223
[assembly: InternalsVisibleTo("Uno.UI.Svg.Skia")]

src/Uno.UWP/FeatureConfiguration/WinRTFeatureConfiguration.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,14 @@ public static class ResourceLoader
3535
/// </summary>
3636
public static bool PreserveParsedResources { get; set; }
3737
}
38+
39+
#if __ANDROID__
40+
public static class StoreContext
41+
{
42+
/// <summary>
43+
/// Set True to test Store Context APIs on Android. False by default.
44+
/// </summary>
45+
public static bool TestMode { get; set; }
46+
}
47+
#endif
3848
}

src/Uno.UWP/Generated/3.0.0.0/Windows.Services.Store/StoreContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ public bool CanSilentlyDownloadStorePackageUpdates
256256
throw new global::System.NotImplementedException("The member IAsyncOperation<StoreUninstallStorePackageResult> StoreContext.UninstallStorePackageByStoreIdAsync(string storeId) is not implemented. For more information, visit https://aka.platform.uno/notimplemented#m=IAsyncOperation%3CStoreUninstallStorePackageResult%3E%20StoreContext.UninstallStorePackageByStoreIdAsync%28string%20storeId%29");
257257
}
258258
#endif
259-
#if __ANDROID__ || false || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
259+
#if false || false || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
260260
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "IS_UNIT_TESTS", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
261261
public global::Windows.Foundation.IAsyncOperation<global::Windows.Services.Store.StoreRateAndReviewResult> RequestRateAndReviewAppAsync()
262262
{

src/Uno.UWP/Services/Store/StoreContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ private StoreContext()
2323
/// store-related data for the current user.</returns>
2424
public static StoreContext GetDefault() => _instance.Value;
2525

26-
#if __IOS__
26+
#if __IOS__ || __ANDROID__
2727
/// <summary>
2828
/// Requests the user to rate and review the app. This method will
2929
/// display the UI for the user to select a store rating and add

0 commit comments

Comments
 (0)