agamemnus / cordova-plugin-xapkreader

Easily access Google Play APK expansion file data.
32 stars 55 forks source link

Download failed because you may not have purchased this app #100

Closed piermariacosina closed 6 years ago

piermariacosina commented 6 years ago

I've updated to the latest plugin version 6.5.0, I set the variables for public key and authority URI via command line, build test with a device and works perfectly. I upload the new version in beta, set the apk file expansion test and I always have the same error "Download failed because you may not have purchased this app"

I've checked and the OBB file is in the right place on the device and it is downloaded from play store, the error happens when you open the app.

I've checked the api key around the project and it is always the same.

Looks like that the system is not licensing the app like the API key is not valid.

is there anything that I can check?

PS I've posted a similar error in past but a the time the API was wrong, I've checked several time that error before posting

agamemnus commented 6 years ago

Idk.... no idea where to start checking. What os?

piermariacosina commented 6 years ago

Mac os sierra cordova 6.5 cordova-android 6.2.3

androidmanifest

<?xml version='1.0' encoding='utf-8'?>
<manifest android:hardwareAccelerated="true" android:versionCode="10705" android:versionName="1.7.5" package="it.enhancers.azimutyachts1" xmlns:android="http://schemas.android.com/apk/res/android">
    <supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <application android:hardwareAccelerated="true" android:icon="@drawable/icon" android:label="@string/app_name" android:supportsRtl="true">
        <activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="@string/activity_name" android:launchMode="singleTop" android:name="MainActivity" android:screenOrientation="landscape" android:theme="@android:style/Theme.Black.NoTitleBar" android:windowSoftInputMode="adjustResize">
            <intent-filter android:label="@string/launcher_name">
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
        <activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="@string/app_name" android:name="com.flyingsoftgames.xapkreader.XAPKDownloaderActivity" />
        <service android:name="com.flyingsoftgames.xapkreader.XAPKDownloaderService" />
        <receiver android:name="com.flyingsoftgames.xapkreader.XAPKAlarmReceiver" />
        <provider android:authorities="@string/xapk_expansion_authority" android:exported="false" android:multiprocess="true" android:name="com.flyingsoftgames.xapkreader.XAPKProvider" />
    </application>
    <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="21" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="com.android.vending.CHECK_LICENSE" />
</manifest>

android.iml

<?xml version="1.0" encoding="UTF-8"?>
<module external.system.id="GRADLE" type="JAVA_MODULE" version="4">
  <component name="FacetManager">
    <facet type="android-gradle" name="Android-Gradle">
      <configuration>
        <option name="GRADLE_PROJECT_PATH" value=":" />
      </configuration>
    </facet>
    <facet type="android" name="Android">
      <configuration>
        <option name="ALLOW_USER_CONFIGURATION" value="false" />
      </configuration>
    </facet>
  </component>
  <component name="NewModuleRootManager" inherit-compiler-output="true">
    <exclude-output />
    <content url="file://$MODULE_DIR$" />
    <orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
    <orderEntry type="sourceFolder" forTests="false" />
  </component>
</module>

android.json

