new_version icon indicating copy to clipboard operation
new_version copied to clipboard

Play store changes => StateError: Bad state: No element

Open peterhijma opened this issue 2 years ago • 37 comments

Google Play store looks very different since yesterday or today?

I've got some error messages popping up now.

StateError: Bad state: No element
  File "list.dart", line 167, in ListMixin.firstWhere
  File "new_version.dart", line 157, in NewVersion._getAndroidStoreVersion
  File "<asynchronous suspension>"
  File "new_version.dart", line 94, in NewVersion.showAlertIfNecessary

So I think changes are necessary. You can find the version of the app in a modal @ "About this app ->"

peterhijma avatar May 20 '22 13:05 peterhijma

Yes looks like it, thanks for reporting. This will probably break the plugin until I determine the new HTML elements.

timtraversy avatar May 20 '22 13:05 timtraversy

Looks like they are rolling it out gradually? Right now I see the old play store in my browser again.

peterhijma avatar May 21 '22 09:05 peterhijma

When is the next update for this package? My users are facing stuck issue because of this error.

yenyichau avatar May 27 '22 05:05 yenyichau

Hi, any updates regarding this issue? Didn't even know about the store change since said breaking changes haven't reflected in my area till like yesterday/today

JaviCore avatar May 27 '22 05:05 JaviCore

When can I get another update for this package?

mrsoehtet avatar May 27 '22 05:05 mrsoehtet

Dear author let us know whether this issue is going to fix or not. If not then we will drop this package or let us know the estimation time to fix. thousands of devices are stuck in launcher screen due to this error.

angadiumakant avatar May 27 '22 06:05 angadiumakant

Dear author let us know whether this issue is going to fix or not. If not then we will drop this package or let us know the estimation time to fix. thousands of devices are stuck in launcher screen due to this error.

Agreed. I am waiting the fix too. Please let us know ASAP when you fixed.

ahmetberber avatar May 27 '22 06:05 ahmetberber

My client thought I'm the one who cause the issue. I've removed the plugin and upload to AppStore & PlayStore. If the problem fix I I will use It back.

yenyichau avatar May 27 '22 06:05 yenyichau

I can confirm I'm experiencing the same problem here as everyone.

nebiyuelias1 avatar May 27 '22 06:05 nebiyuelias1

Same here. Dear Author please do let us know ASAP about this fix. Is there an alternative to this package if this won't be fixed anytime soon?

shabeenabarde avatar May 27 '22 08:05 shabeenabarde

same issue i faced now. please find the solution by author. plz client is waiting this Error is :

