Ahh the in-app billing problems never end! ^.^ I have everything working properly to show the transaction page for the in-app purchase. If I complete the purchase it returns me to my application and after about 10 seconds it verifies the purchase and I receive the item.
On the other hand, if I press the back button after returning to the application and switch to another activity it never processes the transaction. Even if I return to the in-app billing activity I never receive my purchased item, like the purchase has been completely forgotten about if you call finish().
What can I do so that it either completes the transaction and gives the item when I return to the in-app billing activity or processes the transaction and gives the purchased item anywhere that I am at within my application?
Receiving the notification is handled by a broadcast receiver which is independent from your activities. How you handle the notification is up to you. In the default implementation you have a PurchaseObserver interface implemented by an Activity. You can have multiple activities implement it and register to be called accordingly. Or, you can have related code in a base activity, so that all your activities are PurchaseObserver's (might not be practical if you have a lot of activities).
Related
In my app I have a mainactivity that implements authstatelistener, and redirects the user to a login screen if the state is changed (user signs out or timed out). In the app I have a total of about 6 other activities, which contain an navhostfragment container of many fragments.
The purpose of the activities to is to collect user data and send it to firebase.
I am confused if I need to implement authstatelistener in all these activities as well. If I do not do this, will the UI not respond to the user being signed out (and will this happen if the main activity remains in the history stack?).
I read a few questions on this and have found very different answers for different use cases. Currently I am not doing this, and my app runs just fine, but I have no clue if this will cause a bug in the future.
If you implement the auth state listener on the level of activities, then indeed you'll need to implement it in each activity. You'll typically want to implement it in a base-class in that case, and derive all your concrete activities from that.
I have an app that has implemented In App Billing for a premium version of my app. On startup, I check if the user has purchased the product using IabHelper. When I load up my next activity, I need to check for the purchase again to decide whether or not to show certain menu content. I do not want to store the result of the call at startup in preferences or local db for security reasons and understand the Play information is cached anyway. Is my best option in the second activity to create a new instance of IabHelper and call startSetup() again then queryInventoryAsync()? Trouble with this is, as the call is asynchronous, I'm not sure when the response will return in order to update the UI menu.
This is what I'm currently doing as well. I use the async callback to update a previously held menu object to show/hide a purchase option which in reality is never seen the speed of the returned call.
To speed up the process if you call queryInventoryAsync(false, mGotInventoryListener); (note the false flag) then you will only use a local cached inventory which is far quicker to respond.
In my application i want to let users sign in with their google account so i am using google play services. This works - they can login and logout. I also want to find out if the user is signed in the onCreate method when i pass from one activity to another. I am trying to use Google play services isSignedIn function for this but on onCreate method it always return false (because google play service trigger on onStart).
Why do I want it ?
Because, i have two login option. One is google account another is my own login panel. I want to know that is user sign in wtih google or my system or not on onCreate. So i will give direction my flow.
How can i achive this or do you have an alternative suggestion ?
Thank you for answers.
This is due to the Activity lifecycle. Every time an Activity goes into the background, it will get onStop. The Play Games API requires you to disconnect when this happens. When the Activity comes back into the foreground, it gets onStart, and then GameHelper will attempt to reestablish the connection. Until this happens, isSignedIn will return false. When the connection is restored (which should be very fast if the user had already signed in), the onSignInSucceeded callback will be called and from that point on isSignedIn will return true.
It's impossible to know, on onCreate, whether or not the sign-in will succeed. Instead, you should wait for either onSignInSucceeded or onSignInFailed. It is guaranteed that one of those two callbacks will be called shortly after the Activity comes into the foreground.
At that point, you can decide what to do, because it will be clear whether or not the user is signed in with Google+.
I am not certain how your app works but it sounds as though you may be calling GameHelper.onStop at the end of one activity when in fact you want the game to continue in another activity. I don't think you can do this (see the accepted answer here):
Google Play Game Services multiplayer with Activity switching
My app is arranged into fragments and I have one fragment which interacts with GameHelper. Therefore, once I have performed GameHelper.setup and GameHelper.onStart, I am able to call isSignedIn from any method in any fragment and get the correct response.
An alternative approach (which I have used in the past) is to save the result of isSignedIn in a boolean in shared preferences. You can then check this to determine whether the user is signed in or not.
I'm having trouble figuring out how the in-app billing process is supposed to work for broadcast events when the application isn't running. I have a managed product setup and as far as I can see, is working well. With a test account I'm able to purchase my published component and my test application handles it, retaining its state. I then cancel this order via my merchant account and the application again receives the event and removes the item.
The problem occurs when instead of cancelling the order while the application is active. I exit out of it (not with home, with multiple back buttons). If I cancel the item now, my 'device' gets a notification 'purchase failed', but when I start my application nothing seems to happen and thus the state of the item is still purchased.
I'm not sure if billing service is still running or not. Given the documentation says my application must send back a CONFIRM_NOTIFICATIONS or it keeps sending it I can only assume it is. However why is it unable to interact with my database and remove the item like it does correctly if the application is active?
I hope tihs is clear, and I apologize if it has been discussed before, I couldn't find anything in my searches.
Apologies for answering my own question but hopefully my findings will help others that were confused as I was.
My issue was thinking that the Dungeons.java class provided in the example had all the code needed for modification. The example design has its database implementation nested in the observer class that is active while the user is interacting with the store. The issue it created for me outlined in my question, what happens if a transaction is cancelled after the fact when this observer isn't registered or the application isn't running.
From trial and error my solution was to take the database interaction out of the observer and place it in
private void purchaseStateChanged(int startId, String signedData, String signature) {
of the BillingService class.
Placed in here, when my broadcast receiver fires, I act on a cancellation and update my database accordingly regardless of whether my application is started much less my observer registered.
The official documentation says that "Your application must have a local Service to facilitate messaging between your application and Android Market."
My question is, is this is really necessary? And if yes, why?
Wouldn't it be possible to simply bind to the MarketBillingService from an Activity's onCreate method without having to creating a local service first?
Having to create a local service that forward the requests to the remote MarketBillingService just seems a bit over-complicated.
I agree that the In-App Billing example application has a number of layers to it that seem unnecessary, but the idea of using a Service to interact with Market is a good one. This is because the process is very asynchronous (and can take a good amount of time) and some events are generated outside the workflow of a user purchase.
While the user will be interacting with some Market UI while deciding whether to purchase the "item", after this process is over there is a long back-and-forth between your app and the market app to authorize and finalize the transaction, many steps delayed while Market communicates with its servers. You don't want to hold the user up and force them to wait on that Activity simply so you can complete the purchase. You want that to be in a Service so the user can move around in the app, or leave it completely for awhile, and still be able to finalize the purchase and download the appropriate purchased content without fear of your process being removed.
Also, there are many events that may come into your application if purchases are canceled or otherwise rejected that can happen LONG after the initial purchase back-and-forth, and the user may be doing something completely different or not have their phone awake at all at that time. You want to be able to handle these events without having to pop up an Activity.
Bottom line, it's a long-running background process...which is what Services were designed for.
HTH