csai_sdk 0.3.0
csai_sdk: ^0.3.0 copied to clipboard
Client-Side Ad Insertion (CSAI) SDK for Flutter with VAST 4.0 support, HLS/MPEG-DASH streaming, and seamless ad insertion.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:csai_sdk/csai_sdk.dart';
import 'package:interactive_media_ads/interactive_media_ads.dart';
import 'package:video_player/video_player.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'CSAI SDK + IMA Test',
theme: ThemeData(primarySwatch: Colors.blue),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _log = '🚀 CSAI SDK + IMA Integration Test\n\nTap buttons below to test';
bool _isLoading = false;
void _addLog(String message) {
setState(() {
_log = '$message\n\n$_log';
});
}
/// Test 1: Generate Ad Request
Future<void> _testGenerateAdRequest() async {
setState(() => _isLoading = true);
_addLog('📝 Generating Ad Request...');
try {
final response = await CsaiSdk.generateAdRequest({
'deviceId': 'device_001',
'operatorId': 'operator_001',
'channelId': 'ch_001',
'channelName': 'Test Channel',
'channelGenre': 'news',
'adBlockDuration': '60',
});
_addLog('✅ Ad Request Generated\n'
'Device: ${response['deviceId']}\n'
'Timestamp: ${response['timestamp']}');
} catch (e) {
_addLog('❌ Error: $e');
} finally {
setState(() => _isLoading = false);
}
}
/// Test 2: Get VAST Response
Future<void> _testGetVASTResponse() async {
setState(() => _isLoading = true);
_addLog('🌐 Getting VAST Response...');
try {
final adRequest = AdRequest(
deviceId: 'device_001',
operatorId: 'operator_001',
channelId: 'ch_001',
channelName: 'Test Channel',
channelGenre: 'news',
adBlockDuration: 60,
);
final vastUrl = await CsaiSdk.getVastResponse(adRequest.toJsonString());
if (vastUrl != null && vastUrl.isNotEmpty) {
_addLog('✅ VAST URL Received\n'
'URL: ${vastUrl.substring(0, 80)}...');
} else {
_addLog('❌ VAST URL is empty');
}
} catch (e) {
_addLog('❌ Error: $e');
} finally {
setState(() => _isLoading = false);
}
}
/// Test 3: Send Playback Report
Future<void> _testSendReport() async {
setState(() => _isLoading = true);
_addLog('📤 Sending Playback Report...');
try {
final report = AdReport(
adBlockId: 'adblock_001',
duration: 60,
status: AdPlaybackStatus.completed,
playbackInfo: [
AdPlaybackInfo(
adId: 'ad_001',
title: 'Sample Ad 1',
playbackDuration: 30,
status: AdPlaybackStatus.completed,
),
AdPlaybackInfo(
adId: 'ad_002',
title: 'Sample Ad 2',
playbackDuration: 15,
status: AdPlaybackStatus.completed,
),
AdPlaybackInfo(
adId: 'ad_003',
title: 'Sample Ad 3',
playbackDuration: 15,
status: AdPlaybackStatus.completed,
),
],
);
final success = await CsaiSdk.sendReport(report.toJsonString());
if (success) {
_addLog('✅ Report Sent Successfully\n'
'Ads: 3\n'
'Total Duration: 60s');
} else {
_addLog('❌ Failed to send report');
}
} catch (e) {
_addLog('❌ Error: $e');
} finally {
setState(() => _isLoading = false);
}
}
/// Test 4: SCTE-35 Listener
void _testSCTE35Listener() {
_addLog('👂 Setting up SCTE-35 Listener...');
CsaiSdk.setScte35Listener((cue) {
_addLog('📢 SCTE-35 Cue Received\n'
'Event ID: ${cue.eventId}\n'
'Duration: ${cue.duration}ms');
});
_addLog('✅ SCTE-35 Listener Ready\n'
'Waiting for cues...');
}
/// Test 5: Ad Event Listener
void _testAdEventListener() {
_addLog('👂 Setting up Ad Event Listener...');
CsaiSdk.setAdEventListener((event) {
_addLog('🎬 Ad Event\n'
'Type: ${event.eventType}\n'
'Title: ${event.adTitle}');
});
_addLog('✅ Ad Event Listener Ready\n'
'Waiting for events...');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('CSAI SDK + IMA Test'),
backgroundColor: Colors.blue.shade700,
),
body: Column(
children: [
// Log Display
Expanded(
child: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Card(
color: Colors.grey.shade900,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
_log,
style: const TextStyle(
color: Colors.white,
fontFamily: 'monospace',
fontSize: 11,
height: 1.5,
),
),
),
),
),
),
// Test Buttons
Padding(
padding: const EdgeInsets.all(16.0),
child: _isLoading
? const CircularProgressIndicator()
: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
ElevatedButton.icon(
onPressed: _testGenerateAdRequest,
icon: const Icon(Icons.send),
label: const Text('Test 1:\nAd Request'),
),
const SizedBox(width: 8),
ElevatedButton.icon(
onPressed: _testGetVASTResponse,
icon: const Icon(Icons.cloud_download),
label: const Text('Test 2:\nVAST Response'),
),
const SizedBox(width: 8),
ElevatedButton.icon(
onPressed: _testSendReport,
icon: const Icon(Icons.upload),
label: const Text('Test 3:\nSend Report'),
),
const SizedBox(width: 8),
ElevatedButton.icon(
onPressed: _testSCTE35Listener,
icon: const Icon(Icons.mic),
label: const Text('Test 4:\nSCTE-35'),
),
const SizedBox(width: 8),
ElevatedButton.icon(
onPressed: _testAdEventListener,
icon: const Icon(Icons.event),
label: const Text('Test 5:\nAd Events'),
),
],
),
),
),
],
),
);
}
}