Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

requestReview does nothing on Android #127

Open
lukehutch opened this issue Jul 17, 2024 · 37 comments
Open

requestReview does nothing on Android #127

lukehutch opened this issue Jul 17, 2024 · 37 comments

Comments

@lukehutch
Copy link

requestReview does nothing on Android. Here are the logs:

I/InAppReviewPlugin(22895): cacheReviewInfo: Requesting review flow
I/PlayCore(22895): UID: [10195]  PID: [22895] ReviewService : Initiate binding to the service.
I/PlayCore(22895): UID: [10195]  PID: [22895] ReviewService : ServiceConnectionImpl.onServiceConnected(ComponentInfo{com.android.vending/com.google.android.finsky.inappreviewservice.InAppReviewService})
I/PlayCore(22895): UID: [10195]  PID: [22895] ReviewService : linkToDeath
I/PlayCore(22895): UID: [10195]  PID: [22895] ReviewService : Unbind from service.
I/PlayCore(22895): UID: [10195]  PID: [22895] OnRequestInstallCallback : onGetLaunchReviewFlowInfo
I/InAppReviewPlugin(22895): onComplete: Successfully requested review flow
I/InAppReviewPlugin(22895): onMethodCall: requestReview
I/InAppReviewPlugin(22895): requestReview: called
I/InAppReviewPlugin(22895): noContextOrActivity: called
I/InAppReviewPlugin(22895): launchReviewFlow: called
I/InAppReviewPlugin(22895): noContextOrActivity: called

After these logs are printed to the console, requestReview returns from the await without throwing an exception.

Flutter 3.23.0-0.1.pre • channel beta • https://github.com/flutter/flutter.git
Framework • revision 2feea7a407 (6 weeks ago) • 2024-06-06 10:19:10 +0700
Engine • revision bb10c54666
Tools • Dart 3.5.0 (build 3.5.0-180.3.beta) • DevTools 2.36.0
Android API 33

@HenrikH96
Copy link

I have a similar Issue. It opened once, and i think this is Intended by the operating System.
But it would be nice to get an Error/ Return Object to react to "requestReview" results.
Or at least the isAvailable function shouldn't return true if the popup is already called and not available anymore.

It's a bad UX when nothing happens on my Button press.

Any suggestions ?

@britannio
Copy link
Owner

requestReview does nothing on Android. Here are the logs:

I/InAppReviewPlugin(22895): cacheReviewInfo: Requesting review flow
I/PlayCore(22895): UID: [10195]  PID: [22895] ReviewService : Initiate binding to the service.
I/PlayCore(22895): UID: [10195]  PID: [22895] ReviewService : ServiceConnectionImpl.onServiceConnected(ComponentInfo{com.android.vending/com.google.android.finsky.inappreviewservice.InAppReviewService})
I/PlayCore(22895): UID: [10195]  PID: [22895] ReviewService : linkToDeath
I/PlayCore(22895): UID: [10195]  PID: [22895] ReviewService : Unbind from service.
I/PlayCore(22895): UID: [10195]  PID: [22895] OnRequestInstallCallback : onGetLaunchReviewFlowInfo
I/InAppReviewPlugin(22895): onComplete: Successfully requested review flow
I/InAppReviewPlugin(22895): onMethodCall: requestReview
I/InAppReviewPlugin(22895): requestReview: called
I/InAppReviewPlugin(22895): noContextOrActivity: called
I/InAppReviewPlugin(22895): launchReviewFlow: called
I/InAppReviewPlugin(22895): noContextOrActivity: called

After these logs are printed to the console, requestReview returns from the await without throwing an exception.

Flutter 3.23.0-0.1.pre • channel beta • https://github.com/flutter/flutter.git Framework • revision 2feea7a407 (6 weeks ago) • 2024-06-06 10:19:10 +0700 Engine • revision bb10c54666 Tools • Dart 3.5.0 (build 3.5.0-180.3.beta) • DevTools 2.36.0 Android API 33

Hey, did you see the testing guidelines? https://pub.dev/packages/in_app_review#testing-read-carefully

@lukehutch
Copy link
Author

Hey, did you see the testing guidelines? https://pub.dev/packages/in_app_review#testing-read-carefully

The docs appear to be incomplete. They basically imply that the submit button will be disabled if you don't have an app bundle uploaded to at least the "internal app sharing" track. However, that's not the behavior I am reporting: the dialog doesn't even pop up, and no error message is even reported to the console.

