java - How can I implement Google Play Licensing for an Android app? -
i saw stock android-developer licensing library instructions, overview seems omit several key steps in process , fails explain how working.
can provide explicit set of operations worked licensing library set on android app checks ensure user has paid app in google play before allowing use?
i have been working on implementing licensing in app time , have working. wanted share of things found helpful getting started , problems , solutions found everyone. android dev tutorial have linked below ok, wasn't useful me, decided make tutorial. enjoy, , hope helps you!
link developer page here.
1. getting started
things need.
1.1 base64 unique application key
how it:
a. go developer console. link.
b. if haven't created application draft app, now.
c. once have created draft, idea upload .apk
alpha or beta. leave unpublished.
d. click services & apis
e. scroll down , find your license key application
f. copy key app this:
private static final string base64_public_key = "your license key application";
make sure there no spaces.
1.2 salt
a. salt?
a salt random data additional input when hashing password. used defend against dictionary attacks , rainbow table attacks.
b. how one?
this link generate random salt. there should exactly 20 random integers, put 20
in amount of random strings generate, each string should 2
characters long (used example, doesn't have be). check numeric digits, , check identical strings allowed. can negative numbers too. try remove redundancy, e.g. 00 -> 0
, sake of consistency.
c. put salt?
when declaring variables put code in, except random salt.
private static final byte[] salt = new byte[] {your random salt, comma separated, 20 integers};
2. importing lvl (licensing) library eclipse , code need
2.1 importing library
a. open android sdk manager
b. go extras
c. install google play licensing library
d. find sdk
install path listed @ top of sdk manager.
e. once there, navigate to: <sdk>/extras/google/play_licensing
f. in eclipse, click file
import
, existing android code workspace
, when asks file path, navigate play_licensing
folder , click on library
.
g. once project named library
has been imported, right click it, hit properties
. click android
on left , navigate bottom , check is library
, hit apply. lets eclipse know can use project code library.
h. right click on app adding licensing to, , click properties, hit android
. go bottom , click library
, add build path. should import library android dependencies
folder.
i. project set go next step.
2.2 variables declare along salt
, key
private handler mhandler; private licensechecker mchecker; private licensecheckercallback mlicensecheckercallback; boolean licensed; boolean checkinglicense; boolean didcheck;
2.3 code
paste code near bottom of app. implementation notify user if license not valid , prompt them buy app or exit it.
private void docheck() { didcheck = false; checkinglicense = true; setprogressbarindeterminatevisibility(true); mchecker.checkaccess(mlicensecheckercallback); } private class mylicensecheckercallback implements licensecheckercallback { @override public void allow(int reason) { // todo auto-generated method stub if (isfinishing()) { // don't update ui if activity finishing. return; } log.i("license","accepted!"); //you can other things here, saving licensed status //sharedpreference app has check license once. licensed = true; checkinglicense = false; didcheck = true; } @suppresswarnings("deprecation") @override public void dontallow(int reason) { // todo auto-generated method stub if (isfinishing()) { // don't update ui if activity finishing. return; } log.i("license","denied!"); log.i("license","reason denial: "+reason); //you can other things here, saving licensed status //sharedpreference app has check license once. licensed = false; checkinglicense = false; didcheck = true; showdialog(0); } @suppresswarnings("deprecation") @override public void applicationerror(int reason) { // todo auto-generated method stub log.i("license", "error: " + reason); if (isfinishing()) { // don't update ui if activity finishing. return; } licensed = true; checkinglicense = false; didcheck = false; showdialog(0); } } protected dialog oncreatedialog(int id) { // have 1 dialog. return new alertdialog.builder(this) .settitle("unlicensed application dialog title") .setmessage("this application not licensed, please buy play store.") .setpositivebutton("buy", new dialoginterface.onclicklistener() { public void onclick(dialoginterface dialog, int which) { intent marketintent = new intent(intent.action_view, uri.parse( "http://market.android.com/details?id=" + getpackagename())); startactivity(marketintent); finish(); } }) .setnegativebutton("exit", new dialoginterface.onclicklistener() { public void onclick(dialoginterface dialog, int which) { finish(); } }) .setneutralbutton("re-check", new dialoginterface.onclicklistener() { public void onclick(dialoginterface dialog, int which) { docheck(); } }) .setcancelable(false) .setonkeylistener(new dialoginterface.onkeylistener(){ public boolean onkey(dialoginterface dialoginterface, int i, keyevent keyevent) { log.i("license", "key listener"); finish(); return true; } }) .create(); }
2.4 getting device id
there has been debate in past whether or not use sim serial or telephonymanager.getdeviceid();
recommended use following code android_id
of device maximum compatibility.
string deviceid = secure.getstring(getcontentresolver(), secure.android_id); log.i("device id", deviceid); //an example of logging should doing :)
2.5 creation of license checker
a. before call docheck();
must put code in app make sure gets created properly.
mhandler = new handler(); mlicensecheckercallback = new mylicensecheckercallback(); mchecker = new licensechecker(this, new servermanagedpolicy(this, new aesobfuscator(salt, getpackagename(), deviceid)), base64_public_key);
when doing implemetation of lvl, read if having problems licensing, can change first this
in mchecker = new licensechecker(this...
getapplicationcontext()
, mine seemed work without it, in case.
2.6 adding permissions
a. there 2 permissions need add applications manifest
file.
<uses-permission android:name="android.permission.internet"/> <uses-permission android:name="com.android.vending.check_license"/>
2.7 make sure have proper imports!
you have done this, figured place check.
2.8 how call license checked
a. call docheck();
whenever want check license. example if app on first run, check.
3. how test licensing make sure works before publishing it?
3.1 configuring testing device
a. have personal phone use testing. recommended there 1 google account registered on phone, historically makes things little easier. can check accounts going settings -> accounts
.
3.2 configuring developer console
a. open developer console , go settings
on left hand side.
b. find license testing
c. make sure email address listed under gmail accounts testing access
d. now, can change test response whatever testing purposes. app should respond accordingly. remember if saving data via sharedprefs need clear app data every time test it. make sure click save after change test response or nothing happen! forgot multiple times , ended migraine, saw stinking save button. lol.
4. things try
4.1 conditional license checking
a. can try code if saving didcheck
data in sharedpreferences
.
if(didcheck==false){ toast.maketext(this, "checking application license...", toast.length_short).show(); docheck(); log.i("checking!", "checking license!"); }
4.2 encrypting sharedpreferences
using securepreferences
a. go link.
b. copy , paste code securepreferences.java
class exact same name project.
c. read readme.md
info on implementing this.
5. troubleshooting
licensing can 1 heck of headache troubleshoot, because there many more things can go wrong. example, there network problems or server problems make want rip hair out. use of proper logging this, can server response codes if there problem , can trace server or app. have had on multiple occasions.
5.1 can't app return server
possible fixes:
a. make sure app has correct key
.
b. make sure logging each step of progress
c. check log licensing service. can useful figuring out went wrong.
d. make sure allow()
, dontallow()
, applicationerror()
have @override
tags.
5.2 app says licensed
or not_licensed
no matter set in test response
a. best cure have wait. seems if lots of testing in short period of time, send server code 291
retry code. waited overnight , worked fine next morning.
b. can clear data (not cache) of google play app , google play services app. open play , accept licenses , try again.
c. clear app data.
5.3 list of server response codes debugging
you should these decimal values int reason
if log them. use table reference server sending app.
licensed = hex: 0x0100, decimal: 256 not_licensed = hex: 0x0231, decimal: 561 retry = hex: 0x0123, decimal: 291 licensed_old_key = hex: 0x2, decimal: 2 error_not_market_managed = hex: 0x3, decimal: 3 error_server_failure = hex: 0x4, decimal: 4 error_over_quota = hex: 0x5, decimal: 5 error_contacting_server = hex: 0x101, decimal: 257 error_invalid_package_name = hex: 0x102, decimal: 258 error_non_matching_uid = hex: 0x103, decimal: 259
5.4 room more! come!
i hope helps guys! tried share headaches , fixes guys best can , hope helps!
if made errors, sure tell me them can them fixed asap!
Comments
Post a Comment