Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
6799b76
Add initial template
tvanlaerhoven Jan 14, 2026
b16bf3d
Update Android collector
tvanlaerhoven Jan 21, 2026
7873196
Add comments
tvanlaerhoven Jan 21, 2026
3005061
Add table entry
tvanlaerhoven Jan 21, 2026
8deee6b
Only support Android
tvanlaerhoven Jan 22, 2026
cef99f1
Update hook
tvanlaerhoven Jan 22, 2026
372c7f2
Pass defaultMetadata
tvanlaerhoven Jan 23, 2026
1311c80
Tag version
tvanlaerhoven Jan 23, 2026
4731603
Drop pod
tvanlaerhoven Jan 23, 2026
e7228d8
Rename API file
wvanhaevre Jan 23, 2026
53e001b
Remove native module
wvanhaevre Jan 23, 2026
9520b62
Add BitmovinAdapter for type conversions
wvanhaevre Jan 26, 2026
cc4c2cd
Add BitmovinConnector to separate native logic
wvanhaevre Jan 26, 2026
c3681d9
Update objc bridging code
wvanhaevre Jan 26, 2026
e7e3c66
Connect bridged methods to BitmovinConnector functionality
wvanhaevre Jan 26, 2026
3f12507
Add setup for adobe-edge and bitmovin to e2e app
wvanhaevre Jan 26, 2026
a19d327
Drop Android only check.
wvanhaevre Jan 26, 2026
5ff5f01
make config a let
wvanhaevre Jan 26, 2026
abef852
Fix podspec to fetch BitmovinAnalyticsCollector's Core
wvanhaevre Jan 26, 2026
b81e0fc
Update api
tvanlaerhoven Jan 29, 2026
058a6f9
Bump versions
tvanlaerhoven Jan 29, 2026
ddf98b1
Update e2e test app
tvanlaerhoven Jan 29, 2026
308e66f
Fix workspace
tvanlaerhoven Jan 29, 2026
d16458e
Disable yospace test
tvanlaerhoven Jan 29, 2026
7290364
Add custom menu
tvanlaerhoven Jan 29, 2026
0a7d2fc
Update readme
tvanlaerhoven Jan 29, 2026
e89f7ce
Add support for web
tvanlaerhoven Jan 29, 2026
3afd203
Attach player to bitmovin collector
wvanhaevre Jan 29, 2026
3113623
Add programChange placeholder for iOS
wvanhaevre Jan 29, 2026
9c82e10
Merge branch 'feature/bitmovin-analytics' of github.com:THEOplayer/re…
wvanhaevre Jan 29, 2026
1c87537
Bump version
tvanlaerhoven Jan 29, 2026
2e05ae5
Update changelog
tvanlaerhoven Jan 29, 2026
9fd9eb7
Add changeset entry
tvanlaerhoven Jan 29, 2026
1ab9514
Disable THEOplayerCollector usage until available through pod and thr…
wvanhaevre Jan 30, 2026
02cd994
Update license
tvanlaerhoven Jan 30, 2026
90a93d0
Disable setting customData on Android
tvanlaerhoven Jan 30, 2026
77d5b5c
Make InitBitmovin public on API
wvanhaevre Jan 30, 2026
1f4cc0c
Align device-info version
tvanlaerhoven Jan 30, 2026
1e114e6
Remove adobe-edge pod from e2e PodFile
wvanhaevre Jan 30, 2026
23d2c6d
Add alias
tvanlaerhoven Jan 30, 2026
7cbceb4
Add extra watch folder for root package dependencies
wvanhaevre Jan 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/rude-lamps-teach.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@theoplayer/react-native-analytics-bitmovin': patch
---

