Android Tutorial Protect your Android application with the Licensing library

Discussion in 'Tutorials & Examples' started by Erel, Sep 11, 2011.

  1. Erel

    Erel Administrator Staff Member Licensed User

    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:
    Sub Activity_Create(FirstTime As Boolean)
    Dim lc As LicenseChecker
    Dim p As PhoneId
    "lc", p.GetDeviceId, publicKey, "kljdflkf".GetBytes("UTF8"))
    "test_1""some secret value")
    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:

    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.

    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:
    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:
    Sub Process_Globals
    Dim publicKey As String
       publicKey = 
    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", p.GetDeviceId, publicKey, "kljdflkf".GetBytes("UTF8"))
    "test1""some secret value")
    End Sub
    Sub lc_Allow
    End Sub
    Sub lc_DontAllow
    ToastMessageShow("Closing application."True)
    End Sub
    Sub lc_Error (ErrorCode As String)
    Log("error: " & ErrorCode)
    ToastMessageShow("Closing application."True)
    End Sub
    Sub Activity_Pause(UserClosed As Boolean)
    End Sub
    Sub Activity_Resume

    End Sub
    The library is available here:
    Last edited: Jan 24, 2018
    dcoun, toby, JOTHA and 6 others like this.
  2. Highwinder

    Highwinder Active Member Licensed User

    Thank you!

    I'd like to thank you for getting this library written. I have some concerns about the B4A community getting caught with pants down when Google gets around to cancelling their old Copy Protection service, which they've been promising for a while now.

    THANK YOU for providing us with a way to use the new service! Whew!

    Looking forward to putting it to use!


    - Highwinder
    Prakaash likes this.
  3. Kamac

    Kamac Active Member Licensed User


    (It won't be useful for me as i can't sell anything)

    But still good job on this one ;)
  4. pjd

    pjd Member Licensed User

    why not ?!
  5. ondesic

    ondesic Active Member Licensed User

    One thing to keep in mind when using this license is that google strongly suggests that you obfuscate your code with progaurd. Google's license can be cracked very easily article here

    It would be nice to have an easy way from B4A to use progaurd.
  6. Erel

    Erel Administrator Staff Member Licensed User

    It is in the planned feature list.

    Note that the library itself is obfuscated and using SetVariableAndValue correctly should give you more protection.
  7. ondesic

    ondesic Active Member Licensed User

    I think google was talking about your entire code being obfuscated, not just the license library.

    Anyway, thanks for the info. I am glad this is in the planned feature list.
  8. magarcan

    magarcan Active Member Licensed User

    So, does have Internet is needed in order to every time user execute our application??

    Does B4A's Routing list is public??
  9. Erel

    Erel Administrator Staff Member Licensed User

    No. The result is cached locally.

    What do you mean with routing list?
  10. magarcan

    magarcan Active Member Licensed User

    I was asking for B4A's development road map, which features are you going to implement next, etc.
  11. Erel

    Erel Administrator Staff Member Licensed User

    Please start a new thread for questions not related to the thread topic.
  12. Inman

    Inman Well-Known Member Licensed User

    What will happen if the user

    • buys my app
    • runs it the first time and the Android Market license status get cached locally
    • then cancels the purchase and gets a refund within the allowed 15 minutes window
    When he runs my app the next time and the license check is called, will it still return "Allow", based on the result data that is cached locally?
  13. Erel

    Erel Administrator Staff Member Licensed User

  14. magarcan

    magarcan Active Member Licensed User

    Using this library is the way, if you don't like people cheat you. I'll use this in my new releases.

  15. peacemaker

    peacemaker Well-Known Member Licensed User

    So, if that copy protection works via Market application - at least for the first local permission info cashing - the Market must be internet conncted, isn't it ?
  16. Erel

    Erel Administrator Staff Member Licensed User

  17. Highwinder

    Highwinder Active Member Licensed User



    A few really horrible "Noob" questions about implementing the licensing lib:

    lc.SetVariableAndValue("test1", "some secret value")

    "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."

    How do I "test the value"? In what way is it tested? Can you show an example? Is it simply something like "If test1 = TheSecretValue then licensecheck = passes.with.flying.colors"?

    "lc.Initialize("lc", p.GetDeviceId, publicKey, "kljdflkf".GetBytes("UTF8"))"

    Erel, what does the "kljdflkf" represent? I believe you called this a "Salt"? What is this and how is it used? Is length arbitrary or defined? Please elaborate.

    "lc.SetVariableAndValue("test1", "some secret value")"

    Can you please explain the "some secret value" part of that line? Is this supposed to be a number, letter, or otherwise random string of our choosing? Please elaborate for us "LCD noobs" who are sometimes a little slow at getting our heads around things. :)

    And once again, THANK YOU for providing this functionality!

    Highwinder the :sign0104:
    Last edited: Oct 8, 2011
  18. Erel

    Erel Administrator Staff Member Licensed User

    2) See this article for more information about salt: Salt (cryptography) - Wikipedia, the free encyclopedia
    The string length is not really important.

    1, 3) SetVariableAndValue is an optional feature which you can use to strengthen the protection.
    A hacker can decompile your code, remove the CheckAccess call and compile it again. The hacked program will now work without doing any license check.
    If however you did use SetVariableAndValue and CheckAccess is skipped then the variable value will not be set.
    You should somewhere in your code do something with this variable which will fail if the variable was not set.

    You should try to make it not too obvious. For example use the variable only further down the road. Instead of testing its value you can use its value. For example as the limiter of a For loop.
  19. Kevin

    Kevin Well-Known Member Licensed User

    I plan to implement this in my paid app soon, but just wanted to clarify something. From reading your tutorial as well as the info on the Android site, I assume that the library (or at least your sample code) uses the "Server Managed Policy" as opposed to a "Strict" or "Custom" policy?

    I think for simplicity's sake I would prefer the managed policy, but I am curious which one we are actually using when using this library, and was also wondering if it would allow us to use the other policies if we wanted to.
  20. Erel

    Erel Administrator Staff Member Licensed User

    This library is using the recommended "server managed policy".
    It can be possible to add other policies in the future, though this policy is supposed to be the best option in almost all cases.
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice