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:

magarcan

Active Member
Licensed User
Longtime User
In Process_Globals I've:
'Activity module
Sub Process_Globals
Dim publicKey As String
publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBC***********************+NwgcVTr1JPH6yOK+e/lnYUeSucG6Ak/rSe/pgZQGSHkp8eLZQXXe0T7M9g9DsSNvFLcMTrDBFPGvYW03ncXlV91V/Fusrk+TbyO8yfz++XVSiH2e8RL8jaVWEkyQt6UI4TOFAufUPegk0a6jc/45Ga9/z3ZWyFz12pG2QYYcjIjLQaBfiQIDAQAB"'Poner mi número
Dim esp As Boolean
Dim PosicionMenu As Int

End Sub

Do I need any other variables?
 
Last edited:

magarcan

Active Member
Licensed User
Longtime User
The test1 variable should be declared as a process global variable (of type string).

See the example in the first post.
Now it's working. I forgoten include it :sign0013:

Now I'm having another problem. I know that License is saved in caché, but if I'm not conected to Internet, I always appear as unlicensed, and app gets closed.

If I'm connected, there is no problem at all...

Any idea?

PD: I'm using the same code that in the example (license is checked on Activity_Create).
 

William Hunter

Active Member
Licensed User
Longtime User
Licensing library

I had thought I would use the Licensing library in an app I’m about to submit to Google Play. I’m having second thoughts for two reasons.

1. I don’t like that the app cannot be installed to a SD card. This may be a part of Google’s copy protection scheme. If so, their reasoning escapes me.

2. I have tested with the app installed to a device, and I get the correct responses for LICENSED or UNLICENSED using the appropriate setting in the developer’s console. So, I know that copy protection is working OK. In reading comments in this thread I get the impression that there must always be online access to the Google server in order to validate the app as being licensed. If this is so, this is a deal breaker for me.

I would like a means of testing this before submitting my APK. But, there doesn’t seem to be a way to do this. Does anyone have an app that has been installed to a device from Google Play, and can describe how this copy protection is seen by the licensed end user? Is always being online, when running the app, required for validation? Or, is this a one time online validation process that writes licensing approval to the device?

I would appreciate comment on the subject from those that have gone down this road before.

Regards :)
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
1. There is no problem with installing a protected app to the SD card. This was a limit of the deprecated copy protection method.

2.
In reading comments in this thread I get the impression that there must always be online access to the Google server in order to validate the app as being licensed.
This is not correct. The policy is described in the link I posted in post #85.

In order to fully test your app you can activate your app, download it and then deactivate your app. Though if it works properly when you test it now then it is expected to work properly for all customers.
 

johnaaronrose

Active Member
Licensed User
Longtime User
Simplification required

There are so many messages & so much advice in this thread that I am not able to understand what I should do. Can someone please clarify? Also, if this procedure is followed, will I be able to test my app on emulator or my device directly (i.e. without uploading the app to Google Play & then downloading it)?
 

William Hunter

Active Member
Licensed User
Longtime User
There are so many messages & so much advice in this thread that I am not able to understand what I should do. Can someone please clarify? Also, if this procedure is followed, will I be able to test my app on emulator or my device directly (i.e. without uploading the app to Google Play & then downloading it)?

Hello John,

If you find things a little confusing, don’t be overly concerned, you’re not alone.
Help for Google Developers provides this information:

“Purchasing your own applications
Please note that it is against Google Checkout's policies to purchase your own application. You will receive an error message when you try to purchase your own application.” I could find no other possible means provided for a developer to do a TEST install directly from GOOGLE, and I've read Google's Help file until blue in the face.

This can be viewed at:
Viewing and purchasing your own apps - Google Play for Developers Help

The only way that I have found to test the Google copy protection is through the Developer Console using my application installed to a device. Trying to test with the emulator does not work. If copy protection is set up properly you will get the correct responses for LICENSED or UNLICENSED using the appropriate setting in the developer’s console.