Yes, this might be caused by not having an app in production yet (I have several builds uploaded for testing). However, whatever the cause, in_app_review should report an error to the console at a bare minimum, and ideally also show an error message in a dialog, rather than failing silently.

@britannio
Copy link
Owner

  @override
  Future<void> requestReview() async {
    if (kDebugMode && _platform.isAndroid) {
      print( 'in_app_review must be tested with a build downloaded from the Play Store.');
    }
    return _channel.invokeMethod('requestReview');
  }

Would this suffice? Showing a dialog is fine until I get an issue saying "why is this dialog being shown in production".

@britannio
Copy link
Owner

Actually, based on https://stackoverflow.com/questions/37539949/detect-if-an-app-is-installed-from-play-store it is possible to detect if the app was installed via the Play Store or via any store.

@lukehutch
Copy link
Author

A console message is much better than nothing. Nothing should ever fail silently.

@britannio
Copy link
Owner

@lukehutch Do you get a log that looks like isAvailable: playStoreAndPlayServicesAvailable: <true/false> before the logs you posted?

@lukehutch
Copy link
Author

I didn't notice that in the logs, but on this device Play Services should be available.

(If you need me to test this, it will be a couple of days before I will be able to get to it.)

@rsillador
Copy link

Any updates on this? I got the same issue.

image

@lukehutch
Copy link
Author

lukehutch commented Aug 26, 2024

In case it helps anyone else, this is what I resorted to doing:

  final startTime = Stopwatch()..start();
  if (await inAppReview.isAvailable()) {
    try {
      await inAppReview.requestReview();
    } catch (e, st) {
      logError(
        message: 'Failed to request app review',
        error: e,
        stacktrace: st,
      );
    }
  }
  final elapsedMilliseconds = startTime.elapsedMilliseconds;
  if (elapsedMilliseconds > 300) {
    // If the above method did not return immediately, assume it
    // succeeded in opening the rating modal, and return
    return;
  }

  // Otherwise if the above method failed, try opening the store listing by URL
  try {
    // Use `url_launcher` rather than `openStoreListing`
    await launchUrl(Uri.parse(Platform.isAndroid
        ? 'https://play.google.com/store/apps/details?id=$androidPackageName'
        : 'https://apps.apple.com/us/app/click-social/id$appStoreId'));
  } catch (e, st) {
    logError(
      message: 'Failed to open app store listing',
      error: e,
      stacktrace: st,
    );
  }

I use launchUrl rather than openStoreListing because I had a report by one user that if openStoreListing is called, they get a version of the Play Store listing that does not allow them to rate the app:

#131

@nicolaikol
Copy link

nicolaikol commented Sep 6, 2024

final elapsedMilliseconds = startTime.elapsedMilliseconds;
if (elapsedMilliseconds > 300) {
// If the above method did not return immediately, assume it
// succeeded in opening the rating modal, and return
return;
}

I just tried your code on iOS simulator, and on iOS physical, and it returns immediately with 0 elapsed time. Does await even do anything on requestReview() ?

Edit: okay sometimes it's like 12 - 16 milliseconds, nowhere near the 300 mark

@lukehutch
Copy link
Author

lukehutch commented Sep 6, 2024

@nicolaikol I didn't test it on iOS, but I did read the source before and it looks like the method is supposed to block until it has a result from user interaction. I could be reading the code wrong though, or possibly the code is returning as soon as the dialogue is open, before the user has tapped on anything.

I picked the 300ms based only on human reaction time, not based on the actual method return time. My assumption was that if there wasn't enough time to pop up a dialogue and have the user tap on a button, then either the dialog must not have opened, or it must have opened and immediately closed without user intervention.

There could be a flaw in the logic here, I am open to other suggestions!

@nicolaikol
Copy link

nicolaikol commented Sep 8, 2024

There could be a flaw in the logic here, I am open to other suggestions!

I've tried a few approaches, but I can't find any way to detect the OS popup on iOS.
Therefore my approach is to have a conservative policy for when I ask the user and assume it will work whenever i call it...

if (await inAppReview.isAvailable()) {
    try {
      await inAppReview.requestReview();
      return;
    } catch (e, st) {
      logger.e(
        'Failed to request app review',
        error: e,
        stackTrace: st
      );
    }
  }

  // Otherwise if the above method failed, try opening the store listing by URL
  try {
    await LaunchReview.launch(
        writeReview: true, iOSAppId: iOSAppId, androidAppId: androidAppId);
  } catch (e, st) {
    logger.e(
      'Failed to open app store listing',
      error: e,
      stackTrace: st,
    );
  }