[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: Bad state: No element E/flutter ( 8554): #0 ListMixin.firstWhere (dart:collection/list.dart:167:5) E/flutter ( 8554): #1 NewVersion._getAndroidStoreVersion (package:new_version/new_version.dart:153:51) E/flutter ( 8554): E/flutter ( 8554): #2 SplashScreenPageState.checkAppUpdate (package:{pagename}.dart:125:41) E/flutter ( 8554):

SamarthSerpentCS avatar May 27 '22 08:05 SamarthSerpentCS

@timtraversy So apparently the store changed for more users. Any idea how to proceed?

I looked a bit into it myself, but getting the version from the HTML page itself seems more difficult because it doesn't appear in the source code on a page load anymore. It's all javascript-driven it seems.

Also: what if they decide to change a class name anytime soon again? Is there is more robust option to get the latest version of an app?

peterhijma avatar May 27 '22 09:05 peterhijma

@peterhijma From now on, remote configuration needs to be added. But when app is uploaded to Android, you have to do it in Firebase. so this is not proper solution. please find what class is used by javascript? so this is easily to find this. whats version is used in latest playstore.

final additionalInfoElements = document.getElementsByClassName('hAyfc');

This class is not found. beacuse google has changed design of play store.

SamarthSerpentCS avatar May 27 '22 10:05 SamarthSerpentCS

Hi. is there going to be a fix for this anytime soon?

shabeenabarde avatar May 27 '22 15:05 shabeenabarde

Unfortunately, there is not an easy fix for this. The new Play Store listing design does not include the app version number. For example: https://play.google.com/store/apps/details?id=com.google.android.apps.cloudconsole

There may be some other site where the version is listed, but someone will have to find it.

timtraversy avatar May 27 '22 17:05 timtraversy

actually the designer has changed a little I can't find the app version

Rodrigossff91 avatar May 27 '22 17:05 Rodrigossff91

In section „about this app“ is the version. Does this help?

sbergmair avatar May 27 '22 18:05 sbergmair

Good catch. That's closer, but that HTML element is only shown after a Javascript function is triggered, so we wouldn't be able to scrape it with a simple HTTP request as we do now.

It looks like the version info is pre-fetched though, and hidden in a huge block of in-line JS. So there might be a way to scrape out of there. But who knows if the format they return it in will be consistent.

timtraversy avatar May 27 '22 19:05 timtraversy

https://pub.dev/packages/webdriver is a possibility.

Right now, I'm leaning towards turning off Android support and releasing a version without it. But I'll give it another day to see if anything comes up.

timtraversy avatar May 27 '22 19:05 timtraversy

If anyone is up for a challenge:

  1. Go to random app with no reviews - https://play.google.com/store/apps/details?id=com.aakenya.testapp
  2. Look at page source - view-source:https://play.google.com/store/apps/details?id=com.aakenya.testapp
  3. CTRL-F for the version number - currently 1.0.14
  4. See if there's any possible way to extract that value from that blob of js/json

That's probably the only way.

timtraversy avatar May 27 '22 20:05 timtraversy

JavaScript Code

import { JSOM } from 'jsdom'; 
  import axios from 'axios';

  const res = await axios('https://play.google.com/store/apps/details?id=com.yourapp');
  const dom = new JSDOM(res.data);
  const scripts = Array.from(dom.window.document.querySelectorAll('script'));
  const script = scripts.find(s => s.textContent && s.textContent.includes('/store/apps/developer'));
  const matches = script.textContent.match(versionStringRegex);
  const match = matches[0];
  const version = match.replace(/"/g, '');

  console.log(version); // '1.2.345'

@timtraversy can u check it out ?..

Java code

  class AppVersionParser {


  suspend fun versionForIdentifier(bundleID: String): String? {
   val userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_3_1) AppleWebKit/605.1.15 (KHTML, like Gecko) " +
    "Version/15.3 Safari/605.1.15"

  val document: Document

      try {
             document = Jsoup.connect("https://play.google.com/store/apps/details?id=$bundleID&hl=en")
        .timeout(5000)
        .userAgent(userAgent)
        .referrer("https://www.google.com")
        .get()
         } catch (e: Exception) {
    logger.error("Failed to get Google Play info for $bundleID\n\t${e.toStandardString()}")
    return null
         }

         return parseDocument(document)
     }

     fun parseDocument(document: Document): String? {
         val HTML = document.toString()
         val policyMarker = "" // INSERT YOUR PRIVACY POLICY URL
         val policyUrlIndex = HTML.lastIndexOf(policyMarker)
         val versionStart = HTML.indexOf("\"", startIndex = policyUrlIndex + policyMarker.length + 1) + 1 // "
         val versionEnd = HTML.indexOf("\"", startIndex = versionStart + 1)
         return HTML.substring(startIndex = versionStart, endIndex = versionEnd)
     }
     }`

prakasharyaman avatar May 28 '22 02:05 prakasharyaman

For me, some changes in _getAndroidStoreVersion worked.

Future<VersionStatus?> _getAndroidStoreVersion(
      PackageInfo packageInfo) async {
    final id = androidId ?? packageInfo.packageName;
    final uri =
        Uri.https("play.google.com", "/store/apps/details", {"id": "$id"});
    final response = await http.get(uri);
    if (response.statusCode != 200) {
      debugPrint('Can\'t find an app in the Play Store with the id: $id');
      return null;
    }
    final document = parse(response.body);

    String storeVersion = '0.0.0';
    String? releaseNotes;

    final additionalInfoElements = document.getElementsByClassName('hAyfc');
    if (additionalInfoElements.isNotEmpty) {
      final versionElement = additionalInfoElements.firstWhere(
            (elm) => elm.querySelector('.BgcNfc')!.text == 'Current Version',
      );
      storeVersion = versionElement.querySelector('.htlgb')!.text;

      final sectionElements = document.getElementsByClassName('W4P4ne');
      final releaseNotesElement = sectionElements.firstWhereOrNull(
            (elm) => elm.querySelector('.wSaTQd')!.text == 'What\'s New',
      );
      releaseNotes = releaseNotesElement
          ?.querySelector('.PHBdkd')
          ?.querySelector('.DWPxHb')
          ?.text;
    } else {
      final scriptElements = document.getElementsByTagName('script');
      final infoScriptElement = scriptElements.firstWhere(
            (elm) => elm.text.contains('key: \'ds:4\''),
      );

      final param = infoScriptElement.text.substring(20, infoScriptElement.text.length - 2)
          .replaceAll('key:', '"key":')
          .replaceAll('hash:', '"hash":')
          .replaceAll('data:', '"data":')
          .replaceAll('sideChannel:', '"sideChannel":')
          .replaceAll('\'', '"')
          .replaceAll('owners\"', 'owners');
      final parsed = json.decode(param);
      final data =  parsed['data'];

      storeVersion = data[1][2][140][0][0][0];
      releaseNotes = data[1][2][144][1][1];
    }

    return VersionStatus._(
      localVersion: _getCleanVersion(packageInfo.version),
      storeVersion: _getCleanVersion(forceAppVersion ?? storeVersion),
      appStoreLink: uri.toString(),
      releaseNotes: releaseNotes,
    );
  }

Still not sure if play store HTML will be consistent or not but it worked for now.

annkitpanwar avatar May 28 '22 08:05 annkitpanwar

I'm getting the same error is there any solution because user can't visit to my application it stuck on the splash screen and my application is live Anaaj issue

Sapnajain01 avatar May 30 '22 06:05 Sapnajain01

I'm getting the same error is there any solution because user can't visit to my application it stuck on the splash screen and my application is live Anaaj issue

same here

kldawad avatar May 30 '22 08:05 kldawad

To those this is breaking: you will have to release a new version of your apps to fix this issue. I would recommend just doing that now, and removing the calls to this plugin. This was an unforseen change in the Play Console, we're working on a fix.

timtraversy avatar May 30 '22 20:05 timtraversy

Nice concepts above, thank you!

@prakasharyaman - This is a clever idea, but people format there versions different ways. Also, the HTML contains multiple version strings from past versions, so we would have to add some logic to fix that as well.

@ankitpanwar8979 - This is my preferred solution. The nested array doesn't seem like it will remain stable as the Play site changes, but best we can do for now.

timtraversy avatar May 30 '22 20:05 timtraversy

3 days ago

can u explain code _getCleanVersion is what for?

glngrizkyy avatar May 31 '22 02:05 glngrizkyy

Try This

Works for now

   public function getAndroidVersion(string $storeUrl): string
   {
   $html = file_get_contents($storeUrl);
       $matches = [];
       preg_match('/\[\[\[\"\d+\.\d+\.\d+/', $html, $matches);
       if (empty($matches) || count($matches) > 1) {
           throw new Exception('Could not fetch Android app version info!');
       }
       return substr(current($matches), 4);
   }

prakasharyaman avatar May 31 '22 03:05 prakasharyaman

@timtraversy same issue is facing ( Bad state: No element ) Now what is the solution for it.

vinayakyengandul avatar May 31 '22 06:05 vinayakyengandul

Google Play store looks very different since yesterday or today?

I've got some error messages popping up now.

StateError: Bad state: No element
  File "list.dart", line 167, in ListMixin.firstWhere
  File "new_version.dart", line 157, in NewVersion._getAndroidStoreVersion
  File "<asynchronous suspension>"
  File "new_version.dart", line 94, in NewVersion.showAlertIfNecessary

So I think changes are necessary. You can find the version of the app in a modal @ "About this app ->"

Please provide me solution ASAP in "Bad state: No element"

eramitsharma957 avatar May 31 '22 11:05 eramitsharma957