{
    "prepare_queue": {
        "installed": [],
        "uninstalled": []
    },
    "config_munge": {
        "files": {
            "AndroidManifest.xml": {
                "parents": {
                    "/manifest/application": [
                        {
                            "xml": "<meta-data android:name=\"com.google.android.gms.version\" android:value=\"@integer/google_play_services_version\" />",
                            "count": 1
                        }
                    ],
                    "/manifest": [
                        {
                            "xml": "<uses-permission android:name=\"android.permission.INTERNET\" />",
                            "count": 1
                        },
                        {
                            "xml": "<uses-permission android:name=\"android.permission.WAKE_LOCK\" />",
                            "count": 1
                        },
                        {
                            "xml": "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />",
                            "count": 1
                        },
                        {
                            "xml": "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\" />",
                            "count": 1
                        },
                        {
                            "xml": "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />",
                            "count": 1
                        },
                        {
                            "xml": "<uses-permission android:name=\"com.android.vending.CHECK_LICENSE\" />",
                            "count": 1
                        }
                    ],
                    "application": [
                        {
                            "xml": "<activity android:configChanges=\"orientation|keyboardHidden|keyboard|screenSize|locale\" android:label=\"@string/app_name\" android:name=\"com.flyingsoftgames.xapkreader.XAPKDownloaderActivity\"></activity>",
                            "count": 1
                        },
                        {
                            "xml": "<service android:name=\"com.flyingsoftgames.xapkreader.XAPKDownloaderService\" />",
                            "count": 1
                        },
                        {
                            "xml": "<receiver android:name=\"com.flyingsoftgames.xapkreader.XAPKAlarmReceiver\" />",
                            "count": 1
                        },
                        {
                            "xml": "<provider android:authorities=\"@string/xapk_expansion_authority\" android:exported=\"false\" android:multiprocess=\"true\" android:name=\"com.flyingsoftgames.xapkreader.XAPKProvider\" />",
                            "count": 1
                        }
                    ],
                    "/*": [
                        {
                            "xml": "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />",
                            "count": 1
                        }
                    ]
                }
            },
            "res/xml/config.xml": {
                "parents": {
                    "/*": [
                        {
                            "xml": "<feature name=\"XAPKReader\"><param name=\"android-package\" value=\"com.flyingsoftgames.xapkreader.XAPKReader\" /><param name=\"onload\" value=\"true\" /></feature>",
                            "count": 1
                        },
                        {
                            "xml": "<feature name=\"Device\"><param name=\"android-package\" value=\"org.apache.cordova.device.Device\" /></feature>",
                            "count": 1
                        },
                        {
                            "xml": "<feature name=\"Notification\"><param name=\"android-package\" value=\"org.apache.cordova.dialogs.Notification\" /></feature>",
                            "count": 1
                        },
                        {
                            "xml": "<feature name=\"EmailComposer\"><param name=\"android-package\" value=\"de.martinreinhardt.cordova.plugins.email.EmailComposer\" /></feature>",
                            "count": 1
                        },
                        {
                            "xml": "<feature name=\"InAppBrowser\"><param name=\"android-package\" value=\"org.apache.cordova.inappbrowser.InAppBrowser\" /></feature>",
                            "count": 1
                        },
                        {
                            "xml": "<feature name=\"NetworkStatus\"><param name=\"android-package\" value=\"org.apache.cordova.networkinformation.NetworkManager\" /></feature>",
                            "count": 1
                        },
                        {
                            "xml": "<feature name=\"SplashScreen\"><param name=\"android-package\" value=\"org.apache.cordova.splashscreen.SplashScreen\" /><param name=\"onload\" value=\"true\" /></feature>",
                            "count": 1
                        },
                        {
                            "xml": "<feature name=\"StatusBar\"><param name=\"android-package\" value=\"org.apache.cordova.statusbar.StatusBar\" /><param name=\"onload\" value=\"true\" /></feature>",
                            "count": 1
                        },
                        {
                            "xml": "<feature name=\"Whitelist\"><param name=\"android-package\" value=\"org.apache.cordova.whitelist.WhitelistPlugin\" /><param name=\"onload\" value=\"true\" /></feature>",
                            "count": 1
                        },
                        {
                            "xml": "<feature name=\"Html5Video\"><param name=\"android-package\" value=\"org.apache.cordova.plugin.Html5Video\" /></feature>",
                            "count": 1
                        }
                    ]
                }
            },
            "res/values/xapkreader.xml": {
                "parents": {
                    "/*": [
                        {
                            "xml": "<string name=\"xapk_expansion_authority\">it.enhancers.azimutyachts1.expansion</string>",
                            "count": 1
                        },
                        {
                            "xml": "<string name=\"xapk_google_play_public_key\">my google key</string>",
                            "count": 1
                        },
                        {
                            "xml": "<string name=\"xapk_text_downloading_assets\">Downloading assets…</string>",
                            "count": 1
                        },
                        {
                            "xml": "<string name=\"xapk_text_preparing_assets\">Preparing assets…</string>",
                            "count": 1
                        },
                        {
                            "xml": "<string name=\"xapk_text_download_failed\">Download failed.</string>",
                            "count": 1
                        },
                        {
                            "xml": "<string name=\"xapk_text_error\">Error.</string>",
                            "count": 1
                        },
                        {
                            "xml": "<string name=\"xapk_text_close\">Close.</string>",
                            "count": 1
                        },
                        {
                            "xml": "<integer name=\"xapk_main_version\">0</integer>",
                            "count": 1
                        },
                        {
                            "xml": "<integer name=\"xapk_patch_version\">0</integer>",
                            "count": 1
                        },
                        {
                            "xml": "<integer name=\"xapk_main_file_size\">0</integer>",
                            "count": 1
                        },
                        {
                            "xml": "<integer name=\"xapk_patch_file_size\">0</integer>",
                            "count": 1
                        }
                    ]
                }
            }
        }
    },
    "installed_plugins": {
        "cordova-google-play-services": {
            "PACKAGE_NAME": "it.enhancers.azimutyachts1"
        },
        "com.flyingsoftgames.xapkreader": {
            "PACKAGE_NAME": "it.enhancers.azimutyachts1"
        },
        "cordova-plugin-device": {
            "PACKAGE_NAME": "it.enhancers.azimutyachts1"
        },
        "cordova-plugin-dialogs": {
            "PACKAGE_NAME": "it.enhancers.azimutyachts1"
        },
        "cordova-plugin-email": {
            "PACKAGE_NAME": "it.enhancers.azimutyachts1"
        },
        "cordova-plugin-inappbrowser": {
            "PACKAGE_NAME": "it.enhancers.azimutyachts1"
        },
        "cordova-plugin-network-information": {
            "PACKAGE_NAME": "it.enhancers.azimutyachts1"
        },
        "cordova-plugin-splashscreen": {
            "PACKAGE_NAME": "it.enhancers.azimutyachts1"
        },
        "cordova-plugin-statusbar": {
            "PACKAGE_NAME": "it.enhancers.azimutyachts1"
        },
        "cordova-plugin-transport-security": {
            "PACKAGE_NAME": "it.enhancers.azimutyachts1"
        },
        "cordova-plugin-whitelist": {
            "PACKAGE_NAME": "it.enhancers.azimutyachts1"
        },
        "jaeger.Html5Video": {
            "PACKAGE_NAME": "it.enhancers.azimutyachts1"
        }
    },
    "dependent_plugins": {},
    "modules": [
        {
            "file": "plugins/cordova-plugin-device/www/device.js",
            "id": "cordova-plugin-device.device",
            "pluginId": "cordova-plugin-device",
            "clobbers": [
                "device"
            ]
        },
        {
            "file": "plugins/cordova-plugin-dialogs/www/notification.js",
            "id": "cordova-plugin-dialogs.notification",
            "pluginId": "cordova-plugin-dialogs",
            "merges": [
                "navigator.notification"
            ]
        },
        {
            "file": "plugins/cordova-plugin-dialogs/www/android/notification.js",
            "id": "cordova-plugin-dialogs.notification_android",
            "pluginId": "cordova-plugin-dialogs",
            "merges": [
                "navigator.notification"
            ]
        },
        {
            "file": "plugins/cordova-plugin-email/www/email_composer.js",
            "id": "cordova-plugin-email.EmailComposer",
            "pluginId": "cordova-plugin-email",
            "clobbers": [
                "cordova.plugins.email",
                "plugin.email"
            ]
        },
        {
            "file": "plugins/cordova-plugin-inappbrowser/www/inappbrowser.js",
            "id": "cordova-plugin-inappbrowser.inappbrowser",
            "pluginId": "cordova-plugin-inappbrowser",
            "clobbers": [
                "cordova.InAppBrowser.open",
                "window.open"
            ]
        },
        {
            "file": "plugins/cordova-plugin-network-information/www/network.js",
            "id": "cordova-plugin-network-information.network",
            "pluginId": "cordova-plugin-network-information",
            "clobbers": [
                "navigator.connection",
                "navigator.network.connection"
            ]
        },
        {
            "file": "plugins/cordova-plugin-network-information/www/Connection.js",
            "id": "cordova-plugin-network-information.Connection",
            "pluginId": "cordova-plugin-network-information",
            "clobbers": [
                "Connection"
            ]
        },
        {
            "file": "plugins/cordova-plugin-splashscreen/www/splashscreen.js",
            "id": "cordova-plugin-splashscreen.SplashScreen",
            "pluginId": "cordova-plugin-splashscreen",
            "clobbers": [
                "navigator.splashscreen"
            ]
        },
        {
            "file": "plugins/cordova-plugin-statusbar/www/statusbar.js",
            "id": "cordova-plugin-statusbar.statusbar",
            "pluginId": "cordova-plugin-statusbar",
            "clobbers": [
                "window.StatusBar"
            ]
        },
        {
            "file": "plugins/cordova-plugin-whitelist/whitelist.js",
            "id": "cordova-plugin-whitelist.whitelist",
            "pluginId": "cordova-plugin-whitelist",
            "runs": true
        },
        {
            "file": "plugins/jaeger.Html5Video/www/Html5Video.js",
            "id": "jaeger.Html5Video.Html5Video",
            "pluginId": "jaeger.Html5Video",
            "clobbers": [
                "plugins.html5Video"
            ]
        }
    ],
    "plugin_metadata": {
        "cordova-google-play-services": "25.0.0",
        "com.flyingsoftgames.xapkreader": "0.9.0",
        "cordova-plugin-device": "1.1.1",
        "cordova-plugin-dialogs": "1.2.0",
        "cordova-plugin-email": "1.1.0",
        "cordova-plugin-inappbrowser": "1.2.1",
        "cordova-plugin-network-information": "1.2.0",
        "cordova-plugin-splashscreen": "3.1.0",
        "cordova-plugin-statusbar": "2.1.1",
        "cordova-plugin-transport-security": "0.1.1",
        "cordova-plugin-whitelist": "1.2.1",
        "jaeger.Html5Video": "1.2.1"
    }
}
piermariacosina commented 6 years ago

