Implemented in-app update feature, using the following code snippet:
private void showInAppUpdateDialog(boolean isMandatoryUpdate) {
Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo();
appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> {
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
|| appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
int appUpdateType = isMandatoryUpdate ? IMMEDIATE : AppUpdateType.FLEXIBLE;
int requestCode = isMandatoryUpdate ? REQUEST_APP_UPDATE_IMMEDIATE : REQUEST_APP_UPDATE_FLEXIBLE;
if (appUpdateInfo.isUpdateTypeAllowed(appUpdateType)) {
// start the app update
try {
appUpdateManager.startUpdateFlowForResult(appUpdateInfo, appUpdateType, targetActivity, requestCode);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
}
}).addOnFailureListener(e -> {
e.printStackTrace();
});
}
I am testing in-app update on the device which has Android 9. Still, it is giving me following an error (ERROR_API_NOT_AVAILABLE):
com.google.android.play.core.install.InstallException: Install Error(-3): The API is not available on this device. (https://developer.android.com/reference/com/google/android/play/core/install/model/InstallErrorCode#ERROR_API_NOT_AVAILABLE)
at com.google.android.play.core.appupdate.i.a(Unknown Source:24)
at com.google.android.play.core.internal.o.a(Unknown Source:13)
at com.google.android.play.core.internal.j.onTransact(Unknown Source:22)
at android.os.Binder.execTransact(Binder.java:731)
It is saying that check the following link:
https://developer.android.com/reference/com/google/android/play/core/install/model/InstallErrorCode#ERROR_API_NOT_AVAILABLE)
Using Play core library version: 1.6.5
Latest core library version:
implementation 'com.google.android.play:core:1.7.0'
However, I am not able to get why it is saying that ERROR_API_NOT_AVAILABLE. Any help would be appreciated!
Firstly, please check that you are using the latest version of the play library.
Secondly, understated fact: Please check the app you are testing has the same package name which is available on the play store.
Example:
You have an app on the play store with package name com.example.app but you are testing your app with package name com.example.app.debug. You will get this error: ERROR_API_NOT_AVAILABLE
Note: You need to have at least one version of your app on the play store when you are testing.
On top of what Vipal suggested, the issue may be due to a signature mismatch between the version you have installed on the device and the one that Play Store would deliver (this is a common issue if you try to test it with debug builds). See https://developer.android.com/guide/playcore/in-app-updates#troubleshoot
Recently the Play Core API started returning an API_NOT_AVAILABLE error if the app is not owned by the user or the signatures mismatch, while before it used to return a successful UPDATE_NOT_AVAILABLE Task.
The recommendation is:
if you use the Kotlin Extension, make sure that you are catching the exception thrown by requestAppUpdateInfo
if you use PlayCore Java, make sure you have an onFailureListener that handles failures from getAppUpdateInfo
in order to test a debug build, you can use Internal App Sharing, as explained here: https://developer.android.com/guide/playcore/in-app-updates#internal-app-sharing
Source: I work on the Play Core team
My app was working fine before today, but I started getting this error today. One temporary workaround is to clear your Google Play Store cache and storage and then try launching the app. For me, it works only the first time, but fails afterwards. Before launching the app again, I have to clear the cache and storage again. I think there is something wrong on Google Play Store side due to which this issue is happening because everything was fine for me before today.
Got the same error, tried all solutions described here, nothing works.
App installed from Play Store Internal Test track with Version Code 267, then submitted new update to the same track with Version Code 268.
Play Store shows available update but the application still says ERROR_API_NOT_AVAILABLE
Clear Play Store data and cache does not help.
Description of ERROR_API_NOT_AVAILABLE say that it means “API is not available on device”
After carefully reading again this page, I have noticed that “in-app updates support apps running on only Android mobile devices and tablets, and Chrome OS devices”
Android TV not mentioned, I think it’s the reason in my case.
Temporary workaround for the moment is to surround the OnCompleteListener with a :
try {...} catch(e: RuntimeExecutionException) {...}
Just to avoid having to clear the PlayStore cache everytime I relaunch the app
After long time of debugging. I found, this is because of we are testing the app directly in mobile. Even though we generate and use signed apk, this error will occur.
The only way to get rid of this error is, we need to download the app from google play.
We can use Internal app sharing to test or simply publish our app.
Well, in my case we've cleared Google Play app cache and we didn't launch the Google Play before our app. You have to do it to download fresh data from the store, which is necessary for the SDK.
Related
On trying to migrate Google billing integration from version 4 to 5, I'm getting an error 'Client does not support ProductDetails' on calling queryProductDetailsAsync.
List<QueryProductDetailsParams.Product> productList = List.of(QueryProductDetailsParams.Product.newBuilder()
.setProductId("ppgapp1")
.setProductType(BillingClient.ProductType.SUBS)
.build());
QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder()
.setProductList(productList)
.build();
billingClient.queryProductDetailsAsync(params, listener);
Are there any changes needed to be made on the console on migration?
And how long it'll take to complete review on submitting to closed or internal test track for Google billing integration?
I face same issue when my emulator PlayStore application version is too old (in my case it is 23.0.21...)
Update PlayStore application to newer version will solve the problem (30.9.0...)
Here is how to update the Play Store app
If you want to guide user to update the PlayStore app, you can do like
billingClient.queryProductDetailsAsync(productParams) { billingResult, productDetails ->
if (billingResult.responseCode == BillingClient.BillingResponseCode.FEATURE_NOT_SUPPORTED) {
Log.e("TAG", "Feature not supported ")
runOnUiThread {
Toast.makeText(this#MainActivity, "Please update PlayStore app", Toast.LENGTH_LONG).show()
// or AlertDialog or any error message
}
return#queryProductDetailsAsync
}
...
}
I had experienced the same problem. I couldn't find any information on why the problem is occurring. You can use it after checking whether the ProductDetail feature is supported.
BillingResult billingResult = billingClient.isFeatureSupported( BillingClient.FeatureType.PRODUCT_DETAILS );
if ( billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK ) {
// use billingClient.queryProductDetailsAsync()
}
Getting this error when I use google play version 21.2.12-21. When I use the 31.2.29-21 version of google play on another device, the item can be successfully queried. I can't use the 5.0 version of the billing library because it affects the user's payment
Issue resolved
Issue was occuring on one device and not occuring on another device with latest library.
Upon debuging I used old library on device where issue was occuring. And it was working fine on old library.
So after alot of trouble shoot I do following to resolve issue on that device with latest library code.
On device where issue is occurred
Do following
Update device OS update if there is any. In my case there was security patch update. Notification was there to update.
update play store if already not updated
Then clear data storage of play store app under setting of play store app. Then force stop play store app and then open play store app
uninstall and reinstall the android app again
After that my app shows product details as well as purchase pop up with latest billing library.
Thank you
I had to reinstall the app for the Billing client to recognize the supported product ID. I imagine that simply purged some stale cache behind the scenes.
I'm working with AppsFlyer in Unity based on the following documentation: https://support.appsflyer.com/hc/en-us/articles/213766183-Unity-plugin-V4-integration-guide-for-developers
I followed the necessary steps but when it came to running the integration test, it just stayed stuck in this screen:
https://imgur.com/a/taXW909
Are there any potential things that I might be missing that could cause this issue? As far as I understand, I need to whitelist my Android device, select it in the SDK Integration Test, scan the QR Code, install my project's .apk file and the AppsFlyer should start detecting something.
Additional details
Here's the script for initializing AppsFlyer:
public class AppsFlyerObject : MonoBehaviour
{
private const string AppsFlyerKey = /* MY DEV KEY */;
private void Start()
{
AppsFlyer.setAppsFlyerKey(AppsFlyerKey);
AppsFlyer.init(AppsFlyerKey, "AppsFlyerTrackerCallbacks");
}
}
Regarding the AppsFlyer app, here're the settings I selected:
https://imgur.com/a/7PxEnlW
I want to test an APK file that is not present on any kind of a store.
Have you tried testing a non-organic install with this link?
https://support.appsflyer.com/hc/en-us/articles/207032126#integration-43-simulating-a-nonorganic-install
If everything implemented correctly, but you are still stuck on this screen - it's very likely you have 'zero plan' on your AppsFlyer account. You cannot pass this test on free plan for some reason.
I've found it after two days by connecting device via logcat and recieving 403 error. You can do same to be sure its your reason too.
NOTE: I am not trying to update google play services in the emulator. I do not care that it is out of date. I mentioned it only to show that somehow logcat is reporting the actual build number, which I wish to access in the app.
Similar, but not the same as, How can I determine the version of Google Play services?
An app I'm developing using Android Studio 1.2.2 is experiencing a problem if the latest Google Play Services is not installed on the device, yet GoogleApiAvailability is not reporting a problem and so the code instructing the user to update is never called. If I manually tell the users to update play services in the play store with a manual link to https://play.google.com/store/apps/details?id=com.google.android.gms&hl=en, there is an update available, and the app functions correctly after they install it.
However I am unable to find a way to determine that the user needs to update via application code or the gradle build file.
In the gradle file I've specified: compile 'com.google.android.gms:play-services:7.5.0' and this is the latest version as far as I know. Android Studio does not indicate that I should update this line to a newer version.
The SDK manager reports the play services I have installed is "rev 25", and no update is available.
When I test in an emulator, the code works correctly, and in logcat I see the message: "W/GooglePlayServicesUtil: Google Play services out of date. Requires 7571000 but found 6774470". This is normal for the emulator since they haven't released new images yet, but it provides an interesting clue.
Is there a way to get this build number reported in item 3 above, programatically? If so, I could compare against that rather than using the isgooglePlayServicesAvailable method of GoogleApiAvailability -- which I'm already using, but is reporting success on devices that need an update.
I've managed to do a little digging and answer my own question. The following code will do what I (and perhaps others) want.
PackageInfo pi = getPackageManager().getPackageInfo("com.google.android.gms", 0);
if (pi.versionCode < VERSION_YOU_WANT)
{
// instruct user to update
}
What I've done is wrap this in the required exception handler and run it if the API check reports SUCCESS. If the version is too low I call the getErrorDialog just like when the API check fails, with ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED instead of the returned SUCCESS value.
Doing this may require you to update your minimum SDK target. For example both my phone(5.0.1) and tablet(4.2.2) report success from the API check, and going to the play store does not show an update for either one; However, the installed build on the table is 7895032 while on the phone it's 7895438.
This function will tell the user to update the GooglePlaServices if an update is available. You can start the registration process, if this function returns true
private boolean checkPlayServices()
{
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS)
{
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode))
GooglePlayServicesUtil.getErrorDialog(resultCode, this, 9000).show();
else
{
Log.i(TAG, "This device is not supported.");
finish();
}
return false;
}
return true;
}
I'm developing a game for Android using the Google Play Services for creating a turnbased match.
At first everything was fine I load the turnbased matches for the signed in user using
Games.TurnBasedMultiplayer.loadMatchesByStatus(getApiClient(),
new int[]{TurnBasedMatch.MATCH_TURN_STATUS_MY_TURN,
TurnBasedMatch.MATCH_TURN_STATUS_THEIR_TURN,
TurnBasedMatch.MATCH_TURN_STATUS_INVITED,
TurnBasedMatch.MATCH_TURN_STATUS_COMPLETE})
.setResultCallback(this);
It always loaded all matches that are any of the given states. But since last weekend the callback is called but there are no matches, as I'm not participating in any match (Status response is OK). I deleted the cache of Google Play Services on my phone and rebooted the device. At that moment all the matches were shown again until the next time I opened the app. Again all matches were missing.
Once I start a new match the match keeps showing up with the above method (refreshing the list) until I close the app. At the next launch that match is also gone.
I have to say the game is not published yet but in a test phase on the Google Play Developer Console. I found the same issue on an emulator. It ran fine for days but suddenly got the same problem as my real device (with a later build so it is not that a single change of code causes this).
Did anyone else notice this behaviour or has an idea on how to resolve it?
Might it be related to having multiple apps connected to one game? I had two apps signed with debug certificates connected and this afternoon added one for a signed apk. When I used the signed apk it worked again until I deployed a new test app (debug signed). After switching back to the signed apk the bug is still around.
As nobody seems to know the answer let me rephrase the question. Should I cache TurnBasedMatches myself on the device? I just deleted the play services cache again and reopened my app. Result? A list of hundreds of games (since I have to start a new game every time while testing...)
My code to handle the loadMatchesResult
#Override
public void onResult(TurnBasedMultiplayer.LoadMatchesResult loadMatchesResult)
{
showToast("GotMatches status: " + loadMatchesResult.getStatus().getStatusCode());
//add matches to listview (only caching matchId, no references to turnbasedmatch)
loadMatchesResult.getMatches().getMyTurnMatches().close();
loadMatchesResult.getMatches().getInvitations().close();
loadMatchesResult.getMatches().getTheirTurnMatches().close();
loadMatchesResult.getMatches().getCompletedMatches().close();
loadMatchesResult.release();
}
Found another interest point.. it starts to look like the issue occurs when deploying a new apk to the device... Once I deploy a new apk (either by install alpha version from google play or directly debug version from Android Studio) the matches are gone. When I don't change the apk I can reboot my phone/close the app and it works fine...
Issue also occurs if I update the app through the play store... There should be more people having this problem!
Gotten from https://developer.android.com/reference/com/google/android/gms/common/api/PendingResult.html#setResultCallback(com.google.android.gms.common.api.ResultCallback)
After the result has been retrieved using await() or delivered to the result callback, it is an error to attempt to retrieve the result again. It is the responsibility of the caller or callback receiver to release any resources associated with the returned result. Some result types may implement Releasable, in which case release() should be used to free the associated resources.
After you retrieve the result, an error is given when you try to get the results again, until you free the resources associated with the returned result, which is why clearing the cache works to make them visible again. You need to either access the device's cache and display results from there as well, or clear the associated resources (within the program) whenever you want to access the results again.
I had the same problem until I found "Saved Games" in my Developer Console:
Go to Game Services -> Game Details -> Saved Games
Set the item to "On"
This should solve your issue.
Working with Lollipop, I have a device-owner app that is installed with NFC at provision time.
What I need now is to handle automatic updates for my App, from Google Play to rely on the standard Android App update system...
So far I can imagine 2 ways to get this done, but don't know how to handle any of them :
in my NFC install constant EXTRA PROVISIONING DEVICE ADMIN PACKAGE
DOWNLOAD LOCATION install the App directly from the Play Store instead of the url on my own dev server. However
this constant need to handle the url of an apk file, and I did not find any
official way to get apk install direct from Play Store ? (as it will
be a production App in the future I'm not interested in hacks)
keep installing the apk from the dev server, but then allow the App
to update itself with its little brother located on the Play Store
with the same package name. To say it an other way: Would this be possible to install a v1 apk from a custom location, then put a v2 on the PlayStore... and let the magic come true ?
I'd be glad to hear if anyone could share experience about such procedures. Thanks for reading!
EDIT after #Stephan Branczyk suggestion I could make some more testing, here is what I did and the results:
1 - In the NFC provisioning I replaced the apk url with
snep://my.app.packagename without luck ; it just gives an error
without much explanation.
2 - I replaced this url by such a PlayStore link :
https://play.google.com/store/apps/details?id=my.app.packagename but
it gives a checksum error whether I use the checksum locally
computed, or the checksum given on the GooglePlay apk details. It looks not so far from the goal but I could not make it work.
3 - Finally I came back on my first solution, a self-hosted apk
versioned 1... but this time I tried to put on the PlayStore a newer
version 2 of the app with the exact same packagename... That led me
to strange things:
At first my App did not appear anywhere in the local PlayStore App,
but when I searched for it in Google Play, it showed up with the green
"installed" badge, and it proposed me to make an update... So did I.
Then, after this first manual update, the App is in v2, nice, and
better: it appears well listed in my PlayStore.
Optimistically, I uploaded a v3 of the App... just to see if my
PlayStore would automatically update my app (as is does for all the
other ones), but sadly no luck : even if my app is still listed in the
playstore, and proposing the "update" button... it never
updates by itself as it should ; I still need to click on it manually.
Isn't it a strange behavior ? If some have ideas about it, I would really need to be able to rely on the Play Store functionalities but so far no luck, and I cannot believe that Device-Owner app distribution is not compatible with PlayStore ?
Just in case, FYI here is the kind of provisioning code I'm using:
try {
Properties p = new Properties();
p.setProperty(
DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,
"my.app.packagename");
p.setProperty(
DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION,
"http://www.example.com/myDeviceOwnerApp.apk");
p.setProperty(
DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM,
"U55o3fO0cXQtUoQCbQEO9c_gKrs");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
OutputStream out = new ObjectOutputStream(bos);
p.store(out, "");
final byte[] bytes = bos.toByteArray();
NdefMessage msg = new NdefMessage(NdefRecord.createMime(
DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC, bytes));
return msg;
} catch (Exception e) {
throw new RuntimeException(e);
}
Write your package name as an AAR record in the tag.
To confirm that this functionality works, use this app to write the tag with.
You need to set Base64 encoded SHA1 or SHA256 (from M forward) of the apk in the
EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM
field when provisioning through NFC otherwise the provisioned device will not accept the URL for download.
Also see this answer for properly encoding the checksum.