Skip to content

Commit

Permalink
feat: In app review on Android
Browse files Browse the repository at this point in the history
  • Loading branch information
morning4coffe-dev committed Sep 18, 2024
1 parent f9b0475 commit 760205a
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 17 deletions.
91 changes: 91 additions & 0 deletions src/AddIns/Uno.UI.GooglePlay/StoreContextExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Print;
using Uno.Foundation.Logging;
using Windows.Foundation.Metadata;
using Windows.Services.Store;
using Windows.Services.Store.Internal;
using Xamarin.Google.Android.Play.Core.Review;
using Xamarin.Google.Android.Play.Core.Review.Testing;
using Xamarin.Google.Android.Play.Core.Tasks;

namespace Uno.UI.GooglePlay;

internal class StoreContextExtension : IStoreContextExtension
{
public async Task<StoreRateAndReviewResult> RequestRateAndReviewAsync(CancellationToken token)
{
TaskCompletionSource<StoreRateAndReviewResult>? inAppRateTcs;

inAppRateTcs = new();

using var reviewManager = WinRTFeatureConfiguration.StoreContext.TestMode
? new FakeReviewManager(Application.Context)
: ReviewManagerFactory.Create(Application.Context);

using var request = reviewManager.RequestReviewFlow();

request.AddOnCompleteListener(new InAppReviewListener(reviewManager, inAppRateTcs));

return await inAppRateTcs.Task;
}

private class InAppReviewListener : Java.Lang.Object, IOnCompleteListener
{
private IReviewManager _reviewManager;
private TaskCompletionSource<StoreRateAndReviewResult>? _inAppRateTcs;
private Xamarin.Google.Android.Play.Core.Tasks.Task? _launchTask;
private bool _forceReturn;

public InAppReviewListener(IReviewManager reviewManager, TaskCompletionSource<StoreRateAndReviewResult>? inAppRateTcs)
{
_reviewManager = reviewManager;
_inAppRateTcs = inAppRateTcs;
}

public void OnComplete(Xamarin.Google.Android.Play.Core.Tasks.Task task)
{
var context = ContextHelper.Current;
var activity = (Activity)context;

if (!task.IsSuccessful)
{
_inAppRateTcs?.TrySetResult(new StoreRateAndReviewResult(StoreRateAndReviewStatus.Error));

_launchTask?.Dispose();

return;
}

try
{
var reviewInfo = (ReviewInfo?)task.GetResult(Java.Lang.Class.FromType(typeof(ReviewInfo)));

_forceReturn = true;
_launchTask = _reviewManager?.LaunchReviewFlow(activity, reviewInfo!);

_launchTask?.AddOnCompleteListener(this);
}
catch (Exception ex)
{
if (this.Log().IsEnabled(LogLevel.Error))
{
this.Log().LogError("Error", "There was an error launching in-app review. Please try again.");
}

_inAppRateTcs?.TrySetResult(new(StoreRateAndReviewStatus.Error));

System.Diagnostics.Debug.WriteLine($"Error message: {ex.Message}");
System.Diagnostics.Debug.WriteLine($"Stacktrace: {ex}");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,19 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Uno.UI\Uno.UI.netcoremobile.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="Xamarin.Google.Android.Play.Core" Version="1.10.3.14" />

<PackageReference Include="SkiaSharp.Skottie" />

<PackageReference Include="SkiaSharp.Views.Uno" Condition="'$(UNO_UWP_BUILD)'=='true'" />
<PackageReference Include="SkiaSharp.Views.Uno.WinUI" Condition="'$(UNO_UWP_BUILD)'!='true'" />

<!-- Explicitly included to remove all assets from Uno dependencies coming from SkiaSharp.Views.* -->
<PackageReference Include="Uno.UI" Version="4.4.5" ExcludeAssets="all" IncludeAssets="none" PrivateAssets="all" Condition="'$(UNO_UWP_BUILD)'=='true'"/>
<PackageReference Include="Uno.WinUI" Version="4.4.5" ExcludeAssets="all" IncludeAssets="none" PrivateAssets="all" Condition="'$(UNO_UWP_BUILD)'!='true'" />
<ProjectReference Include="..\..\Uno.Foundation.Logging\Uno.Foundation.Logging.csproj" />
<ProjectReference Include="..\..\Uno.UI\Uno.UI.netcoremobile.csproj" />
</ItemGroup>

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

<Target Name="_CleanupReferences" BeforeTargets="CoreCompile">
<!-- Required when building under VS to remove analyzer references coming from the Uno.UI/Uno.WinUI transitive references -->
<ItemGroup>
<Analyzer Remove="@(Analyzer)" Condition="'%(Analyzer.NugetPackageId)'=='Uno.UI'"/>
<Analyzer Remove="@(Analyzer)" Condition="'%(Analyzer.NugetPackageId)'=='Uno.WinUI'"/>
<Analyzer Remove="@(Analyzer)" Condition="'%(Analyzer.NugetPackageId)'=='Uno.UI'" />
<Analyzer Remove="@(Analyzer)" Condition="'%(Analyzer.NugetPackageId)'=='Uno.WinUI'" />
</ItemGroup>
</Target>

Expand Down
1 change: 1 addition & 0 deletions src/Uno.Foundation.Logging/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
[assembly: InternalsVisibleTo("Uno.UI.FluentTheme")]
[assembly: InternalsVisibleTo("Uno.UI.FluentTheme.v1")]
[assembly: InternalsVisibleTo("Uno.UI.FluentTheme.v2")]
[assembly: InternalsVisibleTo("Uno.UI.GooglePlay")]
[assembly: InternalsVisibleTo("Uno.UI.Lottie")]
[assembly: InternalsVisibleTo("Uno.UI.Svg")]
[assembly: InternalsVisibleTo("Uno.UI.Svg.Skia")]
Expand Down
10 changes: 10 additions & 0 deletions src/Uno.UWP/FeatureConfiguration/WinRTFeatureConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,14 @@ public static class ResourceLoader
/// </summary>
public static bool PreserveParsedResources { get; set; }
}

#if __ANDROID__
public static class StoreContext
{
/// <summary>
/// Set True to test Store Context APIs on Android. False by default.
/// </summary>
public static bool TestMode { get; set; }
}
#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ public bool CanSilentlyDownloadStorePackageUpdates
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");
}
#endif
#if __ANDROID__ || false || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false || false || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "IS_UNIT_TESTS", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public global::Windows.Foundation.IAsyncOperation<global::Windows.Services.Store.StoreRateAndReviewResult> RequestRateAndReviewAppAsync()
{
Expand Down
2 changes: 1 addition & 1 deletion src/Uno.UWP/Services/Store/StoreContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ private StoreContext()
/// store-related data for the current user.</returns>
public static StoreContext GetDefault() => _instance.Value;

#if __IOS__
#if __IOS__ || __ANDROID__
/// <summary>
/// Requests the user to rate and review the app. This method will
/// display the UI for the user to select a store rating and add
Expand Down

0 comments on commit 760205a

Please sign in to comment.