Another thing that I've changed is that I've updated the app to the new google play signature instead of the regular keystore, but that should regard the app not the licensing part.

Debuging the beat apk on android the error that the console print is this one

05-31 14:30:29.680: E/LicenseValidator(19074): Signature verification failed.

fonograph commented 6 years ago

Getting the same error in Android 7.

agamemnus commented 6 years ago

Idk. Something doesn't sound right. Maybe you are missing a step. 100% sure the signature is correct?

fonograph commented 6 years ago

Yes, totally sure.

So apparently the license server is sending a blank signature. The LicenseChecker.verifyLicense callback is being called with a blank signature argument. No idea why this is happening, but I've read that the LVL logic can be convoluted and funky when you're in testing, and FWIW right now I'm testing with an open alpha.

agamemnus commented 6 years ago

Maybe a good idea to put this in the readme. Other than that, any other suggestions?

On Jun 2, 2017 10:17 AM, "fonograph" notifications@github.com wrote:

Yes, totally sure.

So apparently the license server is sending a blank signature. The LicenseChecker.verifyLicense callback is being called with a blank signature argument. No idea why this is happening, but I've read that the LVL logic can be convoluted and funky when you're in testing, and FWIW right now I'm testing with an open alpha.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/agamemnus/cordova-plugin-xapkreader/issues/100#issuecomment-305801569, or mute the thread https://github.com/notifications/unsubscribe-auth/ADFJWK0ZC0g6H8cRJYm2Sr0FobqHfo_7ks5sABmDgaJpZM4NqAt6 .

