Android Tutorial Protect your Android application with the Licensing library

The licensing library allows you to use Android market licensing service to verify that the user is allowed to access your application.

Your applications sends a request to the local market application. The market application contacts the market server and returns the result. The result is cached based on the market rules.

It is recommended to go over Google's documentation related to the licensing method: Application Licensing | Android Developers

Configuring the licensing library is simple. You should first have a publisher account in the market.
The license key is available in Google Play developer console under Development tools - Services & APIs.

The licensing library and service will not prevent a dedicated hacker from hacking your application. It will however make it more difficult.

The first step is to initialize a LicenseChecker object:
B4X:
Sub Activity_Create(FirstTime As Boolean)
   Dim lc As LicenseChecker
   Dim p As PhoneId
   lc.Initialize("lc", p.GetDeviceId, publicKey, "kljdflkf".GetBytes("UTF8"))
   lc.SetVariableAndValue("test_1", "some secret value")
   lc.CheckAccess
End Sub
The result of the licensing check is cached locally. The cache is encrypted with AES algorithm. In order to avoid users from tampering with the cache and copying the cache to different devices, the device id is used together with the package name as the password.

Note that the same user will be able to download your application to other devices running with the same user account.

PhoneId (from the Phone library) requires the READ_STATE permission. The protection will still work if you pass an arbitrary string. It will be weaker however.
The Salt parameter should be an array of bytes with some random values (the values should be the same on each run).

Edit: It is recommended to use the alternative id method as described here: http://www.b4x.com/forum/basic4andr...oid-device-unique-id-alternative-phoneid.html

The next step is to call lc.CheckAccess. This in turn calls the market application or the local cache and checks whether the user is allowed to access the program.
One of the following events will be raised when the result arrives: Allow, DontAllow or Error (ErrorCode As String).
It is up to you to handle the event subs as required.

LicenseChecker.SetVariableAndValue
A simple way to hack an application is to "jump over" the checking code. For example a hacker might remove the call to CheckAccess and instead call your Allow event sub.
In order to make it a bit more complicated you can call LicenseChecker.SetVariableAndValue.
For example:
B4X:
lc.SetVariableAndValue("test_1", "some secret value")
The above code will set the value of a process global string value in the main activity named test1 to "some secret value" if the check was successful. You should not use or test the value of test1 in the Allow event sub as it will be too obvious. Instead you should use it later in your program.
You can be creative and pass the name of the variable or the value by using BytesToString or some other way.
As this variable is accessed in a dynamic way it will fail when the code is obfuscated. Therefore you need to include an underscore in the variable name to prevent it from being obfuscated. For example: test_1.
Note that SetVariableAndValue method will fail when running in rapid debug mode as the variable is part of the "debugger engine".

A more complete example:
B4X:
Sub Process_Globals
   Dim publicKey As String
   publicKey = "MIIBIjANBgkqhAADSFEFEFkiG9w0BfW/cGhTbtIs6QIDAQAB..."
   Dim test_1 As String
End Sub
Sub Globals

End Sub
Sub Activity_Create(FirstTime As Boolean)
   Dim lc As LicenseChecker
   Dim p As PhoneId
   lc.Initialize("lc", p.GetDeviceId, publicKey, "kljdflkf".GetBytes("UTF8"))
   lc.SetVariableAndValue("test1", "some secret value")
   lc.CheckAccess
End Sub
Sub lc_Allow
   Log("Allow")
End Sub
Sub lc_DontAllow
   Log("DontAllow")
   ToastMessageShow("Closing application.", True)
   Activity.Finish
End Sub
Sub lc_Error (ErrorCode As String)
   Log("error: " & ErrorCode)
   ToastMessageShow("Closing application.", True)
   Activity.Finish
End Sub
Sub Activity_Pause(UserClosed As Boolean)
 
End Sub
Sub Activity_Resume

End Sub

The library is available here: http://www.b4x.com/forum/additional-libraries-official-updates/11430-licensing-library.html
 
Last edited:

peacemaker

Expert
Licensed User
Longtime User
Last edited:

luke2012

Well-Known Member
Licensed User
Longtime User
Free version

First of all thanks Erel!

It's possible to protect the same phisical apk published with two different pkg names?

I'm doing a apk with the free and full version using the Package name as identifier.
 

luke2012

Well-Known Member
Licensed User
Longtime User
My target is to publish a "Lite" Version and a "Pro" versione of my app.

I wish to use the same project (phisical files) and publish a package name "my.app.lite" and "my.app.pro" using the same B4A project.
 

luke2012

Well-Known Member
Licensed User
Longtime User
Test case

There is some specific step to reproduce in order to test if the licensing protection is working fine ?

I mean :

Step 1 : Check a
Step 2 : Check b
....
 

ondesic

Active Member
Licensed User
Longtime User
I seem to be having the same problem as before. There doesn't appear to be any local cache being stored. My app will run no problems UNLESS I turn to Airplane Mode. Then it will pop up the message I created "Your Application is not registered", then quits.

From time to time I have users complain of this as well. Most people have a connection at all times and so they don't notice this. However, I'd like to nip this quick. Any suggestions?
 
Last edited:

yttrium

Active Member
Licensed User
Longtime User
Isn't the licensing library service no longer required for >=API16?
https://support.google.com/googleplay/android-developer/answer/186113?hl=en
Please note that starting with JellyBean release of Android OS, all apps, paid as well as free, are encrypted by default, and therefore, do not require any additional protection against unauthorized copying such as Google Licensing Server. If you only develop for devices running JellyBean, you don't need Google Licensing Server.
 

derez

Expert
Licensed User
Longtime User
Protect a purchased file ?

I have not yet published any application in google play and I need an advice.
I'm helping a friend with programming a game with many puzzles. The application will be accessible for free with one set of puzzles, then the next sets (binary files) will have to be purchased through google play.
How do I protect the additional puzzles files from being copied and used by other users ?
Thanks
 

Wembly

Member
Licensed User
Longtime User
Hi - I seem to be having a issue with the new B4A version 3 beta 2 and the use of this library.

Using the following code:

B4X:
Sub Process_Globals
   
    Dim publicKey As String
    publicKey = "MIIBIjANBgkqhki...."
    Dim test_1 As String
...

    If CheckConnection = True Then
   
        lc.Initialize("lc", GetDeviceId, publicKey, "kljdflkf".GetBytes("UTF8"))
        lc.SetVariableAndValue("test_1", "test value")
        lc.CheckAccess
       
        If test_1 <> "test value" Then Activity.finish
    End If

I now get the following error in debug:

unexpected error.
Error occurred on line: 110 (main)
mainafterFirstLayout (java line: 98)
java.lang.RuntimeException: java.lang.NoSuchFieldException: _test_1
at com.android.vending.licensing.ServerManagedPolicy.allowAccess(SourceFile:275)
at com.android.vending.licensing.LicenseChecker.checkAccess(SourceFile:133)
at anywheresoftware.b4a.objects.LicenseCheckerWrapper.CheckAccess(SourceFile:60)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at anywheresoftware.b4a.shell.Shell.runVoidMethod(Shell.java:487)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:210)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:170)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:93)
at uk.co.androidapps4u.ProExpMgr.main.afterFirstLayout(main.java:98)

Please can anyone advise as why this is happening?

Thanks.
 
Top