Erel has previously explained that if copy protection works properly when you test it in this manner, then it is expected to work properly for all customers.

I would like a better way of testing this myself, but as I understand it this is the only way. I hope this helps.

Regards
 

johnaaronrose

Active Member
Licensed User
Longtime User
Hello John,

If you find things a little confusing, don’t be overly concerned, you’re not alone.
Help for Google Developers provides this information:

“Purchasing your own applications
Please note that it is against Google Checkout's policies to purchase your own application. You will receive an error message when you try to purchase your own application.” I could find no other possible means provided for a developer to do a TEST install directly from GOOGLE, and I've read Google's Help file until blue in the face.

This can be viewed at:
Viewing and purchasing your own apps - Google Play for Developers Help

The only way that I have found to test the Google copy protection is through the Developer Console using my application installed to a device. Trying to test with the emulator does not work. If copy protection is set up properly you will get the correct responses for LICENSED or UNLICENSED using the appropriate setting in the developer’s console.

Erel has previously explained that if copy protection works properly when you test it in this manner, then it is expected to work properly for all customers.

I would like a better way of testing this myself, but as I understand it this is the only way. I hope this helps.

Regards

William,

Thank you for your reply.

Should I code the copy protection procedure as per Erel's zip file or should I use amendments as shown in the message thread?

If I understand you correctly, you say that when the copy protection procedure is followed, I will be able to run my app on my device directly (i.e. the app will not object because I have installed it to my device without using Google Play)? Currently, I am not able to compile my app to my ZTE Blade phone (even Erel has not been able to work out a solution to this) and install it using the .apk that I have copied to my sdcard. Will the copy protection object to an app installed this way?
 
Last edited:

William Hunter

Active Member
Licensed User
Longtime User
William,

Thank you for your reply.

Should I code the copy protection procedure as per Erel's zip file or should I use amendments as shown in the message thread?

If I understand you correctly, you say that when the copy protection procedure is followed, I will be able to run my app on my device directly (i.e. the app will not object because I have installed it to my device without using Google Play)? Currently, I am not able to compile my app to my ZTE Blade phone (even Erel has not been able to work out a solution to this) and install it using the .apk that I have copied to my sdcard. Will the copy protection object to an app installed this way?

Hi John,

Use the MORE COMPLETE EXAMPLE at the beginning of this thread. Pay attention to placing the underscore in “Dim test_1 As String”, if you use obfuscate when compiling.

You will be able to run the application on your device directly for testing purposes only. If you do not use the Developers Console settings for this purpose, the application will always close with the ToastMessage “Closing application”.

When you setup in the Developers Console for a License Test Response of LICENCED, your application should run normally. If you set the License Test Response to NOT_LICENSED, your application should ALWAYS close with the ToastMessage “Closing application”. If you get these responses, this indicates that copy protection is working as it should.

I am not familiar with the ZTE Blade phone. But I would think that you should be able to install the application by clicking on the APK you have copied to the SD card. The copy protection has no effect on installation, only on running the application.

You say that you are having a problem installing your application to your phone, and that Erel has been unable to help you with a solution. I’m no expert in this area, and Erel has far more knowledge than I. I hope that my comments are in some way helpful to you.

Regards
 

William Hunter

Active Member
Licensed User
Longtime User
@johnaaronrose

Hello again John,

I found a previous post of yours, entitled ZTE Blade driver which included the following PS:

“PS it would be nice to have a Compile only facility: then I could transfer the .apk file to the phone's sdcard using Windows Explorer & install my app from the sdcard.”

You can compile to an APK without running the AVD Manager, or bridging to a device. Use the hot keys ALT + 3 to compile in the background. You will get an error message at the end of compile stating, “No device found”. Take no notice of this, as your APK will have been successfully created. :icon_clap:

Regards
 

johnaaronrose

Active Member
Licensed User
Longtime User
@johnaaronrose

