Registration¶
How Registration Works¶
The Surfmeter Mobile Quality SDK uses a license-based registration system to manage access. Before your app can run any quality measurements, the device must be registered against the Surfmeter server using a registration key provided by AVEQ.
A registration key controls:
- How many devices can register with it (a finite counter, or unlimited)
- How long each device may use the SDK after registering (optional usage limit in days)
- When the key is valid (“valid until” – a time window) – this controls when new registrations are accepted, but does not affect already-registered devices
- Which measurement types and subjects the device is allowed to run (capabilities)
When a device registers, the server decrements the key's registration counter, creates a client record, and returns a unique device identity (UUID + secret) along with any configured capabilities and expiration details. These credentials are stored encrypted on the device and used for all subsequent API calls.
Registration Lifecycle¶
The following diagram shows the full lifecycle from registration to expiration or unregistration. Understanding this lifecycle is important for integrators, because registered devices count toward your billing unless they are explicitly unregistered.
flowchart TD
A[App starts] --> B{Device registered?}
B -- No --> D["Integrator calls registerClientAsync()"]
B -- Yes --> C[Use stored credentials]
D --> E{Server validates key}
E -- Invalid or expired key --> F[Registration failed]
E -- No registrations left --> F
E -- Valid --> G["Server creates client,<br>decrements registration counter;<br>SDK stores UUID, secret,<br>capabilities, expiration locally"]
G --> C
C --> T["Integrator creates QualityTest"]
T --> J{SDK checks:<br>registration expired?}
J -- Yes --> L["SDK calls returnLicense() automatically;<br>client disabled on server,<br>device must re-register with valid key"]
J -- No --> U{SDK checks:<br>type and subject allowed<br>by capabilities?}
U -- No --> V["SDK throws IllegalStateException"]
U -- Yes --> K[Test runs]
K --> M{App lifecycle event}
M -- Continue --> T
M -- Device decommissioned --> N["Integrator calls unregisterClientAsync();<br>server disables client and<br>increments registration counter"]
Billing Implications¶
Registered devices are counted toward your license usage. To avoid being billed for devices that are no longer in use, you must actively unregister them. The server does not automatically free registration slots for inactive devices.
Always unregister devices you no longer need
When a device is decommissioned, replaced, or no longer running measurements, call unregisterClientAsync() to return the license. This frees the registration slot so it can be reused by another device, and ensures the device is no longer counted for billing.
If you are unable to do so, you can manually disable the client in our Surfmeter web GUI. Or, please let us know the device UUIDs so we can manually free the slots on our end.
If a device's registration expires due to a usage limit, the SDK automatically returns the license. However, if there is no usage limit configured, the device stays registered indefinitely until explicitly unregistered.
Registration Example¶
Use the provided Registry class and call registerClientAsync with your license key. Registration is a one-time process per device -- the credentials are persisted in the app's encrypted preferences.
import com.aveq.qualitytestlib.Registry;
Registry registry = Registry.Builder(this).forSurfmeterQualitySdk().build();
if (registry.isClientRegistered()) {
return;
}
registry.registerClientAsync(
"REPLACE_WITH_YOUR_REGISTRATION_KEY",
"your-client-label", // optional: a label to identify the client (must be unique across all your clients)
null, // optional: pass an ArrayList of strings here, which serve as tags for the client
new Registry.OnClientRegisteredListener() {
@Override
public void onClientRegistered() {
// store the state that the client is registered
}
@Override
public void onClientRegistrationFailed(RuntimeException e) {
// log or display an error
}
}
);
Notes:
- Your implementing application should also store the state that the client is registered to avoid redundant registrations or checks.
- The registration key is provided by AVEQ. If it does not work, please contact us.
- Registration should be done asynchronously to avoid blocking the main thread. While a synchronous registration method exists, it is not recommended for production code.
Unregistration¶
When a device is no longer needed, call unregisterClientAsync() to return the license to the pool. This disables the client on the server and increments the registration counter, making the slot available for another device.
registry.unregisterClientAsync(new Registry.OnClientUnregisteredListener() {
@Override
public void onClientUnregistered() {
// client has been unregistered, clear local state
}
@Override
public void onClientUnregistrationFailed(RuntimeException e) {
// handle error
}
});
You should call this when:
- A device is being decommissioned or removed from your fleet
- A device is being replaced by a new one
- You are cleaning up test or development devices
- The app is being uninstalled (if you can intercept this event)
Remote Device Registration via ADB¶
For automated deployments or testing scenarios where you cannot manually enter a registration key, the SDK demo app supports auto-registration via an Android intent. This allows you to register the app on remote devices via ADB without any manual interaction.
First, grant the required permissions:
adb shell pm grant com.aveq.qualitytestlibdemo android.permission.ACCESS_FINE_LOCATION
adb shell pm grant com.aveq.qualitytestlibdemo android.permission.ACCESS_COARSE_LOCATION
adb shell pm grant com.aveq.qualitytestlibdemo android.permission.READ_PHONE_STATE
adb shell pm grant com.aveq.qualitytestlibdemo android.permission.POST_NOTIFICATIONS
Then send the registration intent:
adb shell am start -n com.aveq.qualitytestlibdemo/.MainActivity \
-a com.aveq.qualitytestlibdemo.action.REGISTER \
--es registration_key "YOUR_REGISTRATION_KEY" \
--es label "Device-001" \
--esa tags "production,eu-west"
Intent Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
registration_key |
String | Yes | The license key provided by AVEQ |
label |
String | No | A unique identifier for this device/client |
tags |
String Array | No | Comma-separated tags for categorization |
On successful registration, the client UUID will be logged to logcat under the Surfmeter.MainActivity tag.
Capabilities¶
Capabilities define which measurement types and subjects a device is allowed to run. They are configured server-side, associated with a registration key, and transmitted to the device during registration.
If no capability is assigned to a registration key, all test types and subjects are allowed by default.
How Capabilities Work¶
A capability consists of lists that control access:
allowed_measurement_types-- measurement types the client may run. An empty list means all types are allowed.allowed_measurement_subjects-- specific services or platforms the client may measure. An empty list means all subjects are allowed.
The Mobile Quality SDK currently supports two measurement types:
video-- video streaming quality tests (VideoQualityTest, ExoPlayerQualityTest)web-- web page loading performance tests (WebQualityTest)
The video type supports the following subjects: youtube, netflix_trailer, facebook, instagram, tiktok, hotstar, exoplayer.
The web type only supports website.
Note
The server-side capability system supports additional measurement types (e.g., network, speedtest, conferencing) and their corresponding subjects. These are used by other Surfmeter products but are not available in the Mobile Quality SDK. If a capability restricts your key to types or subjects not supported by this SDK, the affected tests simply cannot be created.
Querying Capabilities¶
After registration, you can inspect the client's capabilities using Registry.getCapability():
Registry registry = new Registry.Builder(context).forSurfmeterQualitySdk().build();
HashMap<String, ArrayList<String>> capabilities = registry.getCapability();
if (capabilities == null) {
// No restrictions — all test types and subjects are allowed
} else {
ArrayList<String> allowedTypes = capabilities.get("allowed_measurement_types");
ArrayList<String> allowedSubjects = capabilities.get("allowed_measurement_subjects");
// These extra fields exists but are typically not set
ArrayList<String> forbiddenTypes = capabilities.get("forbidden_measurement_types");
ArrayList<String> forbiddenSubjects = capabilities.get("forbidden_measurement_subjects");
}
Querying capabilities is useful if you want to adapt your UI -- for example, to only show measurement options that the client is permitted to use.
Automatic Enforcement¶
You do not need to check capabilities manually before running a test. The SDK automatically validates the requested test type and subject when a QualityTest is instantiated. If the test is not permitted, the constructor throws an IllegalStateException:
try {
VideoQualityTest test = new VideoQualityTest.Builder(context)
.setUrl("https://www.youtube.com/watch?v=...")
.setSubject("youtube")
.build();
} catch (IllegalStateException e) {
// "Test type or subject not allowed by capability"
}
Registration Expiration¶
There are two independent expiry mechanisms that can cause a device's registration to end. Both are configured server-side and associated with the registration key.
Per-device usage limit¶
A registration key can define a usage limit in days. When a device registers, the server computes an expiration timestamp (registration time + usage_limit_days) and transmits it to the device. The SDK stores this timestamp locally.
The SDK checks for expiration whenever the stored credentials are accessed -- for example, when instantiating a QualityTest. If the expiration has passed at that point, the SDK calls returnLicense() on the server, clears the local credentials, and throws an IllegalStateException. There is no background timer; the check happens lazily on the next SDK operation that requires credentials.
This is a hard client-side expiration: once triggered, no new tests can be created until the device re-registers with a valid key.
Registration key "Valid until" date¶
Each registration key has an optional "Valid until" date, visible in the Surfmeter admin GUI. This date controls when new devices can register with the key. After it passes, new registrations are rejected.
For already-registered devices, this expiration is not yet enforced locally. In practice, this means a device with an expired key continues to produce measurements and deliver them to the integrator's onTestResult callback, but the results are not transmitted to the Surfmeter server.
Checking remaining time¶
You can check the remaining time for the per-device usage limit using Registry.getExpirationDetails():
Registry registry = new Registry.Builder(context).forSurfmeterQualitySdk().build();
Registry.ExpirationInfo expiration = registry.getExpirationDetails();
if (expiration == null) {
// No expiration set, or client is not registered
} else {
long remaining = expiration.value;
TimeUnit unit = expiration.unit;
// e.g. "Registration expires in 25 DAYS"
}
This method returns null when no expiration is configured (the registration does not expire), when the expiration has already passed, or when the client is not registered.
Note
getExpirationDetails() only reflects the per-device usage limit. It does not account for the registration key's "Valid until" date, which is only enforced server-side.