piermariacosina commented 6 years ago

I don't know, @fonograph are you suggesting that is something related to the signature server in testing alpha and beta but in production should work?

I'm not sure I will risk publishing a version that is not working in beta? what if I can't fix it?

But I guess is the only solution possible to see if is a problem only in testing, right?

keeffEoghan commented 6 years ago

Also having this problem, quite hard to track down the source of the issue. I did manage to get an alpha deploy version working again, though quite unsure how - in case it helps, it seemed to be connected to the app version...

Bumping the version to a higher number seemed to get around the issue (from 2.0.xx to 2.1.0; and receiving the following "Non-upgradable APK" warning on the developer console):

Non-upgradable APK
WARNING
None of the users of this APK will be able to upgrade to any of the new APKs added in this release.
TIP
Ensure that all your new APKs are added to this release.

There was also a (possibly related) problem downloading an old expansion patch file that had been removed, even though it was from a very old and obsolete version of the app - this was failing with a HTTP 401 error. Updating the version as above also seemed to fix this.

.........

I'm still very unsure what the issue was, how to track it, and why this version bump apparently fixed it - main questions:

Is there a good way to investigate where the LicenseChecker is receiving signature from? Can this process be traced all the way back through the licensing service to see what affects it (for example, versions or expansion files)? (The stack trace from the E/LicenseValidator: Signature verification failed. error went back as far as an async callback, where the blank signature was given; but no further.)