Initial release.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,4 @@ lib/
manifest.json
apps/e2e/cavy_results.md
apps/e2e/ios/Pods
apps/e2e/.env
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ the official THEOplayer React Native video player.
| Adobe Heartbeat analytics using the Media Collections API | [![%40theoplayer/react-native-analytics-adobe](https://img.shields.io/npm/v/%40theoplayer%2Freact-native-analytics-adobe?label=%40theoplayer/react-native-analytics-adobe)](https://www.npmjs.com/package/%40theoplayer%2Freact-native-analytics-adobe) | [`Adobe`](https://github.com/THEOplayer/react-native-connectors/tree/main/adobe) |
| Adobe Media Edge analytics | [![%40theoplayer/react-native-analytics-adobe-edge](https://img.shields.io/npm/v/%40theoplayer%2Freact-native-analytics-adobe-edge?label=%40theoplayer/react-native-analytics-adobe-edge)](https://www.npmjs.com/package/%40theoplayer%2Freact-native-analytics-adobe) | [`Adobe Edge`](https://github.com/THEOplayer/react-native-connectors/tree/main/adobe-edge) |
| Agama analytics | [![%40theoplayer/react-native-analytics-agama](https://img.shields.io/npm/v/%40theoplayer%2Freact-native-analytics-agama?label=%40theoplayer/react-native-analytics-agama)](https://www.npmjs.com/package/%40theoplayer%2Freact-native-analytics-agama) | [`Agama`](https://github.com/THEOplayer/react-native-connectors/tree/main/agama) |
| Bitmovin analytics | [![%40theoplayer/react-native-analytics-bitmovin](https://img.shields.io/npm/v/%40theoplayer%2Freact-native-analytics-bitmovin?label=%40theoplayer/react-native-analytics-bitmovin)](https://www.npmjs.com/package/%40theoplayer%2Freact-native-analytics-bitmovin) | [`Agama`](https://github.com/THEOplayer/react-native-connectors/tree/main/bitmovin) |
| Comscore analytics | [![%40theoplayer/react-native-analytics-comscore](https://img.shields.io/npm/v/%40theoplayer%2Freact-native-analytics-comscore?label=%40theoplayer/react-native-analytics-comscore)](https://www.npmjs.com/package/%40theoplayer%2Freact-native-analytics-comscore) | [`Comscore`](https://github.com/THEOplayer/react-native-connectors/tree/main/comscore) |
| Content protection (DRM) | [![%40theoplayer/react-native-drm](https://img.shields.io/npm/v/%40theoplayer%2Freact-native-drm?label=%40theoplayer/react-native-drm)](https://www.npmjs.com/package/%40theoplayer%2Freact-native-drm) | [`DRM`](https://github.com/THEOplayer/react-native-connectors/tree/main/drm) |
| Conviva analytics | [![%40theoplayer/react-native-analytics-conviva](https://img.shields.io/npm/v/%40theoplayer%2Freact-native-analytics-conviva?label=%40theoplayer/react-native-analytics-conviva)](https://www.npmjs.com/package/%40theoplayer%2Freact-native-analytics-conviva) | [`Conviva`](https://github.com/THEOplayer/react-native-connectors/tree/main/conviva) |
Expand Down
11 changes: 11 additions & 0 deletions apps/e2e/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
THEO_LICENSE_KEY=

# CONVIVA
CONVIVA_CUSTOMER_KEY=
CONVIVA_DEBUG=true
CONVIVA_TOUCHSTONE_SERVICE_URL=
CONVIVA_VIEWER_ID=e2e_viewer_id

# BITMOVIN
BITMOVIN_LICENSE_KEY=
BITMOVIN_LOG_LEVEL=DEBUG
170 changes: 87 additions & 83 deletions apps/e2e/android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,57 +1,58 @@
apply plugin: "com.android.application"
apply plugin: "org.jetbrains.kotlin.android"
apply plugin: "com.facebook.react"
apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"

/**
* This is the configuration block to customize your React Native Android app.
* By default you don't need to apply any configuration, just uncomment the lines you need.
*/
react {
/* Folders */
// The root of your project, i.e. where "package.json" lives. Default is '..'
// root = file("../")
// The folder where the react-native NPM package is. Default is ../node_modules/react-native
// reactNativeDir = file("../node_modules/react-native")
// The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen
// codegenDir = file("../node_modules/@react-native/codegen")
// The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js
// cliFile = file("../node_modules/react-native/cli.js")
/* Folders */
// The root of your project, i.e. where "package.json" lives. Default is '..'
// root = file("../")
// The folder where the react-native NPM package is. Default is ../node_modules/react-native
// reactNativeDir = file("../node_modules/react-native")
// The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen
// codegenDir = file("../node_modules/@react-native/codegen")
// The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js
// cliFile = file("../node_modules/react-native/cli.js")

/* Variants */
// The list of variants to that are debuggable. For those we're going to
// skip the bundling of the JS bundle and the assets. By default is just 'debug'.
// If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
// debuggableVariants = ["liteDebug", "prodDebug"]
/* Variants */
// The list of variants to that are debuggable. For those we're going to
// skip the bundling of the JS bundle and the assets. By default is just 'debug'.
// If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
// debuggableVariants = ["liteDebug", "prodDebug"]

/* Bundling */
// A list containing the node command and its flags. Default is just 'node'.
// nodeExecutableAndArgs = ["node"]
//
// The command to run when bundling. By default is 'bundle'
// bundleCommand = "ram-bundle"
//
// The path to the CLI configuration file. Default is empty.
// bundleConfig = file(../rn-cli.config.js)
//
// The name of the generated asset file containing your JS bundle
// bundleAssetName = "MyApplication.android.bundle"
//
// The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
entryFile = file("../../index.js")
//
// A list of extra flags to pass to the 'bundle' commands.
// See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
// extraPackagerArgs = []
/* Bundling */
// A list containing the node command and its flags. Default is just 'node'.
// nodeExecutableAndArgs = ["node"]
//
// The command to run when bundling. By default is 'bundle'
// bundleCommand = "ram-bundle"
//
// The path to the CLI configuration file. Default is empty.
// bundleConfig = file(../rn-cli.config.js)
//
// The name of the generated asset file containing your JS bundle
// bundleAssetName = "MyApplication.android.bundle"
//
// The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
entryFile = file("../../index.js")
//
// A list of extra flags to pass to the 'bundle' commands.
// See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
// extraPackagerArgs = []

/* Hermes Commands */
// The hermes compiler command to run. By default it is 'hermesc'
// hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
//
// The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
// hermesFlags = ["-O", "-output-source-map"]
/* Hermes Commands */
// The hermes compiler command to run. By default it is 'hermesc'
// hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
//
// The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
// hermesFlags = ["-O", "-output-source-map"]

/* Autolinking */
autolinkLibrariesWithApp()
/* Autolinking */
autolinkLibrariesWithApp()
}

/**
Expand All @@ -73,62 +74,65 @@ def enableProguardInReleaseBuilds = true
def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+'

android {
ndkVersion rootProject.ext.ndkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
compileSdk rootProject.ext.compileSdkVersion
ndkVersion rootProject.ext.ndkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
compileSdk rootProject.ext.compileSdkVersion

namespace "com.reactnativetheoplayer"
defaultConfig {
applicationId "com.reactnativetheoplayer.e2e"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
namespace "com.reactnativetheoplayer"
defaultConfig {
applicationId "com.reactnativetheoplayer.e2e"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
// Extra react-native-config resource
resValue "string", "build_config_package", "com.reactnativetheoplayer"
versionCode 1
versionName "1.0"
}
signingConfigs {
debug {
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
signingConfigs {
debug {
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
}
buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://reactnative.dev/docs/signed-apk-android.
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://reactnative.dev/docs/signed-apk-android.
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
}

def safeExtGet(prop, fallback) {
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
}

dependencies {
implementation project(path: ':react-native-theoplayer-analytics-adobe')
implementation project(path: ':react-native-theoplayer-analytics-adobe-edge')
implementation project(path: ':react-native-theoplayer-analytics-comscore')
implementation project(path: ':react-native-theoplayer-analytics-conviva')
implementation project(path: ':react-native-theoplayer-analytics-nielsen')
implementation project(path: ':react-native-theoplayer-yospace')
implementation project(path: ':react-native-theoplayer-analytics-adobe')
implementation project(path: ':react-native-theoplayer-analytics-adobe-edge')
implementation project(path: ':react-native-theoplayer-analytics-comscore')
implementation project(path: ':react-native-theoplayer-analytics-conviva')
implementation project(path: ':react-native-theoplayer-analytics-nielsen')
implementation project(path: ':react-native-theoplayer-analytics-bitmovin')
// implementation project(path: ':react-native-theoplayer-yospace')
// implementation project(path: ':react-native-theoplayer-analytics-adscript')
// implementation project(path: ':react-native-theoplayer-analytics-gemius')

implementation "com.google.android.gms:play-services-cast-framework:${safeExtGet('castFrameworkVersion', '+')}"
implementation "com.google.android.gms:play-services-cast-framework:${safeExtGet('castFrameworkVersion', '+')}"

// The version of react-native is set by the React Native Gradle Plugin
implementation("com.facebook.react:react-android")
// The version of react-native is set by the React Native Gradle Plugin
implementation("com.facebook.react:react-android")

if (hermesEnabled.toBoolean()) {
implementation("com.facebook.react:hermes-android")
} else {
implementation jscFlavor
}
if (hermesEnabled.toBoolean()) {
implementation("com.facebook.react:hermes-android")
} else {
implementation jscFlavor
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,23 @@ import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.react.soloader.OpenSourceMergedSoMapping
import com.facebook.soloader.SoLoader
import com.theoplayer.reactnative.bitmovin.ReactTHEOplayerBitmovinPackage
import com.theoplayercomscore.ReactTHEOplayerComscorePackage
import com.theoplayerconviva.ReactTHEOplayerConvivaPackage
import com.theoplayernielsen.ReactTHEOplayerNielsenPackage
import com.theoplayeryospace.ReactTHEOplayerYospacePackage
//import com.theoplayeryospace.ReactTHEOplayerYospacePackage

class MainApplication : Application(), ReactApplication {
override val reactNativeHost: ReactNativeHost =
object : DefaultReactNativeHost(this) {
override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply {
// Packages that cannot be autolinked yet can be added manually here, for example:
add(ReactTHEOplayerBitmovinPackage())
add(ReactTHEOplayerComscorePackage())
add(ReactTHEOplayerConvivaPackage())
add(ReactTHEOplayerNielsenPackage())
add(ReactTHEOplayerYospacePackage())
// add(ReactTHEOplayerYospacePackage())
}

override fun getJSMainModuleName(): String = "index"
Expand Down
6 changes: 4 additions & 2 deletions apps/e2e/android/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ include ':react-native-theoplayer-analytics-conviva'
project(':react-native-theoplayer-analytics-conviva').projectDir = new File(rootProject.projectDir, '../../../conviva/android')
include ':react-native-theoplayer-analytics-nielsen'
project(':react-native-theoplayer-analytics-nielsen').projectDir = new File(rootProject.projectDir, '../../../nielsen/android')
include ':react-native-theoplayer-yospace'
project(':react-native-theoplayer-yospace').projectDir = new File(rootProject.projectDir, '../../../yospace/android')
include ':react-native-theoplayer-analytics-bitmovin'
project(':react-native-theoplayer-analytics-bitmovin').projectDir = new File(rootProject.projectDir, '../../../bitmovin/android')
//include ':react-native-theoplayer-yospace'
//project(':react-native-theoplayer-yospace').projectDir = new File(rootProject.projectDir, '../../../yospace/android')
// include ':react-native-theoplayer-analytics-adscript'
// project(':react-native-theoplayer-analytics-adscript').projectDir = new File(rootProject.projectDir, '../../../adscript/android')
// include ':react-native-theoplayer-analytics-gemius'
Expand Down
14 changes: 0 additions & 14 deletions apps/e2e/babel.config.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,10 @@
const path = require('path');

const connectors = [
{name: '@theoplayer/react-native-analytics-adobe', path: '../../adobe'}
];

const alias = connectors.reduce((acc, connector) => {
acc[connector.name] = path.join(__dirname, connector.path, 'src/index');
return acc;
}, {});

module.exports = {
presets: ['module:@react-native/babel-preset'],
plugins: [
[
'module-resolver',
{
extensions: ['.tsx', '.ts', '.js', '.json'],
alias: {
...alias
}
},
],
],
Expand Down
5 changes: 4 additions & 1 deletion apps/e2e/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
console.error('This app can only be used with cavy-cli');
import { AppRegistry } from 'react-native';
import App from './src/App';

AppRegistry.registerComponent('ReactNativeTHEOplayerE2E', () => App);
9 changes: 9 additions & 0 deletions apps/e2e/index.web.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React, { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './src/App';

createRoot(document.getElementById('app') as HTMLElement).render(
<StrictMode>
<App />
</StrictMode>,
);
2 changes: 2 additions & 0 deletions apps/e2e/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ target 'ReactNativeTHEOplayer' do
pod 'react-native-theoplayer-conviva', :path => '../../../conviva'
pod 'react-native-theoplayer-nielsen', :path => '../../../nielsen'
pod 'react-native-theoplayer-adobe', :path => '../../../adobe'
pod 'react-native-theoplayer-bitmovin', :path => '../../../bitmovin'

google_cast_redirect

Expand All @@ -48,6 +49,7 @@ target 'ReactNativeTHEOplayer-tvOS' do
pod 'react-native-theoplayer-conviva', :path => '../../../conviva'
pod 'react-native-theoplayer-nielsen', :path => '../../../nielsen'
pod 'react-native-theoplayer-adobe', :path => '../../../adobe'
pod 'react-native-theoplayer-bitmovin', :path => '../../../bitmovin'

end

Expand Down
40 changes: 39 additions & 1 deletion apps/e2e/metro.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,52 @@ const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
const path = require('path');
const root = path.resolve(__dirname, '../..');

const packages = [
'react',
'react-native',
'react-native-theoplayer',
'@babel/runtime'
];

const connectors = [
'adobe',
'adobe-edge',
'adscript',
'agama',
'bitmovin',
'comscore',
'conviva',
'drm',
'gemius',
'mux',
'nielsen',
'yospace',
'youbora',
]

/**
* Metro configuration
* https://reactnative.dev/docs/metro
*
* @type {import('metro-config').MetroConfig}
*/
const config = {
watchFolders: [root],
projectRoot: __dirname,
watchFolders: [
path.resolve(root, 'node_modules'),
...connectors.map(cn => path.resolve(root, cn)),
],
resolver: {
/**
* Metro does not resolve dependencies across multiple node_modules folders by default.
* Explicitly mapping packages in extraNodeModules ensures all dependencies resolve to the correct versions,
* avoids duplication, and prevents issues like multiple React instances or module not found errors.
*/
extraNodeModules: {
...Object.fromEntries(packages.map((pkg) => [pkg, path.join(__dirname, 'node_modules', pkg)])),
...Object.fromEntries(connectors.map((cn) => [`@theoplayer/react-native-analytics-${cn}`, path.join(root, cn)])),
},
},
};

module.exports = mergeConfig(getDefaultConfig(__dirname), config);
Loading
Loading