-
Notifications
You must be signed in to change notification settings - Fork 29.1k
Open
Labels
in triagePresently being triaged by the triage teamPresently being triaged by the triage teamwaiting for customer responseThe Flutter team cannot make further progress on this issue until the original reporter respondsThe Flutter team cannot make further progress on this issue until the original reporter responds
Description
What package does this bug report belong to?
interactive_media_ads
What target platforms are you seeing this bug on?
Android
Have you already upgraded your packages?
Yes
Dependency versions
pubspec.lock
[Paste file content here]
Steps to reproduce
play link live rather than video
set vmap link in ad url
the ads will only play preroll not all ads
just need to use link for streaming live (i cant provide our link becasue link will expired after 2 min )
Expected results
all ads listed in files should be played
Actual results
[log] Firebase Crashlytics Exception
[log] Null check operator used on a null value
[log] #0 AndroidAdDisplayContainer._startAdProgressTracking. (package:interactive_media_ads/src/android/android_ad_display_container.dart:189:34)
when set url its only play first ads
Code sample
Code sample
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_driver/driver_extension.dart';
import 'package:interactive_media_ads/interactive_media_ads.dart';
import 'package:video_player/video_player.dart';
/// Entry point for integration tests that require espresso.
@pragma('vm:entry-point')
void integrationTestMain() {
enableFlutterDriverExtension();
main();
}
void main() {
runApp(const MaterialApp(home: AdExampleWidget()));
}
/// Example widget displaying an Ad before a video.
class AdExampleWidget extends StatefulWidget {
/// Constructs an [AdExampleWidget].
const AdExampleWidget({super.key});
@override
State<AdExampleWidget> createState() => _AdExampleWidgetState();
}
class _AdExampleWidgetState extends State<AdExampleWidget>
with WidgetsBindingObserver {
// IMA sample tag for a pre-, mid-, and post-roll, single inline video ad. See more IMA sample
// tags at https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/tags
// static const String _adTagUrl =
// 'https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/vmap_ad_samples&sz=640x480&cust_params=sample_ar%3Dpremidpost&ciu_szs=300x250&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&env=vp&impl=s&cmsid=496&vid=short_onecue&correlator=';
static const String _adTagUrl = true
? (true
? "https://feeds.kwikmotion.com/v1/VMAP-VAST.xml"
: "https://pubads.g.doubleclick.net/gampad/ads?iu=/18294456/AlSumaria_App_VOD_Preroll&description_url=http%3A%2F%2Fwww.alsumaria.tv%2F&tfcd=0&npa=0&sz=640x480&gdfp_req=1&unviewed_position_start=1&output=vmap&env=vp&impl=s&correlator=")
: 'https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/vmap_ad_samples&sz=640x480&cust_params=sample_ar%3Dpremidpost&ciu_szs=300x250&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&env=vp&impl=s&cmsid=496&vid=short_onecue&correlator=';
// The AdsLoader instance exposes the request ads method.
late final AdsLoader _adsLoader;
// AdsManager exposes methods to control ad playback and listen to ad events.
AdsManager? _adsManager;
// Last state received in `didChangeAppLifecycleState`.
AppLifecycleState _lastLifecycleState = AppLifecycleState.resumed;
// Whether the widget should be displaying the content video. The content
// player is hidden while Ads are playing.
bool _shouldShowContentVideo = false;
// Controls the content video player.
late final VideoPlayerController _contentVideoController;
// Periodically updates the SDK of the current playback progress of the
// content video.
Timer? _contentProgressTimer;
// Provides the SDK with the current playback progress of the content video.
// This is required to support mid-roll ads.
final ContentProgressProvider _contentProgressProvider =
ContentProgressProvider();
late final CompanionAdSlot companionAd = CompanionAdSlot(
size: CompanionAdSlotSize.fixed(width: 300, height: 250),
onClicked: () => debugPrint('Companion Ad Clicked'),
);
late final AdDisplayContainer _adDisplayContainer = AdDisplayContainer(
companionSlots: <CompanionAdSlot>[companionAd],
onContainerAdded: (AdDisplayContainer container) {
_adsLoader = AdsLoader(
container: container,
onAdsLoaded: (OnAdsLoadedData data) {
final AdsManager manager = data.manager;
_adsManager = data.manager;
manager.setAdsManagerDelegate(AdsManagerDelegate(
onAdEvent: (AdEvent event) {
debugPrint('OnAdEvent: ${event.type} => ${event.adData}');
switch (event.type) {
case AdEventType.loaded:
manager.start();
case AdEventType.contentPauseRequested:
_pauseContent();
case AdEventType.contentResumeRequested:
_resumeContent();
case AdEventType.allAdsCompleted:
manager.destroy();
_adsManager = null;
case AdEventType.clicked:
case AdEventType.complete:
case _:
}
},
onAdErrorEvent: (AdErrorEvent event) {
debugPrint('AdErrorEvent: ${event.error.message}');
_resumeContent();
},
));
manager.init(
settings: AdsRenderingSettings(
loadVideoTimeout: Duration(minutes: 1),
mimeTypes: ["video/mp4"],
enablePreloading: true));
},
onAdsLoadError: (AdsLoadErrorData data) {
debugPrint('OnAdsLoadError: ${data.error.message}');
_resumeContent();
},
);
// Ads can't be requested until the `AdDisplayContainer` has been added to
// the native View hierarchy.
_requestAds(container);
},
);
@override
void initState() {
super.initState();
// Adds this instance as an observer for `AppLifecycleState` changes.
WidgetsBinding.instance.addObserver(this);
_contentVideoController = VideoPlayerController.networkUrl(
Uri.parse(
'https://storage.googleapis.com/gvabox/media/samples/stock.mp4',
),
)
..addListener(() {
if (_contentVideoController.value.isCompleted) {
_adsLoader.contentComplete();
}
setState(() {});
})
..initialize().then((_) {
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
setState(() {});
});
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.resumed:
if (!_shouldShowContentVideo) {
_adsManager?.resume();
}
case AppLifecycleState.inactive:
// Pausing the Ad video player on Android can only be done in this state
// because it corresponds to `Activity.onPause`. This state is also
// triggered before resume, so this will only pause the Ad if the app is
// in the process of being sent to the background.
if (!_shouldShowContentVideo &&
_lastLifecycleState == AppLifecycleState.resumed) {
_adsManager?.pause();
}
case AppLifecycleState.hidden:
case AppLifecycleState.paused:
case AppLifecycleState.detached:
}
_lastLifecycleState = state;
}
Future<void> _requestAds(AdDisplayContainer container) {
return _adsLoader.requestAds(AdsRequest(
adWillAutoPlay: true,
adTagUrl: _adTagUrl,
contentProgressProvider: _contentProgressProvider,
));
}
Future<void> _resumeContent() async {
setState(() {
_shouldShowContentVideo = true;
});
if (_adsManager != null) {
_contentProgressTimer = Timer.periodic(
const Duration(milliseconds: 200),
(Timer timer) async {
if (_contentVideoController.value.isInitialized) {
final Duration? progress = await _contentVideoController.position;
if (progress != null) {
await _contentProgressProvider.setProgress(
progress: progress,
duration: _contentVideoController.value.duration,
);
}
}
},
);
}
await _contentVideoController.play();
}
Future<void> _pauseContent() {
setState(() {
_shouldShowContentVideo = false;
});
_contentProgressTimer?.cancel();
_contentProgressTimer = null;
return _contentVideoController.pause();
}
@override
void dispose() {
super.dispose();
_contentProgressTimer?.cancel();
_contentVideoController.dispose();
_adsManager?.destroy();
WidgetsBinding.instance.removeObserver(this);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
spacing: 100,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
width: 300,
child: !_contentVideoController.value.isInitialized
? Container()
: AspectRatio(
aspectRatio: _contentVideoController.value.aspectRatio,
child: Stack(
children: <Widget>[
// The display container must be on screen before any Ads can be
// loaded and can't be removed between ads. This handles clicks for
// ads.
_adDisplayContainer,
if (_shouldShowContentVideo)
VideoPlayer(_contentVideoController)
],
),
),
),
ColoredBox(
color: Colors.green,
child: SizedBox(
width: 300,
height: 250,
child: companionAd.buildWidget(context),
),
),
],
),
),
floatingActionButton:
_contentVideoController.value.isInitialized && _shouldShowContentVideo
? FloatingActionButton(
onPressed: () {
setState(() {
_contentVideoController.value.isPlaying
? _contentVideoController.pause()
: _contentVideoController.play();
});
},
child: Icon(
_contentVideoController.value.isPlaying
? Icons.pause
: Icons.play_arrow,
),
)
: null,
);
}
}
Screenshots or Videos
Screenshots / Video demonstration
[Upload media here]
Logs
Logs
I/flutter (18273): OnAdEvent: AdEventType.adProgress => {}
I/flutter (18273): OnAdEvent: AdEventType.skipped => {}
I/flutter (18273): OnAdEvent: AdEventType.contentResumeRequested => {}
[log] VIDEO STATE is :Instance of 'VideoPlayerLoaded'
I/mali_config(18273): @get_buffer_dataspace_setting: update dataspace from GE (0x00000000 -> 0x10010000)
[log] VIDEO STATE is :Instance of 'VideoPlayerPlaying'
I/Choreographer(18273): Skipped 33 frames! The application may be doing too much work on its main thread.
I/gralloc4(18273): @set_metadata: update dataspace from GM (0x00000000 -> 0x08010000)
[log] Firebase Crashlytics Exception
[log] Null check operator used on a null value
[log] #0 AndroidAdDisplayContainer._startAdProgressTracking.<anonymous closure> (package:interactive_media_ads/src/android/android_ad_display_container.dart:189:34)
<asynchronous suspension>
V/MediaPlayer-JNI(18273): pause
V/MediaPlayerNative(18273): pause
Flutter Doctor output
Doctor output
Flutter (Channel stable, 3.32.8, on Microsoft Windows [Version 10.0.26100.4652], locale en-US)
! Warning: `flutter` on your path resolves to C:\Users\Ab-Aziz\fvm\versions\3.32.8\bin\flutter, which is not inside your current Flutter SDK checkout at
C:\Users\Ab-Aziz\fvm\default. Consider adding C:\Users\Ab-Aziz\fvm\default\bin to the front of your path.
! Warning: `dart` on your path resolves to C:\Users\Ab-Aziz\fvm\versions\3.32.8\bin\dart, which is not inside your current Flutter SDK checkout at
C:\Users\Ab-Aziz\fvm\default. Consider adding C:\Users\Ab-Aziz\fvm\default\bin to the front of your path.
[√] Windows Version (11 Pro 64-bit, 24H2, 2009)
[√] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
[√] Chrome - develop for the web
[X] Visual Studio - develop Windows apps
X Visual Studio not installed; this is necessary to develop Windows apps.
Download at https://visualstudio.microsoft.com/downloads/.
Please install the "Desktop development with C++" workload, including all of its default components
[√] Android Studio (version 2024.3)
[√] VS Code (version 1.99.3)
[√] Connected device (4 available)
[√] Network resources
Metadata
Metadata
Assignees
Labels
in triagePresently being triaged by the triage teamPresently being triaged by the triage teamwaiting for customer responseThe Flutter team cannot make further progress on this issue until the original reporter respondsThe Flutter team cannot make further progress on this issue until the original reporter responds