Radioplayer Developer Reference
Automotive Tracking SDK
Technical documentation for implementing Radioplayer automotive data tracking.
This is the documentation for the Radioplayer Automotive SDK, version 2.1.1.
General principles
The SDK allows the user to track events which will be collected by the Radioplayer Data Platform.
Annotation-Based Implementation
To keep code maintainable and consistent, the Radioplayer Automotive Data Tracking SDK recommends an annotation-based approach to instrumentation. Instead of inserting trackEvent() calls inside business logic, developers declare tracking intent via annotations , and a separate processing tool injects the required tracking logic.
Benefits
- Clarity: tracking points are explicit and easy to spot.
- Separation of concerns: business logic stays clean—no analytics boilerplate.
- Consistency: event-specific annotations enforce the correct schema and required fields.
- Maintainability: schema changes are handled by updating annotation definitions, not scattered call sites.
Annotate the callee, not every call site
Place tracking annotations on the method being called (the callee), rather than on each location where it’s invoked.
Why this matters
- Reduced duplication: one instrumentation block covers all callers.
- Consistent capture: the same arguments/context are collected on every entry.
- Single point of change: updates happen once, in the annotated method.
Tracker Initialization and Configuration
SDK Access & Authentication
Radioplayer adopts a Service Account Pattern to ensure scalability, security, and fine-grained access control. To integrate the Radioplayer Automotive Data Tracking SDK, please adhere to the following access protocols:
- Repository: The SDK is hosted within a private GitHub repository.
- Access Provisioning: Access is granted exclusively through a dedicated Radioplayer service account.
- Authentication: Authentication is handled via GitHub Personal Access Tokens (PATs) , which will be provided directly by the Radioplayer team upon request.
- Permissions: For security purposes, all provided access is strictly read-only.
How to import the Radioplayer Automotive Data Tracking SDK
In
settings.gradle.kts, adddependencyResolutionManagementsection:dependencyResolutionManagement { // ... repositories { // ... maven { url = uri("https://maven.pkg.github.com/Radioplayer/dataplatform-automotive-tracking-sdk") credentials { username = "<github_username>" password = "<your_PAT_with_packages:read>" } } // ... } // ... }Add the following code to the
dependenciessection of yourbuild.gradle.kts (:yourApp):implementation("org.radioplayer.automotivesdk:sdktracking:2.1.1") annotationProcessor("org.radioplayer.automotivesdk:sdkprocessor:2.1.1") annotationProcessor("org.radioplayer.automotivesdk:sdkannotation:2.1.1")Check your setup and use:
For older API level (e.g. 28) and Java version < Java 9, you may need to add this in
build.gradle.kts (:yourApp):implementation "androidx.lifecycle:lifecycle-common-java8:2.2.0"For newer API level and Java version >= Java 9
you likely have to add or modify this variable in
gradle.propertiesin order tojavacarguments:// in this example, we used Java 17 org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 \ --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \ --add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \ --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \ --add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \ --add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED \ --add-modules=jdk.compiler org.gradle.java.home=/usr/lib/jvm/jdk-17.0.12-oracle-x64For dependency issues, we recommend forcing them to the desired version in
build.gradle.kts :root:// e.g. allprojects { configurations.all { resolutionStrategy { force( "androidx.core:core:1.12.0", "androidx.core:core-ktx:1.12.0", "androidx.appcompat:appcompat:1.6.1", "androidx.appcompat:appcompat-resources:1.6.1", "androidx.activity:activity:1.7.2", "androidx.activity:activity-ktx:1.7.2", "androidx.constraintlayout:constraintlayout:2.1.4", "androidx.profileinstaller:profileinstaller:1.3.1", "androidx.annotation:annotation-experimental:1.3.1" ) } } }
Add these imports to every class you want to annotate:
import org.radioplayer.automotiveSDK.EventFactory.action.*; import org.radioplayer.automotiveSDK.EventFactory.listening.*; import org.radioplayer.automotiveSDK.EventFactory.setValue.*; import org.radioplayer.automotiveSDK.EventFactory.EventManager; import org.radioplayer.automotiveSDK.Tracker; import org.radioplayer.automotiveSDK.annotation.*;Add these uses-permission to
AndroidManifest.xmlfile:<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Initialization and Configuration
Once you have imported the Radioplayer Automotive Data Tracking SDK files and integrated the code with annotations and related fields, you must explicitly start tracking to begin collecting data from your application. To do this, you need to call the initialize and then the startTracking methods of TrackingSDK object.
To ensure the tracker functions correctly, it must be configured, preferably when your application first starts. The following example demonstrates how to set up the TrackingSDK object.
import org.radioplayer.automotiveSDK.TrackingSDK;
// ...
TrackingSDK sdk = TrackingSDK.getInstance();
sdk.initialize(
this, //context
"SDKAndroidAppDemo", //appName
"1.0.0", //appVersion
platformId, // provided by RP
productId, // provided by RP
new VehicleInfo("Jade Dragons Inc.", "Qilin",2022), //vehicle info
apiUrl, //apiUrl - provided by RP
appKey, //appKey - provided by RP
debug // boolean to enable verbose debug logging
);
sdk.startTracking(debug, catalogCountryCode, null);
Please note that once one of these start functions has been called and data collection has begun, you cannot restart it unless stopTracking is called (consecutive calls to start method without calling stopTracking will be ignored).
Default Event Params
Certain information must be associated with each event, regardless of its categorization. Parameters such as the application name (appName), application version (appVersion), platform (platformId) and product (productId) identifiers are defined only once, when the TrackingSDK is initialized, and must remain constant throughout the application execution. These parameters must be defined when initializing the SDK, as they form part of its configuration settings.
The values should be specified in the following manner:
sdk.initialize(
this, //context
"SDKAndroidAppDemo", //appName
"1.0.0", //appVersion
platformId, // provided by RP
productId, // provided by RP
new VehicleInfo("Jade Dragons Inc.", "Qilin",2022), //vehicle info
apiUrl, //apiUrl - provided by RP
appKey, //appKey - provided by RP
debug // boolean to enable verbose debug logging
);
Other parameters, such as the catalog country code (catalogCountryCode), are passed directly to the new startTracking methods at start-up. The catalogCountryCode can be modified at any time after initialization using updateCatalogCountryCode respectively. Below is an example for each function.
updateCatalogCountryCode("250")
The string passed to updateCatalogCountryCode function must be a valid_ISO 3166-1_ numeric country code: it must comply with the format of the standard and be associated with an existing nation. If the debug mode is active, the SDK will alert the developer if there are errors with these parameters values.
Debug Mode
To activate the SDK debug mode, you will simply need to pass true as the first debug parameter in the start method).
sdk.startTracking(
true, //debug
...);
In the logcat console, in addition to possible warnings about listening session management, the following debug information will also be displayed:
- Each tracked event, along with the collected parameters.
- Whether the events are received correctly by the Radioplayer dataplatform. In case of error or warning, it will be reported and the error type will also be shown.
TrackingSDK: All available functions
Initialize the TrackingSDK: initialize()
Initialize tracking of application data.
Parameters
| Name | Type | Description |
|---|---|---|
context | Context | The current application or activity context. It is essential for the SDK to access system resources https://developer.android.com/reference/android/content/Context |
appName | String | The name of your app/infotainment application. Identifies the app that integrates the SDK |
appVersion | String | The version of your app/infotainment application. Version number in format ‘x.x.x’ |
platformId | String | Identify the platform where the application is running (provided by Radioplayer) |
productId | String | Identify the specific application into RP products (provided by Radioplayer). |
car | VehicleInfo | An object containing details about the vehicle to which the user is connected. You must call the constructor (e.g., new VehicleInfo(...)) and pass the required parameters for the manufacturer, model, and year (more information here) |
collectorEndpoint | String | The endpoint URL of the data collector. This is where the SDK sends the tracked data |
apiKey | String | A unique key for your application, used to authenticate with the tracking service |
isDebugMode | Boolean | Indicates whether the instance is in debug mode |
Start tracking method : startTracking()
Start tracking of application data.
Parameters
| Name | Type | Description |
|---|---|---|
debug | Boolean | A Boolean flag. indicates whether the SDK should be started in debug mode. If true, enables verbose logging for troubleshooting purposes |
catalogCountryCode | String | The numeric country code, typically compliant with the ISO 3166-1 standard (see Appendix.A) |
initialConsent | CmpConsent | the CmpConsent to apply at startup; if null, the last persisted consent is loaded from shared preferences (more information here) |
Stop tracking method : stopTracking()
Stops the collection of data generated through the use of the Trackable tags.
Update catalog country code: updateCatalogCountryCode(catalogCountryCode)
Updates the catalog country code stored by the SDK.
Parameters
| Name | Type | Description |
|---|---|---|
catalogCountryCode | String | New ISO 3166-1 numeric country code selected by the user (see Appendix.A) |
Update consent: updateConsent(newConsent)
Updates the consent stored by the SDK.
Parameters
| Name | Type | Description |
|---|---|---|
newConsent | CmpConsent | the new CmpConsent to apply; ignored if null |
Geo Localization Tracking
The Tracking SDK automatically manages user location tracking based on the Android permissions granted. The system dynamically adapts to changes in permissions in real time, ensuring privacy compliance and always using the best level of accuracy available.
Event Buffer
The Event Buffer component is designed to collect and optimize events generated by the instrumentation application before they are sent externally.
To ensure efficient data collection, the component locally manages a batch of events by:
- Optimizing the size of the event header
- Managing the persistence of events
Events are held in this local buffer until the batch is full, at which point it is sent. This approach is crucial for preventing data loss. For example, if the vehicle loses its internet connection, the events are safely stored in the local buffer and will be sent automatically as soon as the connection is restored. The optimization of event batching specifically concerns active session management. By aggregating events during an active session, the SDK minimizes the number of transmissions, which in turn optimizes data delivery and reduces overhead.
These optimizations were specifically implemented to meet the needs of the OEM, guaranteeing reliable and complete data transmission.
Tracking Components Usage
In this version of the SDK, the following annotations are available. For correct implementation, you need to import the specific enumerators required from the SDK. This approach makes the code more readable and less prone to errors than using hardcoded strings.
import org.radioplayer.automotiveSDK.annotation.domainEnums.*;
Every event has mandatory fields , and some also include optional fields.
Notation Supported
All parameters can be declared using either a string literal (e.g., "parameter") or in curly brackets (e.g., "{parameter}"). To populate the optional fields , we recommend using the relativeenumeration to access the supported and recommended values.
The value for optional fields can be defined in two ways:
- As a string literal (e.g.,
"ValueName"). - As a Java/Kotlin expression (e.g.,
{myVariable}).
The second method allows the value to be changed at runtime, as it is dynamically mapped from a variable. When using this approach, keep in mind that the call variable must be of the correct type (see here) to ensure data integrity and avoid runtime errors.
Allowed parsing
Call to methods
@SetValue(key = "SwitchStereoMode", value = "{getStereoMode()}") //inject: String.valueOf(getStereoMode())Call to methods with args
@SetValue(key = "SwitchStereoMode", value = "{getStereoMode(arg1, arg2)}") //inject: String.valueOf(getStereoMode(arg1, arg2))Field access
@SetValue(key = "SwitchStereoMode", value = "{stereo.mode}") //inject: String.valueOf(stereo.mode)Array element access
@SetValue(key = "FavRadio", value = "{freqRadioFav[1]}") //inject: String.valueOf(freqRadioFav[1])Allowed keyword/ Keyword recognition:
@SetValue(key = "RadioFocus", value = "{true}") //inject: String.valueOf(true)truefalsenull
Number (int, float, double)
@SetValue(key = "VolumeLevel", value = "{50}") //inject: String.valueOf(50)Explicit string
@SetValue(key = "{\"Test\"}", value = "{\"Not work\"}") //inject: String.valueOf()Return Escape Value
@SetValue(key = "{\"Test\"}", value = "{{RETURN}}")Some other example
@SetValue(key = "SwitchStereoMode", value = "{this.changeRadio(stereo,\"TurnOn\",105.10)}") //inject: this.changeRadio(stereo,"TurnOn",105.10)
NOT allowed parsing
The cases not yet supported are:
Expressions with arithmetic or logical operators
x + yx && yx || yi * (j + k)!flag
Ternary expressions:
x > 0 ? "positive" : "negative"(String) obj.getName()
- Representing negative values (negative numbers)
- Strings with special characters or escape sequences:
\n,\t, etc. Return types and generic methods
List<String>Map<Integer, String>new ArrayList<String>()
Class annotation: @Trackable
The @Trackable annotation is used at the class level to identify components whose methods are to be automatically instrumented and tracked by the Automotive Tracking SDK.
@Trackable(trackableName = "TestAutomotiveSDK", origin = "TestAutomotiveSDK", featureOrigin = "RadioSettings")
public class ExampleClass {
// ...
}
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
| trackableName | String | Identifies the trackable section | Mandatory |
| origin | String | Mandatory | |
| featureOrigin | String | Indicates the logical feature of the application to which the Trackable belongs | Mandatory |
Method Annotation
The annotations that can be used for methods are listed below.
@RadioStart
This action indicates that a radio stream has started playing. It includes details such as the rpuid and the volume level.
The @RadioStart annotation triggers a listening_session_start event, which signals the _start of a new listening session_. This event allows us to detect when the user starts listening to radio content.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
rpuid | String | It takes the value of RPUID for live content | Mandatory |
bearer | String | Refers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiver | Mandatory |
countryCode | String | Country code of the played media (ISO 3166 numeric) | Mandatory |
radioMode | RadioMode | Radio mode used for playback | Mandatory |
volume | Int | Volume level | - |
Example of usage
@RadioStart(rpuid = "{radioStations.get(currentPosition).getMediaId()}",
bearer = "{radioStations.get(currentPosition).getBearers().get(0).getId()}",
radioMode = "{RadioMode.DAB}", volume = "{10}", countryCode = "276")
public void ExampleMethod() {
// ...
}
@RadioStop
This action indicates that a radio stream has been stopped. It includes details like the rpuid, bearer and countryCode.
The @RadioStop annotation triggers a listening_session_stop event, which indicates the _end of the listening session_. This allows us to determine when the user has stopped listening to radio content.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
rpuid | String | It takes the value of RPUID for live content | Mandatory |
bearer | String | Refers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiver | Mandatory |
countryCode | String | Country code of the played media (ISO 3166 numeric) | Mandatory |
radioMode | RadioMode | Radio mode used for playback | Mandatory |
volume | Int | Volume level | - |
Example of usage
@RadioStop(rpuid = "{radioStations.get(currentPosition).getMediaId()}",
bearer = "{radioStations.get(currentPosition).getBearers().get(0).getId()}",
radioMode = "{RadioMode.DAB}", volume = "{this.getDeviceVolume()}", countryCode = "{countryCode}")
public void ExampleMethod() {
// ...
}
@RadioPause
This action indicates that a radio stream has been paused. It includes details such as the rpuid.
The @RadioPause annotation generates a listening_session_pause event, which signals that the listening session has been paused. In the automotive domain, in addition to this event, a listening_session_stop event is also generated to indicate that the user has temporarily stopped listening.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
rpuid | String | It takes the value of RPUID for live content | Mandatory |
bearer | String | Refers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiver | Mandatory |
countryCode | String | Country code of the played media (ISO 3166 numeric) | Mandatory |
Example of usage
@RadioPause(rpuid = "380101", bearer = "dab:ce1.c185.c500.0", countryCode = "{528}")
public void ExampleMethod() {
// ...
}
@RadioSkip
This action indicates that the radio has skipped to a different station or a different item in a playlist. To populate the skipType field, we recommend to follow the notation supported (see here).
The @RadioSkip annotation triggers a listening_session_skip event, which signals that the user has skipped another radio station. Each skip corresponds to a new listening session, so in addition to the listening_session_skip event, the listening_session_stop and listening_session_start events are also generated.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
newRpuid | String | It takes the value of RPUID for live content | Mandatory |
newBearer | String | Refers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiver | Mandatory |
countryCode | String | Country code of the played media (ISO 3166 numeric) | Mandatory |
skipType* | SkipStatus | Indicates the navigation action performed on the media: previous track, next track, jump to a specific position (JUMP) or reach the end of the content (MEDIA_END) | - |
*Optional: if not provided, defaults to SkipStatus.NEXT.
Example of usage
@RadioSkip(newRpuid = "380101", newBearer = "dab:ce1.c185.c500.0", countryCode = "{100}") // DEFAULT: {SkipStatus.NEXT}
@RadioSkip(newRpuid = "380101", newBearer = "dab:ce1.c185.c500.0", countryCode = "{100}", skipType = "{SkipStatus.PREVIOUS}")
@RadioSeek
This action indicates that a user manually changes the playback position of a live radio stream. To populate the seekType field, we recommend to follow the notation supported (see here).
The @RadioSeek annotation triggers a listening_session_seek event, which signals that the audio content is being fast-forwarded or rewound. It is used to understand whether the user is searching for a specific part of the content.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
rpuid | String | It takes the value of RPUID for live content | Mandatory |
bearer | String | Refers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiver | Mandatory |
countryCode | String | Country code of the played media (ISO 3166 numeric) | Mandatory |
seekType* | SeekStatus | Indicates whether the seek is backward, forward, or in progress by dragging the bar | - |
*Optional: if not provided, defaults to SeekStatus.FORWARD.
Example of usage
@RadioSeek(rpuid = "380101", countryCode = "{100}", bearer = "dab:1e0.11f7.12e9.0") // DEFAULT: {SeekStatus.FORWARD}
@RadioSeek(rpuid = "380101", countryCode = "{100}", bearer = "{this.bearer}", seekType = "{SeekStatus.BACKWARD}"))
@RadioError
This action logs an error when triggered whenever an error occurs during a listening session.
Using the @RadioError annotation triggers a listening_session_error event. This event lets us know when an error related to the listening session has occurred.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
rpuid | String | It takes the value of RPUID for live content | Mandatory |
bearer | String | Refers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiver | - |
reason | String | The reason for the error | Mandatory |
Example of usage
@RadioError(rpuid = "380101", bearer = "{bearer}", reason = "")
@PodcastStart
This action indicates that a podcast episode has started playing. It includes details such as the episode ID (crid) and countryCode.
The @PodcastStart annotation triggers a listening_session_start event, which signals the _start of a new listening session_. This event allows us to detect when the user starts listening to podcast content.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
crid | String | It takes he value of CRID for on-demand content | Mandatory |
countryCode | String | Country code of the played media (ISO 3166 numeric) | Mandatory |
position | Int | Current time of media in seconds. This value will be equal to the duration value in the case of end of streaming | - |
Example of usage
@PodcastStart(crid = "{currCrid}", countryCode = "{countryCode}", position = "{10}")
@PodcastStop
This action indicates that a podcast episode has been stopped. It includes details like the episode ID (crid) and the position at which it was stopped.
The @PodcastStop annotation triggers a listening_session_stop event, which indicates the _end of the listening session_. This allows us to determine when the user has stopped listening to podcast content.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
crid | String | It takes the value of CRID for on-demand content | Mandatory |
countryCode | String | Country code of the played media (ISO 3166 numeric) | Mandatory |
position | Int | Current time of media in seconds. This value will be equal to the duration value in the case of end of streaming | - |
Example of usage
@PodcastStop(crid = "{currCrid}", countryCode = "{countryCode}", position = "{300}")
@PodcastPause
This action indicates that a podcast episode has been paused. It includes details such as the episode ID (crid) and the position in the episode at which it was paused.
The @PodcastPause annotation generates a listening_session_pause event, which signals that the listening session has been paused. In the automotive domain, in addition to this event, a listening_session_stop event is also generated to indicate that the user has temporarily stopped listening.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
crid | String | It takes the value of CRID for on-demand content | Mandatory |
countryCode | String | Country code of the played media (ISO 3166 numeric) | Mandatory |
position | Int | Current time of media in seconds. This value will be equal to the duration value in the case of end of streaming | - |
Example of usage
@PodcastPause(crid = "{currCrid}", countryCode = "{countryCode}", position = "{120}")
@PodcastSkip
This action indicates that the podcast player has skipped to a different episode or a different point within the current episode. It provides details about the current media and the skip type. To populate the skipType field, we recommend to follow the notation supported (see here).
The @PodcastSkip annotation triggers a listening_session_skip event, which signals that the user has skipped another episode of the podcast. Each skip corresponds to a new listening session, so in addition to the listening_session_skip event, the listening_session_stop and listening_session_start events are also generated.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
newCrid | String | It takes the value of CRID for on-demand content | Mandatory |
countryCode | String | Country code of the played media (ISO 3166 numeric) | Mandatory |
position | Int | Current time of media in seconds. This value will be equal to the duration value in the case of end of streaming | - |
skipType* | SkipStatus | Indicates the navigation action performed on the media: previous track, next track, jump to a specific position (JUMP) or reach the end of the content (MEDIA_END) | - |
*Optional: if not provided, defaults to SkipStatus.NEXT.
Example of usage
@PodcastSkip(newCrid = "{currCrid}", countryCode = "{this.countryCode}", position = "{1000}") // DEFAULT: {SkipStatus.NEXT}
@PodcastSkip(newCrid = "{currCrid}", countryCode = "{528}", position = "{1000}", skipType = "{SkipStatus.PREVIOUS}")
@PodcastSeek
This action indicates that a user manually changes the playback position of a podcast episode. To populate the seekType field, we recommend to follow the notation supported (see here).
The @PodcastSeek annotation triggers a listening_session_seek event, which signals that the audio content is being fast-forwarded or rewound. It is used to understand whether the user is searching for a specific part of the content.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
crid | String | It takes the value of CRID for on-demand content | Mandatory |
countryCode | String | Country code of the played media (ISO 3166 numeric) | Mandatory |
position | Int | Current time of media in seconds. This value will be equal to the duration value in the case of end of streaming | - |
seekType* | SeekStatus | Indicates whether the seek is backward, forward, or in progress by dragging the bar | - |
*Optional: if not provided, defaults to SeekStatus.FORWARD.
Example of usage
@PodcastSeek(crid = "{currCrid}", countryCode = "{this.countryCode}", position = "{1000}") // DEFAULT: {SeekStatus.BACKWARD}
@PodcastSeek(crid = "{currCrid}", countryCode = "{this.countryCode}", position = "{1000}", seekType = "{SeekStatus.BACKWARD}"))
@PodcastError
This action logs an error when triggered whenever an error occurs during a listening session.
Using the @PodcastError annotation triggers a listening_session_error event. This event lets us know when an error related to the listening session has occurred.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
crid | String | It takes the value of CRID for on-demand content. | Mandatory |
position | String | Refers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiver. | Mandatory |
reason | String | The reason for the error. | Mandatory |
Example of usage
@PodcastError(crid = "{currCrid}", position = "{0}", reason = "No podcast detected")
@ActionFavorite
This action indicates that the user has provided feedback on the currently playing media by marking it as liked or disliked. To populate the like field, we recommend to follow the notation supported (see here).
Using the @ActionFavorite annotation triggers an action event. This event lets us know when the user has performed an action on their favorites (e.g., adding or removing a favorite).
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
type | String | Type of the use interaction | Mandatory |
uiSource | String | Information about the UI origin of the event | Mandatory |
mediaId | String | It takes the value of RPUID for live content and the value of CRID for on-demand content | Mandatory |
mediaType | String | Type of the media currently playing (STATION or EPISODE) | Mandatory |
bearer | String | Refers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiver | - |
favorite | Opinion | User feedback on the currently playing media | Mandatory |
Example of usage
@ActionFavorite(type = "ClickOnLikeButton", uiSource = "likeIcon",
mediaId = "{this.mediaId}", mediaType = "STATION", favorite = "{Opinion.LIKE}")
fun setLike() { ... }
@ActionFavorite(type = "ClickOnLikeButton", uiSource = "dislikeIcon",
mediaId = "{this.mediaId}", mediaType = "STATION", favorite = "{Opinion.DISLIKE}")
fun setDislike() { ... }
@ActionMobileMirroring
This action indicates the status of a mobile mirroring connection, such as Android Auto. To populate the mobileMirroringType field, we recommend to follow the notation supported (see here).
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
type | String | Type of the use interaction | Mandatory |
uiSource | String | Information about the UI origin of the event | Mandatory |
mobileMirroringType | SIS | Indicate which smartphone integration platform is in use (CarPlay, Android Auto, MirrorLink, or SDL) | Mandatory |
Example of usage
@ActionMobileMirroring(type = "SmartphoneConnected", uiSource = "None", mobileMirroringType = "{SIS.AndroidAuto}")
@ActionPlayback
This action reports the status of media playback, for instance, when a station is buffering or the playback status is updated. To populate the player field, we recommend to follow the notation supported (see here).
Using the @ActionPlayback annotation launches an action event. This event lets us know when the user has interacted with the playback controls.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
type | String | Type of the use interaction | Mandatory |
uiSource | String | Information about the UI origin of the event | Mandatory |
mediaId | String | It takes the value of RPUID for live content and the value of CRID for on-demand content | Mandatory |
mediaType | String | Type of the media currently playing (STATION or EPISODE) | Mandatory |
bearer | String | Refers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiver | - |
player* | PlaybackStatus | Indicates whether the media is PLAYING, PAUSED, STOP, BUFFERING, REWIND, FORWARD | - |
*Optional: if not provided, defaults to PlaybackStatus.BUFFERING.
Example of usage
@ActionPlayback(type = "Update Scan", uiSource = "Radio", mediaId = "380101", mediaType = "STATION", player = "{PlaybackStatus.PAUSED}")
@ActionPlayback(type = "PlayBackStatus", uiSource = "Radio", mediaId = "380101", mediaType = "STATION", player = "{this.status}")
@ActionPlayback(type = "PlayBackStatus", uiSource = "Radio", mediaId = "380101", mediaType = "STATION") // DEFAULT: {PlaybackStatus.BUFFERING}
@ActionRadioMode
This action is used to change the radio band , for example, switching to FM mode. To populate the uiSource field, we recommend to follow the notation supported (see here).
Using the @ActionRadioMode annotation launches an action event. Through this event, we understand when the user has changed or interacted with the radio mode (AM, FM, DAB etc.).
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
type | String | Type of the use interaction | Mandatory |
uiSource | String | Information about the UI origin of the event | Mandatory |
radioMode* | RadioMode | Radio mode used for playback | - |
*Optional: if not provided, defaults to RadioMode.DAB.
Example of usage
@ActionRadioMode(type = "changeBand", uiSource = "{uiController.getBtnFM()}",radioMode = "{radio}")
@ActionRadioMode(type = "changeBand", uiSource = "{uiController.getBtnFM()}") // DEFAULT: {RadioMode.DAB}
@ActionRadioPower
This action reports the power state of the radio (on or off). To populate the status field, we recommend to follow the notation supported (see here).
Using the @ActionRadioPower annotation, an action event is triggered. Through this event, we understand when the user has turned the radio on or off via the interface.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
type | String | Type of the use interaction | Mandatory |
uiSource | String | Information about the UI origin of the event | Mandatory |
status* | Enablement | Indicates whether the feature is enabled or disabled | - |
*Optional: if not provided, defaults to Enablement.ON.
Example of usage
@ActionRadioPower(type = "PowerMode", uiSource = "{this.radioON.getValue()}") // DEFAULT: {Enablement.ON}
@ActionRadioPower(type = "TestRadioPower", uiSource = "RadioPower", status = "{Enablement.OFF}")
@ActionRecClicked
This action indicates that a recommendation was clicked, such as a suggested station or podcast. It captures which recommended item was selected.
Using the @ActionRecClicked annotation, an action event is triggered. This event lets us know when the user has clicked on recommended content.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
type | String | Type of the use interaction | Mandatory |
uiSource | String | Information about the UI origin of the event | Mandatory |
clickedRecId | String | The ID of the recommendation that was clicked | Mandatory |
clickedRecType | String | Type of the clicked recommended media (STATION or EPISODE) | Mandatory |
Example of usage
@ActionRecClicked(type = "TestRecClicked", uiSource = "Recommendation", clickedRecId = "1234")
@ActionRecClickedSearchResult
This action indicates that a search result item was clicked. It captures which result was selected.
Using the @ActionRecClickedSearchResult annotation, an action event is triggered. This event lets us know when the user has clicked on a search result within the recommendations.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
type | String | Type of the use interaction. | Mandatory |
uiSource | String | Information about the UI origin of the event. | Mandatory |
clickedMediaId | String | The ID of the media clicked in the search result | Mandatory |
clickedMediaType | String | Type of the media currently playing (STATION or EPISODE) | Mandatory |
*Optional: if not provided, defaults to MediaSource.RADIO_ON_BOARD.
Example of usage
@ActionRecClickedSearchResult(type = "TestRecClicked", uiSource = "Recommendation", clickedMediaId = "276058", clickedMediaType = "PODCAST")
@ActionRecSearch
This action indicates that a search was performed. It records the search query.
Using the @ActionRecSearch annotation launches an action event. This event lets us know when the user has performed a search in the recommendation system.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
type | String | Type of the use interaction | Mandatory |
uiSource | String | Information about the UI origin of the event | Mandatory |
searchedValue | String | The search value entered by the user | Mandatory |
Example of usage
@ActionRecSearch(type = "TestRecClicked", uiSource = "Recommendation", searchedValue = "RadioName")
@ActionScan
This action indicates that the radio has started a scan for available stations and can list the frequencies it finds.
Using the @ActionScan annotation, an action event is triggered. This event lets us know when the user/device has started a scan (e.g., of radio frequencies).
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
type | String | Type of the use interaction | Mandatory |
uiSource | String | Information about the UI origin of the event | Mandatory |
status | String | Status of the radio frequency scan operation | Mandatory |
radioFound | String/Boolean | Indicates whether the scan found at least one valid station/frequency (true/false) | Mandatory |
frequencyFound | String/List | List of frequencies/bearers found during the scan | Mandatory |
Example of usage
@ActionScan(type = "ScanAction", uiSource = "startScan", status = "Started", radioFound = "started", frequencyFound = "[radio1,radio2]")
@ActionSourceChange
This action indicates that the active radio station has changed and tracks who triggered the change. It distinguishes between an explicit user-initiated change and an automatic/non-explicit change.
Using the @ActionSourceChange annotation, an action event is triggered. Through this event, we understand when the user has changed the playback source (e.g. On-board radio, Mobile Mirroring, Bluetooth, AUX).
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
type | String | Type of the use interaction | Mandatory |
uiSource | String | Information about the UI origin of the event | Mandatory |
mediaSource* | MediaSource | Source of the media currently playing (e.g. On-board radio, Mobile Mirroring, Bluetooth, AUX) | - |
*Optional: if not provided, defaults to MediaSource.RADIO_ON_BOARD.
Example of usage
@ActionSourceChange(type = "TestMediaSource", uiSource = "MediaSource", mediaSource = "{MediaSource.AUX}")
@ActionSourceChange(type = "TestMediaSource", uiSource = "MediaSource") // DEFAULT: {MediaSource.RADIO_ON_BOARD}
@ActionStationChange
This action indicates that the active radio station has changed and tracks who triggered the change. It distinguishes between an explicit user-initiated change and an automatic/non-explicit change.
Using the @ActionStationChange annotation, an action event is triggered. Through this event, we understand when the user has changed radio stations.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
type | String | Type of the use interaction | Mandatory |
uiSource | String | Information about the UI origin of the event | Mandatory |
mediaId | String | It takes the value of RPUID for live content and the value of CRID for on-demand content | Mandatory |
bearer | String | Refers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiver | - |
onUserChange* | Enablement | Indicates whether the user has changed (Enablement.ON) or not (Enablement.OFF) radio station | - |
*Optional: if not provided, defaults to Enablement.OFF.
Example of usage
@ActionStationChange(type = "TestStationChange", uiSource = "Radio", bearer = "dab:ce1.c185.c479.0")
@ActionUiFocus
This action indicates that the user has changed the radio app focus.
Using the @ActionUiFocus annotation, an action event is triggered. Through this event, we understand when the user has focused their attention on the radio app or on the home screen/other apps.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
type | String | Type of the use interaction | Mandatory |
uiSource | String | Information about the UI origin of the event | Mandatory |
focus* | Enablement | Indicates whether the Radio app is in focus (Enablement.ON) or not (Enablement.OFF) | - |
*Optional: if not provided, defaults to Enablement.ON.
Example of usage
@ActionUiFocus(type = "TestUiFocus", uiSource = "FOCUS") // DEFAULT: {Enablement.ON}
@ActionUiFocus(type = "TestUiFocus", uiSource = "FOCUS", focus="{Enablement.OFF}")
@ErrorEvent
This action logs an error when triggered.
Using the @ErrorEvent annotation triggers an error event. This event lets us know when a generic error has occurred in the system.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
type | CategoryError | The category of the error | Mandatory |
source | String | Information about the UI origin of the event | Mandatory |
severity | Severity | The severity of the error | Mandatory |
reason | String | The reason for the error | Mandatory |
stackTrace | String | The stack trace associated with the error, if available | - |
Example of usage
@ErrorEvent(type = "{CategoryError.PERSISTENCE}", source = "ConsoleButton", severity = "{Severity.CRITICAL}", reason = "Click on button when radio state is off", stackTrace = "{e.getStackTrace().toString()}")
@ErrorEvent(type = "{CategoryError.GENERAL}", source = "ConsoleButton", severity = "{Severity.WARN}", reason = "Click on button when radio state is off")
@SetValue
Allows you to track a variable/option change within the application.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
key | String | Name of the option changed | Mandatory |
value | String | New value of the option | Mandatory |
Example of usage
@SetValue(key = "getCurrentFrequency", value = "{{RETURN}}")
@SystemEventCalling
Used to detect interruptions. Essential for calculating real-time listening sessions and adjusting session metrics. To populate the status field, we recommend to follow the notation supported (see here).
Using the @SystemEventCalling annotation triggers a system_event_calling event. This event lets us know when a system event related to a phone call has occurred (start or end of call).
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
status | CallingStatus | Current call state. Supported values: CallingStatus.RINGING, CallingStatus.NO_CALL, CallingStatus.ON_CALL | - |
*Optional: if not provided, defaults to CallingStatus.NO_CALL.
Example of usage
@SystemEventCalling() // DEFAULT: {CallingStatus.NO_CALL}
@SystemEventCalling(status = "{CallingStatus.RINGING}")
@MetadataUpdate
This action reports an update to the metadata of the currently playing media, such as the artist , song title , and album.
Using the @MetadataUpdate annotation triggers a metadata_update event. This event lets us know when the metadata of the content being played (e.g., song title, artist) has been updated.
Annotation Element
| Name | Type | Description | Mandatory |
|---|---|---|---|
mediaId | String | It takes the value of RPUID for live content and the value of CRID for on-demand content | Mandatory |
bearer | String | Refers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiver | - |
artist | String | Name of the artist currently playing | Mandatory |
song | String | Title of the currently playing track | Mandatory |
album | String | Album name of the currently playing track | Mandatory |
show | String | Name/title of the program/show | Mandatory |
scheduleStart | String | Start time of the show/program schedule window | Mandatory |
scheduleStop | String | End time of the show/program schedule | Mandatory |
Example of usage
@MetadataUpdate(mediaId = "{currentOnAirInfo.getMediaId()}",
bearer = "{currentOnAirInfo.getBearer()}",
artist = "{currentOnAirInfo.getSongArtist()}",
song = "{currentOnAirInfo.getSongName()}",
album = "{currentOnAirInfo.getAlbumName()}",
show = "{currentOnAirInfo.getShowName()}",
scheduleStart = "{currentOnAirInfo.getSongStart()}",
scheduleStop = "{currentOnAirInfo.getSongEnd()}")
Recommended annotations for a first integration
Not all annotations are strictly required from the start. For those approaching the SDK for the first time, it is recommended to focus on the annotations marked with a relevance level of High , as these represent the core integration points for correct and complete functionality.
Annotations with a Medium or Low relevance level can be introduced at a later stage, as the integration matures or based on the specific needs of the product.
| Annotations | Relevance |
|---|---|
@RadioStart | High |
@RadioStop | High |
@RadioPause | High |
@RadioSkip | High |
@RadioSeek | High |
@RadioError | High |
@PodcastStart | High |
@PodcastStop | High |
@PodcastPause | High |
@PodcastSkip | High |
@PodcastSeek | High |
@PodcastError | High |
@ActionFavorite | High |
@ActionMobileMirroring | Low |
@ActionPlayback | Low |
@ActionRadioMode | Medium |
@ActionRadioPower | Low |
@ActionRecClicked | Low |
@ActionRecClickedSearchResult | Low |
@ActionRecSearch | Low |
@ActionScan | High |
@ActionSourceChange | High |
@ActionStationChange | High |
@ActionUiFocus | Medium |
@ErrorEvent | Medium |
@SetValue | Low |
@SystemEventCalling | Low |
@MetadataUpdate | Medium |
Enumeration
| Name | Values |
|---|---|
CallingStatus | ["RINGING", "NO_CALL", "ON_CALL"] |
CategoryError* | ["GENERAL", "NETWORKING", "PERSISTENCE", "COROUTINE", "MULTITHREADING", "AUTOMOTIVE_SDK", "DATA_TRACKING_SDK", "METADATA", "API"] |
Enablement | ["ON", "OFF"] |
MediaSource | ["RADIO_ON_BOARD", "MOBILE_MIRRORING", "BLUETOOTH", "AUX"] |
Opinion | ["LIKE", "DISLIKE"] |
PlaybackStatus | ["PLAYING", "PAUSED", "STOP", "BUFFERING", "REWIND", "FORWARD"] |
RadioMode** | ["AM", "FM", "DAB", "IP", "HD_RADIO", "DRM", "SIRIUS_XM"] |
SeekStatus | ["BACKWWARD", "FORWARD", "DRAGGING"] |
Severity | ["WARN", "ERROR", "CRITICAL"] |
SIS | ["AppleCarPlay", "AndroidAuto", "MirrorLink", "SDL"] |
SkipStatus | ["PREVIOUS", "NEXT", "JUMP", "MEDIA_END"] |
- For more information about
CategoryErrorsee here.
** For more information about RadioMode see here.
Other
Consent Management: CmpConsent
Why this class exists
Radioplayer processes different types of data depending on what the user has agreed to. Privacy regulations (ePrivacy Directive, GDPR) require that some of these activities — particularly anonymous usage analytics and precise location retention — only take place when the user has explicitly opted in. CmpConsent is the bridge between the consent decision shown to the user in the car's UI and the SDK's internal behaviour.
Relationship with CmpState
Internally, the SDK maps the consent flags carried by a CmpConsent instance to one of three operating levels defined by CmpState:
| Flags granted | Resulting CmpState | What changes |
|---|---|---|
| None | ESSENTIAL_RADIO_SERVICES | Core radio functionality only. Location is accessed transiently to find available stations but is never retained |
| Analytics | ESSENTIAL_SERVICES_USAGE_ANALYTICS | Anonymous usage and search statistics are collected to improve the service. Location is still not retained |
| Analytics + Location | FULL_SERVICE_LOCATION_ANALYTICS | Location data is additionally retained for radio coverage analysis. Requires explicit consent under Art. 5(3) ePrivacy and Art. 6(1)(a) GDPR |
Consent dependency
Granting location consent automatically implies analytics consent, because location retention is a superset of the analytics processing level. It is not possible to enable location analytics while keeping usage analytics disabled.
Usage
Use one of the three factory methods that mirror the options presented to the user in the consent UI, or the Builder when the flags come from a custom CMP integration.
// User chose "Essential Radio Services"
CmpConsent consent = CmpConsent.essentialOnly();
// User chose "Essential Services + Usage Analytics"
CmpConsent consent = CmpConsent.withAnalytics();
// User chose "Full Service + Location Analytics"
CmpConsent consent = CmpConsent.fullService();
// Consent flags sourced from a custom CMP integration
CmpConsent consent = new CmpConsent.Builder()
.analyticsConsent(userGrantedAnalytics)
.locationConsent(userGrantedLocation)
.build();
VehicleInfo Class
The VehicleInfo class is a data object for managing vehicle information. It's designed to encapsulate an automobile's basic details like maker, model, year, and a list of features. The primary goal is to create a unique yet deterministic ID for each vehicle.
Properties:
id(String): A unique, deterministically generated identifier for the vehicle object;vehicleType(String): Textual identifier of the vehicle type, obtained by concatenating maker, model and year;;maker(String): The vehicle's manufacturer;model(String): The vehicle's model;year(int): The vehicle's manufacturing year;features(Set<String>): A set of specific vehicle features (e.g., "DAB", "FM", "Bluetooth").
How the Deterministic ID Works
The ID is automatically generated by the class constructor. This ID is deterministic , meaning that if you use the same parameters (maker, model, year, and pseudoId), the generated ID will always be identical. This feature is useful for identifying the same vehicle across different tracking sessions or applications without relying on an external identifier (like the VIN, which might not always be available due to permission restrictions).
The ID generation process uses a combination of these parameters. Specifically, the maker string, model string, and year, combined with the pseudoId, create a hash that is then converted into a UUID Type 5, ensuring the ID is both immutable and deterministic but at the same time, not invertible.
ID retrieval
The TrackingSdk support this method for requests deletion of the user data:
public String retrievalUserId()
The method:
- retrieves the current device ID,
- removes it from local storage.
Usage
You can create a VehicleInfo instance using one of the available constructors depending on the information you have.
Creating a
VehicleInfoobject with basic data:VehicleInfo car1 = new VehicleInfo("Chimera Motors", "Manticore", 2024); VehicleInfo car2 = new VehicleInfo("Siren Automotive", "Leviathan", 2023); // car1.getId() and car2.getId() will return deterministically generated IDsCreating an object with additional features:
List<String> features = Arrays.asList("FM", "DAB", "Navigation", "Apple CarPlay"); VehicleInfo carWithFeatures = new VehicleInfo("Asgardian", "Valkyrie", 2022, features);- Creating an object with a custom pseudo-ID:
If you need to associate the vehicle with a specific identifier (like a user ID or an internal session), you can use the constructor with the pseudoId.
String userId = "user-12345";
VehicleInfo carWithUser = new VehicleInfo("Nautilus Drives", "Kraken", 2024, null, userId);
// The generated ID will always be the same for "Nautilus Drives", "Kraken", 2024, and "user-12345"
APPENDIX
A. Country Code
The International Organization for Standardization (ISO) created and maintains the ISO 3166 standard – Codes for the representation of names of countries and their subdivisions. A country code is a standardised identifier that uniquely represents a country (or territory) in computer systems. In this SDK, we exclusively use the ISO 3166-1 numeric standard which defines 3-digit numeric codes (script-independent).
Validation rules
- Length : must be exactly 3 digits.
- Permitted characters : numbers only (0–9), no spaces or symbols.
- Padding : if the code includes leading zeros, they must be included (e.g. 004, 008).
- Permitted values : the value must belong to the official ISO 3166-1 numeric list (no custom values).
- _Implementation advice_ : treat the value as a string to preserve any leading zeros.
Current ISO 3166 country codes
For an updated list, see: https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes#Current_ISO_3166_country_codes
ISO 3166 country codes (last updated on February 2026)
| ISO 3166 name | ISO 3166-1 numeric |
|---|---|
| Afghanistan | 004 |
| Åland Islands | 248 |
| Albania | 008 |
| Algeria | 012 |
| American Samoa | 016 |
| Andorra | 020 |
| Angola | 024 |
| Anguilla | 660 |
| Antarctica | 010 |
| Antigua and Barbuda | 028 |
| Argentina | 032 |
| Armenia | 051 |
| Aruba | 533 |
| Australia | 036 |
| Austria | 040 |
| Azerbaijan | 031 |
| Bahamas | 044 |
| Bahrain | 048 |
| Bangladesh | 050 |
| Barbados | 052 |
| Belarus | 112 |
| Belgium | 056 |
| Belize | 084 |
| Benin | 204 |
| Bermuda | 060 |
| Bhutan | 064 |
| Bolivia (Plurinational State of Bolivia) | 068 |
| Bonaire Sint Eustatius Saba | 535 |
| Bosnia and Herzegovina | 070 |
| Botswana | 072 |
| Bouvet Island | 074 |
| Brazil | 076 |
| British Indian Ocean Territory | 086 |
| British Virgin Islands | 092 |
| Brunei Darussalam | 096 |
| Bulgaria | 100 |
| Burkina Faso | 854 |
| Burma | 104 |
| Burundi | 108 |
| Cabo Verde | 132 |
| Cambodia | 116 |
| Cameroon | 120 |
| Canada | 124 |
| Cape Verde | 132 |
| Caribbean Netherlands | 535 |
| Cayman Islands | 136 |
| Central African Republic | 140 |
| Chad | 148 |
| Chile | 152 |
| China | 156 |
| China, The Republic of China | 158 |
| Christmas Island | 162 |
| Cocos (Keeling) Islands | 166 |
| Colombia | 170 |
| Comoros | 174 |
| Congo (the Democratic Republic of the Congo) | 180 |
| Congo | 178 |
| Cook Islands | 184 |
| Costa Rica | 188 |
| Côte d'Ivoire | 384 |
| Croatia | 191 |
| Cuba | 192 |
| Curaçao | 531 |
| Cyprus | 196 |
| Czechia | 203 |
| Democratic People's Republic of Korea | 408 |
| Democratic Republic of the Congo | 180 |
| Denmark | 208 |
| Djibouti | 262 |
| Dominica | 212 |
| Dominican Republic | 214 |
| East Timor | 626 |
| Ecuador | 218 |
| Egypt | 818 |
| El Salvador | 222 |
| Equatorial Guinea | 226 |
| Eritrea | 232 |
| Estonia | 233 |
| Eswatini | 748 |
| Ethiopia | 231 |
| Falkland Islands [Malvinas] | 238 |
| Faroe Islands | 234 |
| Fiji | 242 |
| Finland | 246 |
| France | 250 |
| French Guiana | 254 |
| French Polynesia | 258 |
| French Southern Territories | 260 |
| Gabon | 266 |
| Gambia | 270 |
| Georgia | 268 |
| Germany | 276 |
| Ghana | 288 |
| Gibraltar | 292 |
| Great Britain | 826 |
| Greece | 300 |
| Greenland | 304 |
| Grenada | 308 |
| Guadeloupe | 312 |
| Guam | 316 |
| Guatemala | 320 |
| Guernsey | 831 |
| Guinea | 324 |
| Guinea-Bissau | 624 |
| Guyana | 328 |
| Haiti | 332 |
| Heard Island and McDonald Islands | 334 |
| Holy See | 336 |
| Honduras | 340 |
| Hong Kong | 344 |
| Hungary | 348 |
| Iceland | 352 |
| India | 356 |
| Indonesia | 360 |
| Iran | 364 |
| Iraq | 368 |
| Ireland | 372 |
| Isle of Man | 833 |
| Israel | 376 |
| Italy | 380 |
| Ivory Coast | 384 |
| Jamaica | 388 |
| Jan Mayen | 744 |
| Japan | 392 |
| Jersey | 832 |
| Jordan | 400 |
| Kazakhstan | 398 |
| Kenya | 404 |
| Kiribati | 296 |
| Korea (the Democratic People's Republic of Korea) | 408 |
| Korea (the Republic of Korea) | 410 |
| Kuwait | 414 |
| Kyrgyzstan | 417 |
| Lao People's Democratic Republic | 418 |
| Latvia | 428 |
| Lebanon | 422 |
| Lesotho | 426 |
| Liberia | 430 |
| Libya | 434 |
| Liechtenstein | 438 |
| Lithuania | 440 |
| Luxembourg | 442 |
| Macao | 446 |
| Madagascar | 450 |
| Malawi | 454 |
| Malaysia | 458 |
| Maldives | 462 |
| Mali | 466 |
| Malta | 470 |
| Marshall Islands | 584 |
| Martinique | 474 |
| Mauritania | 478 |
| Mauritius | 480 |
| Mayotte | 175 |
| Mexico | 484 |
| Micronesia (Federated States of Micronesia) | 583 |
| Moldova (the Republic of Moldova) | 498 |
| Monaco | 492 |
| Mongolia | 496 |
| Montenegro | 499 |
| Montserrat | 500 |
| Morocco | 504 |
| Mozambique | 508 |
| Myanmar | 104 |
| Namibia | 516 |
| Nauru | 520 |
| Nepal | 524 |
| Netherlands (Kingdom of the Netherlands) | 528 |
| New Caledonia | 540 |
| New Zealand | 554 |
| Nicaragua | 558 |
| Niger | 562 |
| Nigeria | 566 |
| Niue | 570 |
| Norfolk Island | 574 |
| North Korea | 408 |
| Northern Mariana Islands | 580 |
| Norway | 578 |
| North Macedonia | 807 |
| Oman | 512 |
| Pakistan | 586 |
| Palau | 585 |
| Palestine, State of Palestine | 275 |
| Panama | 591 |
| Papua New Guinea | 598 |
| Paraguay | 600 |
| People's Republic of China | 156 |
| Peru | 604 |
| Philippines | 608 |
| Pitcairn | 612 |
| Poland | 616 |
| Portugal | 620 |
| Puerto Rico | 630 |
| Qatar | 634 |
| Republic of China | 158 |
| Republic of Korea | 410 |
| Republic of the Congo | 178 |
| Réunion | 638 |
| Romania | 642 |
| Russian Federation | 643 |
| Rwanda | 646 |
| Saba | 535 |
| Sahrawi Arab Democratic Republic | 732 |
| Saint Barthélemy | 652 |
| Saint Kitts and Nevis | 659 |
| Saint Lucia | 662 |
| Saint Martin (French part) | 663 |
| Saint Pierre and Miquelon | 666 |
| Saint Vincent and the Grenadines | 670 |
| Saint Helena Ascension Island Tristan da Cunha | 654 |
| Samoa | 882 |
| San Marino | 674 |
| Sao Tome and Principe | 678 |
| Saudi Arabia | 682 |
| Senegal | 686 |
| Serbia | 688 |
| Seychelles | 690 |
| Sierra Leone | 694 |
| Singapore | 702 |
| Sint Eustatius | 535 |
| Sint Maarten (Dutch part) | 534 |
| Slovakia | 703 |
| Slovenia | 705 |
| Solomon Islands | 090 |
| Somalia | 706 |
| South Africa | 710 |
| South Georgia and the South Sandwich Islands | 239 |
| South Korea | 410 |
| South Sudan | 728 |
| Spain | 724 |
| Sri Lanka | 144 |
| Sudan | 729 |
| Suriname | 740 |
| Svalbard Jan Mayen | 744 |
| Sweden | 752 |
| Switzerland | 756 |
| Syrian Arab Republic | 760 |
| Taiwan (Province of China) | 158 |
| Tajikistan | 762 |
| Tanzania, the United Republic of Tanzania | 834 |
| Thailand | 764 |
| Timor-Leste | 626 |
| Togo | 768 |
| Tokelau | 772 |
| Tonga | 776 |
| Trinidad and Tobago | 780 |
| Tunisia | 788 |
| Türkiye | 792 |
| Turkmenistan | 795 |
| Turks and Caicos Islands | 796 |
| Tuvalu | 798 |
| Uganda | 800 |
| Ukraine | 804 |
| United Arab Emirates | 784 |
| United Kingdom of Great Britain and Northern Ireland | 826 |
| United States Minor Outlying Islands | 581 |
| United States of America | 840 |
| United States Virgin Islands | 850 |
| Uruguay | 858 |
| Uzbekistan | 860 |
| Vanuatu | 548 |
| Vatican City | 336 |
| Venezuela (Bolivarian Republic of Venezuela) | 862 |
| Viet Nam | 704 |
| Virgin Islands (British) | 092 |
| Virgin Islands (U.S.) | 850 |
| Wallis and Futuna | 876 |
| Western Sahara | 732 |
| Yemen | 887 |
| Zambia | 894 |
| Zimbabwe | 716 |
B. Country Code vs Catalog Country Code
CountryCode
Indicates the country associated with the media currently being played (e.g., selected radio station, selected podcast/stream). Therefore, it changes based on the content being played.
CatalogCountryCode
Indicates the country of the content catalog used by the app for browsing/searching/listing. This value is chosen when the app is initialized and remains stable until it is reinitialized/changed.
Why they may be different
A user may want to listen to content from the Italian catalog (CatalogCountryCode = IT), but be located in Germany (CountryCode = DE).
In this case, an FM/DAB scan based on the receiver will mainly find German stations, because it depends on local coverage and the region where the vehicle is located.
Practical example
_CatalogCountryCode_ = IT → the user is browsing/filtering “Italy” content (Italian stations, metadata, IT market lineup).
_CountryCode_ = DE → the tuner scan/search returns frequencies/stations that can be received in Germany.
C. WRAPI
The Radioplayer Partner API (WRAPI) provides developers with unparalleled access to broadcasters' streaming radio programming and proprietary metadata. You can use this to build a rich and flexible hybrid radio experience for your customers.
The base address for the Radioplayer Partner API (WRAPI) is: api.radioplayer.org/v2/
There are ten endpoints to the Radioplayer Partner API (WRAPI):
WRAPI endpoints
| Endpoint | Purpose |
|---|---|
| _/stations_ | returns a list of all information on all stations, unless filtered by parameters. Also provides the ability to search for stations in a number of ways including keyword searching, category searching, search by bearers and search for local station. |
| _/stations/{rpuids}_ | returns information on a particular station, identified by its rpuid. |
| _/stations/{rpuids}/onair_ | provides current “track now playing” information from one or multiple radio stations. |
| _/stations/{rpuids}/schedule_ | returns programme schedules for up to five radio stations. |
| _/stations/{rpuid}/ondemand_ | returns a list of on-demand items for a given radio station. |
| _/stations/{rpuid}/ondemand/{seriesId}_ | returns a list of on-demand content for a given series. |
| _/ondemand_ | returns details on all pieces of on-demand content, unless filtered by parameters which include text searching, filtering by category, country or station. |
| _/ondemand/{odIds}_ | returns all information on a particular piece of on-demand content, identified by its OD ID. |
| _/recommendations_ | shows recommended content based on station affinity, music preferences from social media such as facebook, geolocation and generally trending stations. |
| _/categories_ | returns a list of categories for live and on demand content which can be used when searching for content by category. |
For complete documentation, see Radioplayer Partner API (WRAPI) documentation.
D. RadioConnectApi
TBD
E. RPUID
TBD
F. Category Error
Below is an explanation of the values in the CategoryError enumeration.
| Value | Description |
|---|---|
GENERAL | Generic error not attributable to a specific domain |
NETWORKING | Error related to network connectivity or HTTP communication |
PERSISTENCE | Error related to local data persistence (database, file I/O) |
COROUTINE | Error originating from a coroutine or asynchronous operation |
MULTITHREADING | Error caused by multithreading or concurrency issues |
AUTOMOTIVE_SDK | Error internal to the Automotive SDK |
DATA_TRACKING_SDK | Error internal to the Data Tracking SDK |
METADATA | Error related to metadata retrieval or parsing |
API | Error returned by or related to an external API call |
G. Radio Mode
Below is an explanation of the values in the RadioMode enumeration.
| Value | Description |
|---|---|
AM | Amplitude Modulation broadcast (Medium Wave / Long Wave) |
FM | Frequency Modulation broadcast |
DAB | Digital Audio Broadcasting (DAB, also known as DAB classic) |
IP | Internet-delivered radio stream (IP-based) |
HD_RADIO | HD Radio — IBOC (In-Band On-Channel) digital radio standard used in North America |
DRM | Digital Radio Mondiale — shortwave/MW digital broadcast standard |
SIRIUS_XM | Satellite radio service — digital radio signal broadcast via satellite (primarily North America) |