jamesmontemagno / StoreReviewPlugin

Request app store reviews across Xamarin and Windows applications
MIT License
184 stars 24 forks source link

User not prompted for review on MAUI WinUI app #49

Closed BurkusCat closed 5 months ago

BurkusCat commented 8 months ago

Bug

Version Number of Plugin: 6.0.0 Device Tested On: Windows 11 22H2 Simulator Tested On: N/A

Expected Behavior

The user is prompted to review the app

Actual Behavior

In Debug and Release mode (and when downloaded from the store), no review dialog shows.

Steps to reproduce the Behavior

#if DEBUG
        await storeReview.RequestReview(true);
#else
        await storeReview.RequestReview(false);
#endif
jamesmontemagno commented 8 months ago

Hmmmm...

Looks like they have improved the code a bit, I will give it an update: https://learn.microsoft.com/en-us/windows/uwp/monetize/request-ratings-and-reviews#show-a-rating-and-review-dialog-in-your-app

BlueRaja commented 6 months ago

Any update on this? Xamarin support ends next week, so everyone is being forced to update to MAUI. Is this plugin dead?

jamesmontemagno commented 6 months ago

can you try 6.1.0-beta. i re-implemented it

BurkusCat commented 5 months ago

Thanks @jamesmontemagno for writing a new implementation

Immediately after updating the package, and trying it with my app I get this error:

Exception thrown: 'System.Runtime.InteropServices.COMException' in WinRT.Runtime.dll
WinRT information: This function must be called from a UI thread

Running it on the UI thread using either of the below options does not resolve the issue:

        await MainThread.InvokeOnMainThreadAsync(async () => await storeReview.RequestReview(true));
        MainThread.BeginInvokeOnMainThread(() => storeReview.RequestReview(true));

The review logic is being called from a service that decides when to prompt the user (as opposed to being activated on a button press).

jamesmontemagno commented 5 months ago

Hmmm it must be invoked on the UI Thread that is for sure.

These are the 2 lines of code that you must call from Windows, try to conditionally compile them and invoke with the dispatcher:

  var context = StoreContext.GetDefault();
 var result = await context.RequestRateAndReviewAppAsync();
jamesmontemagno commented 5 months ago

See: https://learn.microsoft.com/en-us/uwp/api/windows.services.store.storecontext.requestrateandreviewappasync?view=winrt-22621 it "should jus work"

I wonder if I have to do 👍

var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(windowObject);
// Initialize the dialog using wrapper funcion for IInitializeWithWindow
WinRT.Interop.InitializeWithWindow.Initialize(context, hwnd); 
jamesmontemagno commented 5 months ago

Alright in 6.1.1-beta try this:

#if WINDOWS  
var hwnd = ((MauiWinUIWindow)App.Current.Windows[0].Handler.PlatformView).WindowHandle;  
StoreReviewImplementation.WindowObject = hwnd;
#endif  

then call it on UI thread

BurkusCat commented 5 months ago
  1. This didn't work ❌:
#if WINDOWS
        Application.Current.MainPage.Dispatcher.Dispatch(async () =>
        {
            var context = StoreContext.GetDefault();
            var result = await context.RequestRateAndReviewAppAsync();
        });
#endif
  1. Works with window handle ✅:

    #if WINDOWS
        Application.Current.MainPage.Dispatcher.Dispatch(async () =>
        {
            var context = StoreContext.GetDefault();
    
            var hwnd = ((MauiWinUIWindow)App.Current.Windows[0].Handler.PlatformView).WindowHandle;
            WinRT.Interop.InitializeWithWindow.Initialize(context, hwnd);
    
            var result = await context.RequestRateAndReviewAppAsync();
        });
    #endif
  2. Works without dispatcher (it appears it is not necessary)✅:

    #if WINDOWS
        var context = StoreContext.GetDefault();
    
        var hwnd = ((MauiWinUIWindow)App.Current.Windows[0].Handler.PlatformView).WindowHandle;
        WinRT.Interop.InitializeWithWindow.Initialize(context, hwnd);
    
        var result = await context.RequestRateAndReviewAppAsync();
    #endif

image

The 6.1.1-beta package is probably still processing so I will try your latest comment with it when its ready.

jamesmontemagno commented 5 months ago

Perfect! yeah with my changes it should work as it is the same code you have basically :)

Thanks for checking this, i appreciate it.

BurkusCat commented 5 months ago

Unfortunately, trying out 6.1.1-beta with the following code:

#if WINDOWS
        var hwnd = ((MauiWinUIWindow)App.Current.Windows[0].Handler.PlatformView).WindowHandle;
        StoreReviewImplementation.WindowObject = hwnd;
        await storeReview.RequestReview(true);
#endif  

I get these exceptions:

Exception thrown: 'System.InvalidOperationException' in WinRT.Runtime.dll
Exception thrown: 'System.TypeInitializationException' in WinRT.Runtime.dll
Exception thrown: 'System.Reflection.TargetInvocationException' in WinRT.Runtime.dll
Exception thrown: 'System.Reflection.TargetInvocationException' in WinRT.Runtime.dll

image

I've took a look at your branch it looks like what I actually need to be doing is passing the Window object:

#if WINDOWS
        var windowObject = (MauiWinUIWindow)App.Current.Windows[0].Handler.PlatformView;
        StoreReviewImplementation.WindowObject = windowObject;
        await storeReview.RequestReview(true);
#endif  

This works well 👍 Thank you for making these changes :)

jamesmontemagno commented 5 months ago

Oh perfect! Yeah i think having folks pass me the window will make the most sense. I think i will null it out after as well so it doesn't hang on to stuff.

I will change it to Window