Maybe the package would actually work as expected if they use the new non-deprecated iOS api's, just a wild guess though...

@britannio
Copy link
Owner

Maybe the package would actually work as expected if they use the new non-deprecated iOS api's, just a wild guess though...

@nicolaikol PRs welcome :)

@Shkryabminer
Copy link

I have a version of app in Play Market, but await inAppReview.requestReview() doesnt show any thing in Open Testing since the first dialog h've been shown.

@AtamyratBabayev
Copy link

Hi! Is this lib well tested on devices with Android 14.0? Nothing happening on invoking requestReview method. Got the same logs as @lukehutch mentioned.

@justerror
Copy link

Same. Not working with Android 14. Any workarounds?

@crispy-riccardo
Copy link

Still facing the same error with Android 15. The app is in production and while on internal testing the popup is never shown. inAppReview.isAvailable() returns true.

@VB10
Copy link

VB10 commented Nov 8, 2024

I can see the dialog when I upload internal sharing, but when I try to upload production, internal tests, etc., it does not work.

@rhaynel2024
Copy link

Is there any updates? million of people is dying because of this bug.

@justerror
Copy link

Is the problem fixed in the latest version 2.0.10?

@britannio
Copy link
Owner

Is the problem fixed in the latest version 2.0.10?

It's hard to discern if there's a real issue or if people skipped the testing documentation that states the quirks of the underlying API (it generally won't work if you installed your app via flutter run or flutter run --release. https://pub.dev/packages/in_app_review#testing-read-carefully

The native Java code is simple and nobody has pointed out an issue with it.

@britannio
Copy link
Owner

The latest release (2.0.10) fixed a crash caused by the underlying API but didn't change anything else on Android.
https://developer.android.com/reference/com/google/android/play/core/release-notes-in_app_reviews

@crispy-riccardo
Copy link

It's hard to discern if there's a real issue or if people skipped the testing documentation that states the quirks of the underlying API (it generally won't work if you installed your app via flutter run or flutter run --release. https://pub.dev/packages/in_app_review#testing-read-carefully

The native Java code is simple and nobody has pointed out an issue with it.

For me, the problem appears when I install the app from the PlayStore (production channel). I can see the logs (sent via file upload, not console) that inAppReview.isAvailable() returns true and inAppReview.requestReview() is called;

This is my code

final InAppReview inAppReview = InAppReview.instance;
if (await inAppReview.isAvailable()) {
  logger.d('[FEEDBACK] InAppReview available', printToFile: true);
  try {
    return inAppReview.requestReview();
  } catch (e, stackTrace) {
    logger.e('[FEEDBACK] Error requesting review: $e', stackTrace: stackTrace);
  }
} else {
  logger.d('[FEEDBACK] InAppReview not available', printToFile: true);
}

all I see in the logs is this, meaning requestReview(); is called

[FEEDBACK] InAppReview available

@britannio
Copy link
Owner

It's hard to discern if there's a real issue or if people skipped the testing documentation that states the quirks of the underlying API (it generally won't work if you installed your app via flutter run or flutter run --release. https://pub.dev/packages/in_app_review#testing-read-carefully
The native Java code is simple and nobody has pointed out an issue with it.

For me, the problem appears when I install the app from the PlayStore (production channel). I can see the logs (sent via file upload, not console) that inAppReview.isAvailable() returns true and inAppReview.requestReview() is called;

This is my code

final InAppReview inAppReview = InAppReview.instance;
if (await inAppReview.isAvailable()) {
  logger.d('[FEEDBACK] InAppReview available', printToFile: true);
  try {
    return inAppReview.requestReview();
  } catch (e, stackTrace) {
    logger.e('[FEEDBACK] Error requesting review: $e', stackTrace: stackTrace);
  }
} else {
  logger.d('[FEEDBACK] InAppReview not available', printToFile: true);
}

all I see in the logs is this, meaning requestReview(); is called

[FEEDBACK] InAppReview available

Have you tried using internal app sharing or an internal test track? The production track is not recommended for testing.

See this troubleshooting table: https://developer.android.com/guide/playcore/in-app-review/test#troubleshooting

@justerror
Copy link

justerror commented Nov 25, 2024

This issue reproduced only in production channel for latest Android.
Also, we can see it by the number of ratings from Android 14 - significantly less than older Android or iOS.
It perfectly works in internal testing, so it's not caused by inaccurate testing.

If someone has already updated lib to the latest version (2.0.10), please let us know about possible fixing this issue.

@britannio
Copy link
Owner

This issue reproduced only in production channel for latest Android. Also, we can see it by the number of ratings from Android 14 - significantly less than older Android or iOS. It perfectly works in internal testing, so it's not caused by inaccurate testing.

If someone has already updated lib to the latest version (2.0.10), please let us know about possible fixing this issue.

If it works in internal testing then it's out of my hands and almost certainly works as Google intended. I've been testing on Android 14 and now Android 15 with my Pixel 7 Pro.

@DanielMartini
Copy link

DanielMartini commented Nov 25, 2024

This issue reproduced only in production channel for latest Android. Also, we can see it by the number of ratings from Android 14 - significantly less than older Android or iOS. It perfectly works in internal testing, so it's not caused by inaccurate testing.

If someone has already updated lib to the latest version (2.0.10), please let us know about possible fixing this issue.

Tested in production with 2.0.10 version in my google pixel 8 pro, and nothing happens.

Edit: Same code was working properly few weeks ago on my flutter app

@lukehutch
Copy link
Author

If it works in internal testing then it's out of my hands and almost certainly works as Google intended. I've been testing on Android 14 and now Android 15 with my Pixel 7 Pro.

You're saying if it works in internal testing but it's broken in production, then it's "out of your hands"? Huh?

(I can't confirm if it work in internal testing, but I can confirm that it's broken in production.)

@britannio
Copy link
Owner

If it works in internal testing then it's out of my hands and almost certainly works as Google intended. I've been testing on Android 14 and now Android 15 with my Pixel 7 Pro.

You're saying if it works in internal testing but it's broken in production, then it's "out of your hands"? Huh?

(I can't confirm if it work in internal testing, but I can confirm that it's broken in production.)

I'm saying that if it works in internal testing then I'm confident that it works in production. If there is evidence that contradicts this then I don't suspect that it would be an issue with this plugin but rather an issue to bring to the Android team directly if a compelling case can be built.

Send me a production link to your app with instructions to trigger the popup and I'll send a screenshot of it hopefully working.

To my knowledge, the plugin isn't flat-out broken on all devices so if we can find some reproducibility criteria then progress can be made.

Official docs for reference: https://developer.android.com/guide/playcore/in-app-review/test

@lukehutch
Copy link
Author

I had to work around this in my production app, by using another method to take the user to the app listing. Somebody else may be able to direct you to their app.

@DanielMartini
Copy link

Someone tested it already with the newest flutter version to see if it works? (3.27.0)

@britannio
Copy link
Owner

Someone tested it already with the newest flutter version to see if it works? (3.27.0)

Do you have any evidence of it not working? Otherwise it should be fine.

@crispy-riccardo
Copy link

I tested via PlayStore's internal sharing and the popup appeared without any problem following my logic. When it was published i downloaded it from playstore with a different android phone (pixel 7), with different google account (not linked to my developer account) that has never reviewed the app but the popup did't show. I have a file logger in my app and all the logs that I put in place in order to see if my logic worked showed me that inAppReview.requestReview(); was called but it didn't show any popup asking for review.

@DanielMartini
Copy link

Someone tested it already with the newest flutter version to see if it works? (3.27.0)

Do you have any evidence of it not working? Otherwise it should be fine.

Just as people commented before, the review popup appears on test version downloaded through the store, at least when I tried months ago, but in production is not appearing even though inAppReview.requestReview() is called and any review has been submitted before 😕

@britannio
Copy link
Owner

I tested via PlayStore's internal sharing and the popup appeared without any problem following my logic. When it was published i downloaded it from playstore with a different android phone (pixel 7), with different google account (not linked to my developer account) that has never reviewed the app but the popup did't show. I have a file logger in my app and all the logs that I put in place in order to see if my logic worked showed me that inAppReview.requestReview(); was called but it didn't show any popup asking for review.

Can you share the app along with the instructions to trigger the popup?

@DanielMartini
Copy link

I can confirm that is working in another mobile and Google account not related with the development one.

Sorry for the inconvenience and Merry Xmas!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests