So I have a billing client which I instantiate with
billingClient = BillingClient.newBuilder(this).setListener(this).build();
I then call
billingClient.startConnection(new BillingClientStateListener() {
#Override
public void onBillingSetupFinished(int responseCode) {
//TODO: use this for stuff
com.android.billingclient.api.Purchase.PurchasesResult result;
result = billingClient.queryPurchases(BillingClient.SkuType.SUBS);
Timber.d(result.toString());
}
#Override
public void onBillingServiceDisconnected() {
//TODO: use this for stuff
Timber.d("something went wrong ");
}
});
for whatever reason the breakpoint on the timber line always returns disconnected. can anyone provide insight or an example to how i would do this?
I came across this problem.
Be also sure to start the connection:
mBillingClient = BillingClient.newBuilder(mContext).setListener(purchasesUpdatedListener).build();
mBillingClient.startConnection(new BillingClientStateListener() {
#Override
public void onBillingSetupFinished(#BillingClient.BillingResponse int billingResponseCode) {
if (billingResponseCode == BillingClient.BillingResponse.OK) {
Log.d(TAG, "onBillingSetupFinished: BillingClient.BillingResponse.OK ");
}
}
#Override
public void onBillingServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
}
});
Turns out I was not using a version of my apk that was signed with the right version numbering and such. Once I fixed that I was able to connect to play services and figure out what i wanted.
I know it's too late to answer this, but i was missing this permission in manifest,
<uses-permission android:name="com.android.vending.BILLING" />
hope that helps someone
If you use custom rom or rooted device it probably won't work.
Run a system image on which the Google Play client application is preinstalled.
If Google Play is not preinstalled in the system image, your application won't be able to communicate with the Google Play licensing server.
https://developer.android.com/google/play/licensing/setting-up
Related
I am using Google CoreAR package in my React-Native app for AR support. There are some devices which support AR and some not. I am getting error while I run the application in non-supported devices. I want to render a message instead showing error on the screen. For this Google CoreAR package is providing the solution which is not working for me.
void maybeEnableArButton() {
ArCoreApk.Availability availability = ArCoreApk.getInstance().checkAvailability(this);
if (availability.isTransient()) {
// Continue to query availability at 5Hz while compatibility is checked in the background.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
maybeEnableArButton();
}
}, 200);
}
if (availability.isSupported()) {
mArButton.setVisibility(View.VISIBLE);
mArButton.setEnabled(true);
} else { // The device is unsupported or unknown.
mArButton.setVisibility(View.INVISIBLE);
mArButton.setEnabled(false);
}
}
The problem with above code snippet is that availability.isSupported() is always returning true and that's why else part of code is not running. Can you guys please help me with this?
Thank you.
I found solution for this problem. ArCoreApk.Availability has some methods which can be used. You can find these methods in the
documentation. The method ArCoreApk.Availability
return either SUPPORTED_INSTALLED or SUPPORTED_NOT_INSTALLED depending on device support. So based on this return value we can do the stuff.
I did like this.
#ReactMethod
public ArCoreApk.Availability getSupport(){
ArCoreApk.Availability availability = ArCoreApk.getInstance().checkAvailability(this.getReactApplicationContext());
return availability.name();
}
I've seen some posts that seem similar, but they're all fairly old and slightly different. I have an app whose codebase I have not touched in a long time. It makes use of the android SpeechRecognizer Service, and has a toggle for the EXTRA_PREFER_OFFLINE intent param. Previously this was working with no issues, but since I've recently dusted it off I noticed that offline functionality immediately returns with error code 7 NO_MATCH.
I have confirmed that offline language packs are installed, and wrote some stand alone code to test SpeechRecognizer outside my larger code base.
I've not been able to find any documented solutions for the NO_MATCH error, but surely it must occur elsewhere.
For context: This was previously working last year/earlier this year (I've seen people claim this wasn't possible after 2015/17) and on Android 8
Sample code snippet:
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(getContext());
final Intent speechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true);
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_PREFER_OFFLINE, true);
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "en-US");
speechRecognizer.setRecognitionListener(new RecognitionListener() {
#Override
public void onReadyForSpeech(Bundle bundle) {
listening = true;
label.setText(R.string.listening_true);
}
#Override
public void onBeginningOfSpeech() {
}
#Override
public void onRmsChanged(float v) {
}
#Override
public void onBufferReceived(byte[] bytes) {
}
#Override
public void onEndOfSpeech() {
label.setText(R.string.listening_false);
listening = false;
}
#Override
public void onError(int i) {
Log.e(TAG, "Error code " + i);
label.setText(R.string.listening_false);
listening = false;
}
#Override
public void onResults(Bundle bundle) {
ArrayList<String> data = bundle.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
if (data != null && data.size() > 0) {
resultsTextView.setText(data.get(0));
resultsTextView.setTextColor(getResources().getColor(R.color.colorAccent));
listening = false;
}
}
#Override
public void onPartialResults(Bundle bundle) {
ArrayList<String> data = bundle.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
if (data != null && data.size() > 0) {
Log.i(TAG, "how many partial results? " + data.size());
resultsTextView.setText(data.get(0));
resultsTextView.setTextColor(getResources().getColor(R.color.design_default_color_primary));
Log.i(TAG, "Partial results: " + data);
}
}
#Override
public void onEvent(int i, Bundle bundle) {
}
});
view.findViewById(R.id.button_mic).setOnClickListener(view1 -> {
if (!listening) {
speechRecognizer.startListening(speechRecognizerIntent);
} else {
speechRecognizer.stopListening();
}
});
Google app's voice input could work offline previously, but unfortunately, this feature has been removed since version 11 (released in March 2020).
Thus, to use this feature, we have to keep the version of Google app on device at 10.99.8 or older.
However, on some new device released after March 2020, the pre-installed version of Google app is already 11 or 12, so it is not a simple task to downgrade it to an older version.
So we need to use adb command to downgrade it from PC. This command will try to force downgrade the app for the 'current user': adb install -r -d --user 0 google.apk
The answer is that this is no loner supported. If you need a short term fix then go to your "Google", not "Google Play Services", app and uninstall updates from the hamburger menu. This seems to downgrade a lot of libraries, including the voice recognition stuff.
A possibility might be to manually bring and load your own libraries, but I haven't tested this personally.
I'm using 'com.github.javiersantos:PiracyChecker:1.2.3' because my app is not yet integrates AndroidX.
I have numerous reports from user reviews in my app's Google Play page that they have installed the app from the Google Play Store, yet they getting the piracy warning message.
Here are some examples:
Also got a user report via email:
My app have 4k reviews and only 3 of them are like this, but I don't know the exact user count because there could be users who don't comment about this issue.
What is going on?
I use it like this:
public static void showPiracyActivityIfNeeded(final Activity activity) {
if (!BuildConfig.DEBUG) {
//Releaseb build, piracy check.
new PiracyChecker(activity)
.enableInstallerId(InstallerID.GOOGLE_PLAY)
.callback(new PiracyCheckerCallback() {
#Override
public void allow() {
}
#Override
public void dontAllow(#NonNull PiracyCheckerError piracyCheckerError, #Nullable PirateApp pirateApp) {
Intent intent = new Intent(activity, PiracyWarningActivity.class);
activity.startActivity(intent);
activity.finish();
}
})
.start();
}
}
Thanks in advance.
It seems that your Google Play Services are unavailable. Try to check it before start your PiracyActivity:
const val PLAY_SERVICES_RESOLUTION_REQUEST = 9000
fun AppCompatActivity.checkPlayServices(): Boolean {
val apiAvailability = GoogleApiAvailability.getInstance()
val resultCode = apiAvailability.isGooglePlayServicesAvailable(this)
if (resultCode != ConnectionResult.SUCCESS) {
if (apiAvailability.isUserResolvableError(resultCode)) {
apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
.show()
}
return false
}
return true
}
And then:
public static void showPiracyActivityIfNeeded(final Activity activity) {
if (!BuildConfig.DEBUG && activity.checkPlayServices()) { ...
Also note, there are a lot of devices that has Google Play Services turned off because of various reasons, so check availability of Services every time you need it.
I'm currently developing a game and try to implement In-app billing V3 of Google Play. I had followed the In-app sample and used IabHelper. However, when running the app in device, something goes wrong. I found that after mHelper.startSetup, neither onServiceDisconnected nor onServiceConnected was called. So I printed the result of mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE); in the IabHelper Class. The result is false.
Here is my code:
private IabHelper mHelper;
// MainActivity onCreate
protected void onCreate(Bundle savedInstanceState){
// ...
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.enableDebugLogging(true);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
return;
}
if (mHelper == null) return;
}
});
}
And in the method startSetup of IabHelper Class:
public void startSetup(final OnIabSetupFinishedListener listener) {
// ...
Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
if (!mContext.getPackageManager().queryIntentServices(serviceIntent, 0).isEmpty()) {
// service available to handle that Intent
boolean bRes = mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
// ### I printed the result here it was false
Log.i("IAB", "IAB Service Result = " + bRes);
}
else {
// no service available to handle that Intent
if (listener != null) {
listener.onIabSetupFinished(
new IabResult(BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE,
"Billing service unavailable on device."));
}
}
}
I don't know the problem. I have done:
add permission: com.android.vending.BILLING
copy the .aidl file from sample to /src/com/android/vending/billing
my android target set to android-22
Any ideas what's wrong?
Thanks in advance.
Finally, I solved it by uploading the latest version of my game to developer console and debug the latest apk. The problem is gone. Hope this helps someone.
Copy all the class from util folder from the Project "Trivial"
or you can copy whole Util package into your project. And then give a try.
I had this problem, and found that
The app version debugged must be the same as the version released in developer console.
Play service needs to be available, some phones may actually kill the service after a screen lock, start play store, then redo the binding worked.
Using IabHelper out of box may trigger problems like service disconnect not handled, re-initialize fail, I had to modify it a bit.
I want to connect my game with google play service. i have read documentation on android developer and try to following type-a-number sample and still can't load leaderboard.
i have import baseGameUtils, but i use andengine so i didn't use extends BaseGameActivity from google.
what i have until now:
- GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) return success
- startActivityForResult(pickAccountIntent, REQUEST_CODE_PICK_ACCOUNT); is working well and i got my account name from onActivityResult(..);
- i already put this on my manifest.
<meta-data android:name="com.google.android.gms.games.APP_ID"
android:value="#string/app_id" />
my questions are
1. can i use google play service without extends BaseGameActivity?
2. if i use gameHelper.beginUserInitiatedSignIn(); after i got my account name, i got this on log cat. (what this connected mean? because i still got error on next question)
08-25 00:09:01.890: D/BaseGameActivity(11222): isGooglePlayServicesAvailable returned 0
08-25 00:09:01.890: D/BaseGameActivity(11222): beginUserInitiatedSignIn: starting new sign-in flow.
08-25 00:09:01.890: D/BaseGameActivity(11222): All clients now connected. Sign-in successful.
08-25 00:09:01.890: D/BaseGameActivity(11222): All requested clients connected. Sign-in succeeded!
3 . how do i use connect()? i have read and tried about gameClient and GameClientBuilder but i have no idea how to use that. when i tried run this code.
startActivityForResult(gameHelper.getGamesClient().getAllLeaderboardsIntent(), RC_UNUSED);
i got this log.
08-25 00:09:05.660: E/AndroidRuntime(11222): java.lang.IllegalStateException: Not connected. Call connect() and wait for onConnected() to be called.
4 . to use leaderboard i know i must use code from google play store such as CgkIx****AIQAA. but i didn't found where i must put this code to load leaderboard.
sorry for long question, but i think if there is a sample that only for connect and either access achievement or leaderboard it will answer all my question. please don't tell me to see type-a-number sample, i did that and i need another sample code.
update, my snipped code
public class MainMenu extends Activity
implements OnClickListener, GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, GameHelperListener{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_menu);
gameHelper = new GameHelper(this);
}
#Override
public void onClick(View v) {
if(v.equals(loadData)) {
if(gameHelper.isSignedIn()) {
gameHelper.setup(this, GameHelper.CLIENT_GAMES, Scopes.GAMES);
startActivityForResult(gameHelper.getGamesClient().getAllLeaderboardsIntent(), RC_UNUSED);
}
}
else if(v.equals(loginButton)) {
Intent googlePicker = AccountPicker.newChooseAccountIntent(null,null,new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE},true,null,null,null,null) ;
startActivityForResult(googlePicker, REQUEST_CODE_PICK_ACCOUNT);
}
}
#Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
if(requestCode==REQUEST_CODE_RECOVER_PLAY_SERVICES) {
if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "Google Play Services must be installed.", Toast.LENGTH_SHORT).show();
finish();
}
return;
}
else if(requestCode==REQUEST_CODE_PICK_ACCOUNT) {
if (resultCode == RESULT_OK) {
String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
gameHelper.beginUserInitiatedSignIn();
}
else if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "This application requires a Google account.", Toast.LENGTH_SHORT).show();
finish();
}
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
// this 2 methods not called, is this also because my code is wrong?
#Override
public void onSignInFailed() {
Log.d("rush", "on sign in failed");
}
#Override
public void onSignInSucceeded() {
Log.d("rush", "on sign in succeed");
}
}
Yes. Take a look at the BaseGameActivity source and see that it largely just wraps GameHelper. You can implement the calls to GameHelper yourself - in fact, you can probably copy some code directly from BaseGameActivity. I'm a bit confused, because it appears that your code is already using GameHelper. It looks like you are mixing GameHelper calls with BaseGameActivity calls. You cannot do this, and it will result in... errors like you are getting.
The LogCat you see means that all of your clients are connected. The default call to GameHelper.setup() just requests the Games client. If you aren't using BaseGameActivity and want different clients, do:
gameHelper = new GameHelper(this);
gameHelper.setup(this, GameHelper.CLIENT_GAMES | GameHelper.CLIENT_PLUS);
beginUserInitiatedSignIn() is an asynchronous method with a callback when it finishes. Are you running it that way? GameHelper.GameHelperListener is the interface to implement. If you are using gameHelper, make sure to register the callback. See the this in the setup call above? That's registering the callback (this is my main activity).
As I said above, it looks like you are mixing GameHelper calls with BaseGameActivity calls. The GameHelper that is connected is the BaseGameActivity.mHelper instance, not any GameHelper you might have instantiated. Make sure that if you are using BaseGameActivity that you are not using GameHelper as well.
If you want to display a single leaderboard, use the GamesClient.getLeaderboardIntent(string, int) or method to get the Intent. The string is the code you have (CgkIx****AIQAA).
startActivityForResult(gameHelper.getGamesClient().getLeaderboardIntent(
leaderboard_id, RC_UNUSED);
Again, make sure you are using the correct getGamesClient() method, depending on if you are using BaseGameActivity or GameHelper directly.
Here is basic information how to use GameHelper without BaseGameActivity:
https://developers.google.com/games/services/android/init#using_gamehelper_without_basegameactivity