Can the license validation check be controlled/disabled/etc? (And if so, is this wise?)

.........

Would be great to better understand what's happening here, and ideally have a reliable fix (would also feel very uneasy publishing live without knowing why this was breaking in alpha).

PS: I'm unfamiliar with the ins and outs of license and version management, and how it relates to the .obb and license checking - so please bear in mind these are basically trial-and-error shots in the dark.

piermariacosina commented 6 years ago

I can share my experience on this. when you say version, you mean version on the store or apk version? I haven't tried bumping the version. The .obb file is renamed by google accordingly with the version which is attached when uploaded but you can choose to publish with and old expansion file. I've tried uploading a new one with same content, to try fix this thing, and google play says that the content is the same of an old expansion already uploaded that I can use that one instead of uploading the new one. licensing shouldn't be related to the expansion because the expansion is already downloaded when with the apk when you install, so the licensing is checking something else. for example if you delete the obb and open again the app it will check if there is the obb and download it again from the server, this need the license to work.

So this shouldn't in any case related to the expansion file, also because it is working with manual testing the debug apk with obb.

I've checked the api key so many time, but still maybe if someone can spot where the plugin uses it I would try to place it by hand hardcoded, in this way we are sure that it is sent to the server in the right way.

This thread could be useful https://stackoverflow.com/questions/8472709/android-licensevalidator-signature-verification-failed

keeffEoghan commented 6 years ago

when you say version, you mean version on the store or apk version?

I mean the versionCode: https://stackoverflow.com/questions/9629125/versioncode-vs-versionname-in-android-manifest I tweaked the way we're setting this, to ensure it just steadily increments for each release. Unsure why this seems to work for this problem, or why the old version code didn't work; but may be an area to investigate. Any idea how the version code might be connected to the license check and/or .obb, or how this could be tested?

licensing shouldn't be related to the expansion

Good point - though the .obb download seems to trigger / depend on the license check as well, going from logs being observed in this order:

piermariacosina commented 6 years ago

I don't get exactly how version code could be related I'm using the cordova automatically generated syntax so 1.7.5 in the config.xml become in the androidmanifest.xml android:versionCode="10705" android:versionName="1.7.5" package="it.enhancers.azimutyachts1" how can I bump the version like 1.8.0 so would be 108000, the documentation says that it is just an integer, so I don't se the relationship but I will try to see if this fix the version.

I'm wondering if this android:versionName="1.7.5" could be related to this problem you upload with a version name but you can change it in the interface of google play, maybe the value should match?

agamemnus commented 6 years ago

As far as I know, the app install version is not really a built-in part of obb management. Intel followed some google examples IIRC to kind of implement version management but that was superfluous so it is by default not being used in the plugin.

fonograph commented 6 years ago

I've yet to test with a published app yet, but one thing that's worked for me is using the License Testing section in Settings -> Developer Account -> Account Details. I had to use LICENSED for the test response, RESPOND_NORMALLY didn't work.

fonograph commented 6 years ago

And bizarrely, after passing license validation with the test response, I then removed my test account from the License Testing list and switched it back to RESPOND_NORMALLY, and everything works fine. (Note that the OS caches license checks, so after a successful validation you need to uninstall and reinstall the app in order to trigger another check.)

This also lines up with one of the comments in https://stackoverflow.com/questions/8472709/android-licensevalidator-signature-verification-failed.

I'm beginning to suspect that the license validation service is just inherently buggy. Again, hopefully this is just an issue during testing and not after a production release.

As a safety precaution, I'm disabling the downloader service and just using this plugin for its APK reading -- as noted in #94, there shouldn't be many situations where a user needs to download your expansion file outside of Google Play.

piermariacosina commented 6 years ago

OK I even more confused than before, I've tried to publish a beta again and now works I don't know exactly what solved the issue, I've done the following steps: Bump the version from 1.7.7 to 1.8.0 both in the versionName and in the versionCode Added and deleted the license test with the LICENSED selected Removed it and added again to be sure

And now everything works like a charm.

Conclusion, reading around seems that the license verification server is buggy and unreliable

Hope that this help would be great to add in the readme something like, this could happen try this things