I’m trying to integrate LexActivator into my application. When following the examples, they call SetLicenseCallback, then call IsLicenseGenuine to check if the current license is activated/expired/etc.
I find, if I change anything through the dashboard, the first call to IsLicenseGenuine will not return updated info. It’s only until the callback returns the first time after IsLicenseGenuine is called can I get the up to date info.
For example, a license is activated that will expire in 180 days. The app is closed.
In the dashboard I extend the license to 360 days.
I relaunch the app and the first call to IsLicenseGenuine still reports expiry in 180 days.
First callback executes.
Now IsLicenseGenuine will report the correct, updated, 360 days.
This is also an issue if I were to deactivate an activation in the dashboard. IsLicenseGenuine will report everything is fine (license activated) and then the callback will run only then correctly reporting the license was deactivated.
Is there any way to force a sync with the server before calling IsLicenseGenuine? I’d rather not do something weird like, call it, wait for the callback, then call it again to get the real info.
The callback gives you the license status after the server sync succeeds. If IsLicenseGenuine() returns LA_EXPIRED and callback status is LA_OK, this would mean the license is renewed. Similarly for license deactivations.
IsLicenseGenuine() does async server sync which doesn’t block your main thread, and this is per design. If you still want to force a synchronous blocking server sync just call ActivateLicense() function again (but this will not help in case the license was deactivated).
This is my first foray into license via cloud like Cryptlex, so maybe my implementation doesn’t fit this scheme so I appreciate any advice and your time. I am trying to make decisions on app start:
On app start, I need to decide either to:
finish launching because the license is LA_OK
or close because license is LA_EXPIRED/LA_REVOKED/LA_SUSPENDED/LA_FAIL/etc.
If the status of the license has changed (say deactivated by the user through the customer portal) while the app is not running, then my first call on app start to IsLicenseGenuine() will not have the latest license status from the server. Therefore, at my above decision point at app start I will finish launching, when I should actually be closing.
You mention calling ActivateLicense() again to force a sync, but as you said, this will not work out well if the user has used the customer portal to deactivate the license while the app was not running. It will just reactivate the license again causing more issues.
Should I call IsLicenseGenuine() twice? Add a small sleep to wait for the first async server sync? Your advice is most appreciated.
In your case add a check for status in the license callback, if it is not success then exit the app immediately. This way the app will exit within 3 secs if the license has expired or activation deleted. Also ensure that you ignore the LA_E_INET status code in the callback (the network error).
If anyone else is stuck here. Here is how i solved it in go
func waitForSyncCallback(done chan bool) func(int) {
return func(status int) {
select {
case done <- true:
default: // Do nothing if channel is filled
}
}
}
func main() {
// setup stuff ...
synced := make(chan bool, 1)
lexactivator.SetLicenseCallback(waitForSyncCallback(synced))
// start thread to wait for sync
_ = lexactivator.IsLicenseGenuine()
select {
case <-synced:
fmt.Println("License sync complete")
case <-time.After(5 * time.Second):
fmt.Println("Timeout")
synced <- false
}
// update license status
status = lexactivator.IsLicenseGenuine()
}
A blocking version of IsLicenseGenuine would’ve been preferred though… In my case, I call lexactivator in a subprocess that exits quickly so the server sync never happens without the block.