Hello again John,

I found a previous post of yours, entitled ZTE Blade driver which included the following PS:

“PS it would be nice to have a Compile only facility: then I could transfer the .apk file to the phone's sdcard using Windows Explorer & install my app from the sdcard.”

You can compile to an APK without running the AVD Manager, or bridging to a device. Use the hot keys ALT + 3 to compile in the background. You will get an error message at the end of compile stating, “No device found”. Take no notice of this, as your APK will have been successfully created. :icon_clap:

Regards

William,

That's what I do when I want to test the app on my ZTE Blade. I then connect the ZTE Blade by usb cable to my PC & switch on 'USB Storage' (on the Blade). This results in my PC showing the sdcard (on the Blade) as a Removeable Disk. So I copy the .apk from my PC to the sdcard using Nautilus (Ubuntu uses this as standard GUI equivalent of File Manager: I do not use Windows). But this is convoluted, especially as I have to turn off USB Storage (on the Blade) before installing the app (from the sdcard) & then running the app on the Blade.

I can connect my Blade wirelessly to my router (in fact my app uses this connection to download the app's database from the internet i.e. without going through my PC). I have my PC connected by ethernet cabling to my router. I really don't understand why B4A Bridge doesn't work. Is it intended that the PC & the device should communicate directly without going through the router?

BTW I have Cyanogen Mod 7.2 (which uses Android 2.3.3) installed on the Blade: first thing that I did on the Blade was to install it in order to upgrade it from 2.1 & remove Orange's rubbish Android install.
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
I've posted another problem (on another thread) but Erel has not yet replied. When i want to upload my app to Google Play now that I'm a registered developer & merchant in Google Play it shows:
".. does not accept apks signed with the debug certificate. Create a new certificate that is valid for at least 50 years.".
I have compiled the app with Release (not Debug). I have an Enterprise Licence for B4A (bought in June2012). Do you have any ideas how to fix this?
Please do not post duplicate questions. I've answered to your other thread.
 

johnaaronrose

Active Member
Licensed User
Longtime User
Duplicate question removed from previous message. Apologies.

I noticed that the first message on the thread used GetDeviceId. Looking at the documentation, it states that a WiFi only device will give an empty string for this command. I feel that tablet users may have no phonne SIM card and are using WiFi. Is there another way of verifying that the user has paid the app's fee (through Google Play)? I thought that their email id might be a reasonable check.

I also noticed in this thread that there is code to check if the app is being run on the emulator so that this could be allowed. Is there an additional check available for this scenario?
 

johnaaronrose

Active Member
Licensed User
Longtime User
No hacking allowed

I'm getting a "" value in test_1 which I'm using to store my secret value (I've changed it to "abcd" below). From the log shown below, it can be seen that CheckLicense is called, but none of lc_Allow, lc_Dontallow or lc_Error is invoked. Could it be something to do with lc.SetVariableAndValue("test_1", secret) and test_1 = secret not being the same?


B4X:
Sub Process_Globals
  Private publicKey As String
  publicKey = "MIIBIjANBg........"
  Private test_1 As String
  Private secret As String
  secret = "abcd"
End Sub

Sub Activity_Create
  Private p As Phone
  Log("PhoneModel="&p.Model)
  If p.Model = "sdk" Then
    'emulator -> jump to Allow
    AllowEmulator
  Else
    'check license
    CheckLicense
  End If
End Sub

Sub Activity_Resume
  If test_1 <> secret Then
    Log("No hacking allowed")
    Log("test_1="&test_1)
    ToastMessageShow("No hacking allowed: Closing application.", True)
    Activity.Finish
  End If
End Sub

Sub AllowEmulator
  Log("Allow Emulator")
  test_1 = secret
End Sub

Sub CheckLicense
  Log("CheckLicense")
  Dim lc As LicenseChecker
  Dim p As PhoneId
  lc.Initialize("lc", p.GetDeviceId, publicKey, "malach".GetBytes("UTF8"))
  lc.SetVariableAndValue("test_1", secret)
  Log("test_1="&test_1)
  ToastMessageShow("test_1="&test_1, True)
  lc.CheckAccess
End Sub

Sub lc_Allow
  Log("Allow")
End Sub

Sub lc_DontAllow
  Log("DontAllow")
  ToastMessageShow("License check fails: Closing application.", True)
  Activity.Finish
End Sub

Sub lc_Error (ErrorCode As String)
  Log("License Check Error: " & ErrorCode)
  ToastMessageShow("License check error: Closing application.", True)
  Activity.Finish
End Sub

Log extract:
** Activity (main) Create, isFirst = true **
PhoneModel=Blade
CheckLicense
test_1=
** Activity (main) Resume **
No hacking allowed
 

William Hunter

Active Member
Licensed User
Longtime User
No hacking allowed

I'm getting a "" value in test_1 which I'm using to store my secret value (I've changed it to "abcd" below). From the log shown below, it can be seen that CheckLicense is called, but none of lc_Allow, lc_Dontallow or lc_Error is invoked. Could it be something to do with lc.SetVariableAndValue("test_1", secret) and test_1 = secret not being the same?

I'm not sure as to just what you are trying to accomplish. But, you are not using DIM in your code when you should. :signOops:

Regards
 

johnaaronrose

Active Member
Licensed User
Longtime User
Private changed to Dim

I'm not sure as to just what you are trying to accomplish. But, you are not using DIM in your code when you should. :signOops:

Regards

I changed Private to Dim for the appropriate variables in my app. After compiling, uninstalling existing version, installing changed version & running, it gave same result. I was not surprised by the same result, as IMO Private in Process_Globals is exactly equivalent to Dim in Process_Globals.

I am trying to achieve the allowing of the emulator (when running an app) by the license checking procedure as detailed in post #43 of this thread written by Erel.
 

William Hunter

Active Member
Licensed User
Longtime User
I am trying to achieve the allowing of the emulator (when running an app) by the license checking procedure as detailed in post #43 of this thread written by Erel.

Use the MORE COMPLETE EXAMPLE at the beginning of this thread, then use something like the code below at the beginning of Activity_Create. You may or may not wish to use FirstTime.
B4X:
Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
   Dim p As Phone
   If p.Model <> "sdk" Then
      Dim lc As LicenseChecker
      Dim p As PhoneId
      lc.Initialize("lc", p.GetDeviceId, PublicKey, "jubnmtgs".GetBytes("UTF8"))
      lc.SetVariableAndValue("test_1", "whatever")
      lc.CheckAccess
   End If
   ' continue with rest of code here
End If
   ' continue with rest of code here
End Sub

I hope this helps.
Regards
 

johnaaronrose

Active Member
Licensed User
Longtime User
Use the MORE COMPLETE EXAMPLE at the beginning of this thread, then use something like the code below at the beginning of Activity_Create. You may or may not wish to use FirstTime.
B4X:
Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
   Dim p As Phone
   If p.Model <> "sdk" Then
      Dim lc As LicenseChecker
      Dim p As PhoneId
      lc.Initialize("lc", p.GetDeviceId, PublicKey, "jubnmtgs".GetBytes("UTF8"))
      lc.SetVariableAndValue("test_1", "whatever")
      lc.CheckAccess
   End If
   ' continue with rest of code here
End If
   ' continue with rest of code here
End Sub

I hope this helps.
Regards

William,

Thanks for your reply. Unfortunately it won't make any difference because it's effectively the same as my existing code: the only difference is that the 'continue with rest of code here' are replaced by AllowEmulator & CheckLicense subs. I thought I'd found the problem because I was using the same variable name (p) for both the Phone & PhoneId type variables. I changed that but it made no difference i.e. test_1 was still "" when running on my Blade phone. I'll take another look at it tomorrow.
 
Top