I have an app on the market that costs $0.99. I want to implement in-app billing so that I can offer it for free with an option to unlock certain features for a price. I've already modified the code to allow that. Question is... how might I mark the 1000+ people who already purchased the app as having purchased it and unlock all the features?
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(free), 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).
Like I said, it's a hack, but I don't know of any "official" way to check to see an app install is an upgrade or an initial install. 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...
Related
I sell a game on Google Play called Quantum-X. Not many people have bought it so I want to move to an ad-supported model and make it a free download.
But I want to reward the people who did buy the game by disabling advertising. So existing users see no ads, new users see ads. I can store a flag in some obfuscated, device specific way which makes this determination.
But in order to this I need to tell the difference between paying and non paying users.
So how do I do this? I have a few ideas but I don't know if any of them are viable:
The old app wrote some preferences out. I could look for an old preference and set the flag. But this will not work if someone installs the app on a clean device since they won't have that preference. It is also an exploit since anybody could put the old key in to fool my app into disabling advertising.
My pay app currently uses LVL to validate a person's licence. If I make my app free, what happens when I call LVL? Does it respond LICENCED even if a user downloaded it for nothing? If I could tell paid from non-paying users from the response then I know how to set the flag. But LVL is a pain to test since I would have to upload the app, set it to free and then see what difference there is in the result and there may be none.
I could produce one final update of my pay app which sets the flag and asks users to upgrade. Then I could roll out the app free in a month from now. The same problem exists as with 1. that some users may not update or may install onto clean devices.
I could produce two apps on the store. The pay app could be renamed to "Quantum-X legacy" and a new Quantum-X goes in its place which is free. I would update the legacy version to install the flag, but people would have to switch to the new version for continued support. This would work but it's a lot more effort.
None of these are pretty although 2. would be the least amount of work. Has anyone experience of a working solution, or know a some better way of doing this?
EDIT: My intention is now a hybrid and I've begun to do this:
Rename the old app as Quantum-X Legacy and update the description.
The new free version is called Quantum-X. The only fly in the ointment here is that I must update the app package in the manifest to make the two apps distinct.
I intend to put a test into the free version that calls LVL using the old app's key. If this works the way I think it will, it will tell me when a user has bought the old app (since the licence server is being asked about the old app), and I can write out an obfuscated flag somewhere so I don't have to call LVL any more.
Free users carry on but with ads.
I'm up to 3. and this is my intention. If LVL doesn't work, then I might have to put out an update to the legacy version which writes the flag or puts a code out on screen that someone must use to enable adfree when they install the other version.
I currently have an Android app which is distributed as two applications an Ad supported version and an ad-free version. The Ad-Supported version has over 10,000 users and the Ad-Free version has a couple of hundred. Currently both projects are completely independent making updates a fairly tedious task.
Ideally I would like to just updated one project and build be able to build both versions.
After looking online it seems I have two options:
Make a library containing most of the class files and then just extend this for the two versions (changing only the files that are different). As the project is fairly big this may be a large task and may cause some serious headaches.
Just release one version and use in-app purchases to remove the ads. This seems the easiest route but how do I allow my existing ad-free users to remove the ads via in-app purchase without paying?
Hopefully someone has been in a similar predicament before and can point me in the right direction.
Where I used to work we had the 2nd option. It helped us a lot since you just need to maintain 1 code/app/apk. In your case, I suggest you to do the same thing.
In order to migrate all your users to a single App, you can give a random code (generated with the email they are using and an algorithm to create it) via your "Ad-Free version" app. Then, in your All-in-one app you can ask for that code or activate the "In-App-workflow" in order to remove all Ads.
Edit:
Check this link:
How to get the Android device's primary e-mail address
I am always recommend SO user to used android inapp purchase.
Benefits:
1) Easily track manage your playstore user.
2) If updation require then update code on one place.
3) Secure payment with google policy.
4) many more feature.
#bencallis as per your question i recommend to you option 2 is better.
if you require any inapp information then put comment.
You're in a similar boat with me, though I've taken one step already.
I made an app for a small group of people that are close to me, free and ad-free, and released it. I then created another app for a wider group of people, free but with ads. The two applications were almost the same, except a few things that had to be app-specific (like strings, resources, and a few variables). After getting frustrated with updating both of them, I decided to go with the library approach. It might give you headaches in the beginning, but it will truly cut down on your updating. You'll only have to update the library file, then just compile and check the actual application.
Because of how you describe your situation, I think you'll have an easier time than me. Turn one of your applications (probably the ad-free one) into a library, then in the ad-supported version simply overwrite the layouts that show the ads.
I can't suggest your second option, only because, as far as I know, there is no way to do what you want.
I have seen so many threads on creating a time bound trial versions for an android apps but none of them seems to fulfill my purpose.
Few days back i Launched the paid version of my app and now I want to come up with trial version which i dont want to be crippled from any side. So i want to have a time bound limitation on the trial version. I have created a different Package name for the same. Earlier I was using LVL and now also I am using the same except that i created new license library and changed the
setValidityTimestamp(extras.get("VT"));
to
setValidityTimestamp(String.valueOf(System.currentTimeMillis() + (5* MILLIS_PER_MINUTE))); in ServerManagedPolicy.
so that i can test if trial version works for 5 mins and then give me the license error. I published it on the app store , downloaded it and then found that it was still working beyond 5 mins. Now i have unpublished it. Can someone help me in creating the better time bound application which a user can run for a week (say). Besides he should not be able to uninstall and re-install it and then again use it permanently. I know if i can write the info to some external file but again the file can be deleted from sd card and application can be made accesible to the user free for lifetime.
Regards
Pankaj
Within the current capabilities of LVL, and the degree of user control over your average handset, there is currently NO way to do this without a server-side component. Once your app is uninstalled all traces (except, as you pointed out, files you may write to the SD card, which are user-visible) are removed, so the only way to check for an uninstall/re-install is to generate a consistent, device-specific identifier and check with a server component that will either reject this as a re-install or accept it as a new time trial. Even this can possibly be spoofed by a dedicated customer (depending on the server-side component behavior), so you would need to engineer your software so that your server-side component is a necessary part of the process (i.e. it isn't just a license check, it is actually part of the application's functionality).
If you come up with something that works I'd love to hear about it, but I'd say you're out of luck.
#Femi is right, you need a server side component to make always work. What I tend to do is publish only a free version, and teh user buys the full version as in-app-purchase. The IAP server is your server side check if the use purchased the upgrade or not. You can store a pref on first use to know when the user started using the app. If users uninstall and install again your app, they get a new trail period, but this is annoying, and few will do it to save a few bucks. If you add a message in the app where you ask user nicely to upgrade, or have ads that are removed once you upgrade, it is a good enough solution.
We have an application, that can itself be downloaded for free, but works with paid, licensed data. Some users buy particular version of the data while others buy right to use latest data for some period of time. Now as the application evolves, it eventually stops supporting data older than some date. So obviously users who have those data licensed, but no license for newer data don't want to upgrade. But if we publish new version on the market, they would see it and if they upgrade, they will have trouble downgrading back to version that actually works for them.
So can we somehow instruct the market application not to offer upgrades for particular user or some hack to achieve that end?
We currently use mechanism completely independent on the market to sell and check licenses for the data, but could consider different mechanism (like the android in-app billing support or something) if it could help solving the problem.
The way I see it, you have two options to "disable" upgrades:
Use a different signing key - this will prevent installation without removal of the previous app, but upgrade notifications will still appear (I think)
Use a different package name - this will prevent upgrades since it is a completely separate app so far as the market is concerned, and also has the side-effect that old versions are still available for those users who are licensed for that data version.
The second option may be a better match since you can roll out upgrades if necessary for bug-fixes, but can also ensure that wholly new versions are not detected as an upgrade.
EDIT:
Totally agree that the above options are cumbersome and don't really solve the issue as-is.
As you mentioned however, you could use in-app billing, but given the nature of your requirements, you'd have to use unmanaged purchases which means you'll need some infrastructure to manage authorising purchases and preventing people from buying the same license too many times.
I'm guessing you've already got much of that infrastructure in place to handle distribution of the data though.
Can the data not contain a "format version" number at the start of the file?
Then you can program the app to read version 1 files, a new app needs more fields on the data source, so you create version 2 data, which adds extra fields, version 1 app see's the data needs a newer app, so tells the user to upgrade.
Version 2 app should know how to read version 1 files and version 2 files (perhaps create a reader Interface and implement loaders for the different versions of files.)
You'll have to handle the missing data in v1 / old files in the loader in the v2 app. The loading of older files is the nicest way for the customer as the app shouldn't just stop working after an upgrade.
If you keep a copy of each format's data you can quickly run tests to check the new version's loader can load each file correctly, plus if the app has a bug in there you won't have to fix several app versions, just the current one.
Ok.. I saw one of the posters suggest you have a way to read the old data.
First that's likely the best option but as you say your apps a mess.
You should invest some time in migrating your data reading/writing to an abstraction layer. The pain your having on a (likely less than 4 year old project) is only going to get worse.
Okay.. so here's how I've dealt with it in long lived apps..
Create a migration path.. Create a new class call Migrate.
In it have several functions to convert the version of the file from n to n-1
convert_1_to_2(fileName){check the version and upgrade data.)
convert_2_to_3(fileName)...
I suspect you have your old code, and you could write a method to convert one bit of data to the next..
When you add new features to the data, then you create a new convert.. No knowledge of the earlier ones would be needed, and everything would be nice and self contained.
You could even have sub migrations, so part way along the dev cycle, you could have convert_3a_to_3b.
Now... you could archive the original version of the data in case the user wants to go back.
If the data is accessed remotely, you could have the app include the version, or some hash of itself, when requesting it. And then filter the data provided based upon that information.
If you already have in-app purchasing and the infrastructure to support it, just poll for new data when the app is upgraded. If the user has purchased the license for current data, provide it. Otherwise just continue using the existing data.
I came up with an option that market will contain an installer that will download and install another .apk containing the core of the application locally.
We already have an installer dialog in the application for downloading the data and user has to enter it when using the application for the first time, so it can be made responsible for the application core too.
You can not definitely prevent users to download the new version of a app they already have. You can either register a new app or check the version and user data programatically.
What is the recommended way of creating a demo version for an application. Basically, the demo version will be fully functional, but will be limited to running it 25 times. My worry is that if the user uninstalls and reinstalls, the count will be reset.
I thought about writing a data file to the SD Card with the count of executions (hoping that would persist after uninstall), but I do not want to add that permission if I can avoid it.
Any suggestions on how to have some type of demo flag persist after an uninstall?
Even if it's on the SD card, there's no reason the user can't just go and delete your file themselves.
I asked a similar question a few months ago, but that was for a review copy, not a demo version. You could do something similar to what Dave Webb suggested and store each user's device id on a server. It would mean you'd both need the READ_PHONE_STATE and INTERNET permissions enabled and I can understand not wanting to add additional permissions. However, it is the only fool-proof way I can think of to guarantee that an application is only run X number of times, as any change you make to the phone can be reversed.
mbaird pointed out that anyone can install the full version of your app and try it for one day before requesting a refund; with this in mind you might make a crippled demo version that informs the user of this (not-oft-used) Market functionality.