I would like to use in-app billing in my android application (instead of creation 2 versions of application - free and pro). If user paid, then additional options in Preferences should be available.
My application synchronizes data with website (not my).
Each time synchronization happens, I would like to check if user paid or not.
How should I do it?
I think the easiest means for you would be to use Managed purchase. More on it is at http://developer.android.com/guide/market/billing/billing_admin.html#billing-purchase-type
The "manage by user account" purchase
type is useful if you are selling
items such as game levels or
application features. These items are
not transient and usually need to be
restored whenever a user reinstalls
your application, wipes the data on
their device, or installs your
application on a new device.
Update: website and API updated refer this now https://developer.android.com/google/play/billing/api.html
There are to many ways to do that, i will try and give you some of the most used
what about user accounts? can your application support users? if it does, its practically solved with 1 user per 1 account. just add a flag to your DB for each user. this is the most secure way, its very easy to know if someone is stealing from you thats why all MMO's (like WOW) use this type of check. you can easily know if theres more then one user on an account as well
the downside is that it requires more processing and some support is case someone's account gets stolen or other user support of that kind.
you can save a sort of key inside your application. and some other key on the server. if the key matches (either 1 to 1 or after some manipulation) then you have yourself a paid user, other you dont.when someone buys the application then change the key on the device.
just do what you dont want to do and have 2 applications for free and paid it will probably be less work then the other 2 list above.
there are many ways of doing what you want. but i'll tell you this:
most applications use method 2 but on the opposite direction, meaning serial key.
i dont think your gonna create an mmo so theres no need for option 1 unless you really dont want anyone hacking your application (which i assume no matter what you do it will be hacked in todays world. i'll advice you to trust those who pay and accept those who dont)
method 3 is just easy in my opinion especialy when you want to just remove menu options, but it also creates duplicate repositories for code.
good luck. what ever you decide is good, make a theft protection, if someone wants to steal it, they will, dont fight it (even PS3 got hacked in the end)
Related
I am creating an iOS and Android App and I want to create a screen where the player can start with a guest account or can connect his account with our own accountsystem.
But my question is: Can I detect a user after the app was uninstalled and installed again?
I know that there is something like the vendor. But this will change.
I know that other apps also can do this.
With the user's permission- have them log into an account. Or provide you with their google of facebook account info. So far as hardware ids, those are discouraged and actively being removed to prevent people from the API to prevent this.
Also remember- that unless the user logs in with an account, you don't really know whether it is the same person. You could know its the same phone, but you don't know if he gave it to his kid sister to play on. Or sold it when he got a new one, and now you've given the new owner access to someone else's account. Also, if you rely on hardware ids you won't know its me when I buy a new phone and download it on that.
So yeah- either have him log in with a username and password, or use a 3rd party signon mechanism like Google or Facebook.
For iOS, there is a recommended approach to do that: by using the DeviceCheck framework. The idea here is that it allows you to persist 2 bits of data across app installations on each device. You can set the first bit to 1 if the user has already installed the app or 0 otherwise. And use the second bit, for example, to check if the user has signed in or not.
The official documentation is pretty good, please check it out.
The downside of this approach is that you will also have to do some work on the backend side.
UPDATE:
If you specifically want to detect the account, there is no reliable approach. One of the options is to use identifierForVendor or generate some kind of device fingerprint (for example, by combining the device model, timezone, locale, etc.), but of course, this will not work every time.
Uniquely identifying a device is a security leak, and all platforms are putting serious restrictions on unique persistent identifiers because of privacy concerns.
I have a paid app in the Google Play Store. I'm considering reducing the price of that app (somewhat; not all the way to free) and offering one of the features as a separate in-app purchase.
If I did that, I wouldn't want to yank the feature away from anybody who's already bought it.
Is there any way to figure out either the date that the user bought my app, or the original version of the app that they bought, or something like that? I'd like to say something like, "If the app was before the price change (either by date or by version), they should have the feature for free; otherwise, require IAP to unlock the feature."
For example, iOS does have a feature like this; the app receipt includes an "originalVersion" field which can be used to control access to features.
Unfortunately for your customers, this is impossible. There is no API call or anything else to Google Play where you can get the time on which the app was bought.
I know there is an android-publisher API in existance, however it doesn't offer any feature to check that.
The functions you want to use are not public availible and only used by the Playstore internally!
Workarounds which you could do:
1. Get the time the app was installed
On the first start you could check that and unlock the features.
Warning: This system could be abused by changing the time on the device
long installed = context
.getPackageManager()
.getPackageInfo(context.getPackageName(), 0)
.firstInstallTime;
2. Give users free keys
You could give every user who's using the app atm a free key via mail or push notification
3. Unlock the inapp purchase now
Publish an app update which unlocks the inapp purchase for free. After a few weeks you could pusblish your new version with the lower price and just unlock the features as if your current customers had bought your extension.
You might be able to hack your way around this if you're using some sort of persistent storage.
For SharedPreferences, on the first run, do a check for one of your preferences using SharedPreferences.contains(). If it contains it, the app must have already been installed. If not, set another preference that marks the user as new, and set yet one more so it doesn't do the check every time.
That might only work if the preference doesn't have a "default" value, I'm not entirely sure if setting a default in xml will mark it as contained.
You could do something similar if you have any assets that get transferred to SD, or any similar one-time setup. Just check to see if it's already done before doing it the first time.
If you're using an SQLite DB, you could increment the DB version and mark as "paid" in onUpgrade() if coming from the current version(or earlier).
There are some pitfalls here, though. For instance, if a previous paid customer completely uninstalls before installing the new version, or if it's on a new device. For that reason you should:
4. Provide Support
In the about or FAQ section of your app and on first run of your new version set a support mail adress which customers can use if they have any problems because the new features were not unlocked for them.
They could provide any proof (bill) for their purchase.
Like I said, those ideas are workarounds, but I don't know of any "official" way to check to see an app install is an upgrade or an initial install.
Your best option may be a combination of those four.
FYI: I've opened a feature request/idea in Google Cloud Connect for work which you could vote: https://connect.googleforwork.com/ideas/9392 (You can only vote if you have a paid Google Buisiness Account)
I hope this helps you at least a bit.
As far as i know, the best you can do is find the date it was installed. http://developer.android.com/reference/android/content/pm/PackageInfo.html#firstInstallTime
My app is free and, using in-app purchases, I'd like to enable additional functionality. To do so, I am envisioning generating an unlock code that is dependent on the current user and the current app version. I need the first so that the same key won't work with someone else's installation (but will work for multiple devices owned by the same user). I may not need the second, but it would give a bit more future flexibility.
To do this, I need some sort of google user id. Is there such a thing? If so, how do I get it?
Thanks.
Google takes care of some of this for you. It will deliver a device dependent key to each device for a user. Your job is
1) Validate the key properly on your server
2) Make sure you return a device-specific authorization value from the server so users cannot just copy data files around.
3) On the device, use the authorization value to enable things.
Validating the key is easy but do make sure you do it on a server. The problem is identifying the device. Google and its partners dropped the ball a bit on that. Tim Bray has a blog article at http://android-developers.blogspot.ca/2011/03/identifying-app-installations.html that discusses the problem. I recommend using the ANDROID_ID despite his reservations. I have doubts about the security of his other proposal but haven't done a full analysis. Definitely stay away from anything network related (IMSI, IMEI, ESN, ...). I also cache the device identifier used and make sure it doesn't change.
Personally, I scramble the data needed to unlock my features in my app. When I get a valid transaction, I compute a key that can be combined with the device id to unlock the data. It is far from perfect but seems to work. I accept that I will be hacked - I just don't want it to be obvious.
If you want a per-version key, then you need to do a RESTORE_TRANSACTIONS and re-validate at the server any time the version changes.
I'd like to suggest another approach - no better, just different. Use a flag to indicate whether to allow or not running the upgrade features. Periodically validate with the in-app billing apis whether the user has purchased the upgrade. If not, reset the flag.
The user can hack the flag, but sooner or later it will be reset, blocking use of the features.
To truely break this method, the user would have to reverse engineer the code and bypass checking the flag. I doubt most people would bother with that, but what do I know?
I have an app right now that I am planning to put onto Google play as a paid app. I know that one can decide at a later date to make the app free. I'm thinking that I might one day want to make the app free, selling some of the features that are now included in the paid version. Is there a way that I can tell if a user paid for an app?
The best I can suggest is to put some SharedPreference in your app marks it as "paid", then release a new version of your app which does not have this (when you make it free). Then, you can check the flag to see if it was there before it went free.
The downside to this is that root users may be able to change that value, if they were to discover it. Another downside is that clearing the data would clear the flag.
To avoid those downsides, you could store the data in a webserver database, but this seems like a fair bit of extra work for something like this.
Use a SharedPreference, as Eric suggests, but encode your value; instead of using true or yes, use a hash of the device ID so that no one can post that value for use on other devices. Then you can just recompute the hash when testing this indicator, to ensure it is your own value and not one entered by a user.
For my Android application, I want to release it for free, but with ads. Then, I want to give the user an option to remove the ads for a nominal fee using the PayPal library. That way, I don't have to have 2 separate versions of my application that I have to monitor, develop, etc.
Anyways, after the user pays me to remove the ads, I need to securely store something that indicates that they paid so that it isn't easy to spoof my app. How should I do this? I was thinking of encrypting a string and storing that encrypted value in SharedPreferences. Is that a viable option? If one were to take the apk off of their device and give it to someone else, does SharedPreferences move with it, or is it saved outside of the apk? What about if someone has root access? Can they spoof SharedPreferences?
If possible, I'd like to avoid having to query a server every time the app is launched.
Thank you!
I would argue a few of points:
Refactor your application into a free, ad supported version and a paid version. You can package things such that you'll be able to share almost every piece of the application. Then just post the free and paid versions in the market.
Anyone willing to work their way around your copy protections was never going to pay for your app anyway.
You're offering a value proposition. If the only thing that separates your free and paid version is ads then your app better be something the user can't live without. If you're planning on expanding the paid version with more features then #1 above is probably a better idea anyway.
What you could do is take some unique data from the phone (device ID, app version...etc...) in your app and combine that into a message.
Then use a public/private key pair. The public part can be in your app and the private part you keep with you.
When a user pay for your app, it sends you the string with device ID and so on and when you got the payment, you send back a blob of data containing a certificate.
Your app can verify the certificate against the device ID or whatever your decided to put in there by using the public key.
There are still a lot of details you'd have to work out (how the data is sent back and forth...etc...), but with those kind of tools, you should be able to achieve what you are looking for.
You can look here about how to manage certificates : http://developer.android.com/reference/java/security/cert/package-summary.html
Of course, how sophisticated you want to be depends on your app and how much people will have to pay for. Reverse engineering to bypass all that is certainly possible, but I doubt many people would go through the trouble if they only have to pay $0.99 to get rid of the ads.
If the user is determined enough, they will be able to reverse-engineer your app and get the decryption key, or just patch away your protection altogether. SharedPreferences are stored in a file that is accessible to anyone (ok, maybe anyone will root access...).
In summary, save yourself the effort and don't even try to protect your app... who is going to reverse engineer your app to merely get rid of advertisements anyway?
You might want to skimp on the complicated protections for now and wait until in-app purchase arrives. I'd imagine there would be a secure, reliable solution at that point in time.