mapbox_ad_flutter 0.3.0
mapbox_ad_flutter: ^0.3.0 copied to clipboard
Mapbox Ad SDK Flutter Plugin
mapbox-ad-flutter #
Installation #
- Run this command:
flutter pub add mapbox_maps_flutter
flutter pub add mapbox_ad_flutter
This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):
dependencies:
mapbox_maps_flutter: ^0.4.1
mapbox_ad_flutter: ^0.0.8
How to configure #
- import 'package:mapbox_maps_flutter/mapbox_maps_flutter.dart';
- import 'package:mapbox_ad_flutter/mapbox_ad_flutter.dart';
How to use #
1. Initialize MapboxAdManager and load ads #
In your map widget, initialize the MapboxAdManager and call loadAds after map style is loaded.
class _MapboxAdAppState extends State<MapboxAdApp> {
final _adManager = MapboxAdManager();
MapWidget? _mapView;
BuildContext? _context;
_onStyleLoadedListener(mbx.StyleLoadedEventData? data) {
if (_context == null) return;
_adManager.onStyleLoadedCallback();
_adManager.loadAds(
_mapView, null, MediaQuery.of(_context!), configuration: MapboxAdConfiguration.staging);
_adManager.callback = this;
}
@override
Widget build(BuildContext context) {
_context = context;
final MapWidget mapWidget = MapWidget(
key: const ValueKey("mapWidget"),
resourceOptions: ResourceOptions(accessToken: "MAPBOX_ACCESS_TOKEN"),
onStyleLoadedListener: _onStyleLoadedListener,
);
_mapView = mapWidget;
}
}
2. Must implement WidgetsBindingObserver mixin to provide app state to MapboxAdManager when app is resumed and paused #
class _MapboxAdAppState extends State<MapboxAdApp>
with WidgetsBindingObserver {
@override
void initState() {
WidgetsBinding.instance.addObserver(this);
super.initState();
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.resumed:
_adManager.onResume();
break;
case AppLifecycleState.paused:
_adManager.onPause();
break;
case AppLifecycleState.inactive:
break;
case AppLifecycleState.detached:
break;
}
}
}
About MapboxAdMBPCardView, MapboxAdAttributionView #
MapboxAdMBPCardView is a card view which contains ad contents when ad pin is tapped.
MapboxAdAttributionView is a card view which contains advertisement information when advertisement
button is tapped.
MapboxAdMBPCardView Method #
/// Attach view to the parent with animation.
/// @param context of the parent view to be attached.
/// @param completion The block to execute after the animation finishes.
attach(BuildContext context, {bool animated = true, Function()? completion});
/// Detach view from the parent with animation.
/// @param context of the parent view to be detached.
/// @param completion The block to execute after the animation finishes.
detach(BuildContext context, {bool animated = true, Function()? completion});
How to use #
Please show the MapboxAdMBPCardView in the MapboxAdCallback -> onAdDidSelect and hide the card
in the MapboxAdCallback -> onAdDidDeselect callback like the below sample code.
@override
onAdDidSelect(MapboxAdMBPCardView view, MapboxAd mapboxAd) {
if (_context != null) view.attach(_context!);
}
@override
onAdDidDeselect(MapboxAdMBPCardView view) {
if (_context != null) view.detach(_context!);
}
Card tap action type #
| Type | Description |
|---|---|
| route | Called when "Route" button is tapped. Please show route search widget. |
| navigation | Called when "Navigation" action is triggered. Please show navigation widget. "Navigation" button is currently hidden. |
| businessHours | Called when business hours field is tapped. |
| address | Called when address field is tapped. |
| externalLinkBanner | Called when banner is tapped. Transition to its URL by external/internal browser like below. |
| externalLinkDetailSite | Called when detail site button is tapped. Transition to its URL by external/internal browser like below. |
| externalLinkCall | Called when cs is tapped. Transition to its URL by external/internal browser like below. |
| externalLinkCallAttributionLink | Called when attribution add button is tapped. Transition to its URL by external/internal browser like below. |
@override
onAdDidTapCardAction(MapboxAdMBPCardTapAction action, MapboxAd mapboxAd,
{String url = ''}) async {
switch (action) {
case MapboxAdMBPCardTapAction.navigation:
//tapped navigation button
break;
case MapboxAdMBPCardTapAction.route:
//tapped route button
break;
case MapboxAdMBPCardTapAction.businessHours:
// tapped business hours area
break;
case MapboxAdMBPCardTapAction.address:
// tapped address area
break;
case MapboxAdMBPCardTapAction.externalLinkBanner:
// tapped banner
// launch url in browser
launchUrl(mapboxAd.url.toString());
break;
case MapboxAdMBPCardTapAction.externalLinkDetailSite:
// tapped detail site
// launch url in browser
await launchUrl(url);
break;
case MapboxAdMBPCardTapAction.externalLinkCall:
// tapped call
// launch url in browser
await launchUrl(url);
break;
case MapboxAdMBPCardTapAction.externalLinkAttributionLink:
// tapped attribution
// launch url in browser
await launchUrl(url);
break;
}
}
Card transition state #
Card transition state is notified from the following delegate.
@override
onAdDidTransitionCard(MapboxAdMBPCardTransition state) {
switch (state) {
case MapboxAdMBPCardTransition.collapsed:
// called the card is at the bottom of screen
break;
case MapboxAdMBPCardTransition.expanded:
// called the card is showing as full screen
break;
case MapboxAdMBPCardTransition.closed:
// called the card is closed
break;
}
}
- Example code
import 'package:flutter/material.dart';
import 'dart:math' as math;
import 'package:logger/logger.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:mapbox_maps_flutter/mapbox_maps_flutter.dart' as mbx;
import 'package:mapbox_ad_flutter/mapbox_ad_flutter.dart' as ad;
class MapboxAdApp extends StatefulWidget {
const MapboxAdApp({super.key});
@override
State<MapboxAdApp> createState() => _MapboxAdAppState();
}
///Widget state MUST implement `WidgetsBindingObserver` and `MapboxAdCallback`
class _MapboxAdAppState extends State<MapboxAdApp>
with WidgetsBindingObserver
implements ad.MapboxAdCallback {
/// TOKEN and Server Environment
static const environment = ad.AdsEnvironment.develop;
static const String accessToken = "ADD_ACCESS_TOKEN_HERE";
/// Demo Map Settings
static final center =
mbx.Point(coordinates: mbx.Position(139.776606, 35.682400)).toJson();
static const zoom = 14.281;
static const styleUrl =
"mapbox://styles/mapbox-ads/ckt3mhrk4088z18ponqip6fi6";
/// Add a `adManager` variable to the widget.
final _adManager = ad.MapboxAdManager();
mbx.MapWidget? _mapView;
ad.MapboxAdConfiguration? _config;
BuildContext? _context;
final _logger = Logger();
/// Add map to manager in `_onMapCreated` callback
_onMapCreated(mbx.MapboxMap mapboxMap) {
_adManager.onMapCreated(mapboxMap);
}
/// Load ads in `_onStyleLoadedListener` callback
_onStyleLoadedListener(mbx.StyleLoadedEventData? data) {
_adManager.onStyleLoadedCallback();
_loadAds();
}
/// Call `onMapIdle()`
_onMapIdle(mbx.CameraChangedEventData? data) {
_adManager.onMapIdle();
}
/// Call `onCameraIdle()`
_onCameraIdle(mbx.MapIdleEventData? data) {
_adManager.onCameraIdle();
}
/// Call `onMapClick()` and pass coordinates
_onMapClick(mbx.ScreenCoordinate coordinate) {
_adManager.onMapClick(math.Point(coordinate.x, coordinate.y));
}
/// Load ads private method
_loadAds() {
if (_context == null || _config == null) return;
final mediaQueryData = MediaQuery.of(_context!);
_adManager.loadAds(_mapView, null, mediaQueryData, configuration: _config);
_adManager.callback = this;
}
/// Get config private method
_getConfiguration(String accessToken) {
final rootConfig = ad.MapboxAdRootConfiguration();
rootConfig.sdk.adServer = ad.MapboxAdServerConfiguration.init(environment);
rootConfig.sdk.eventTrack =
ad.MapboxEventTrackConfiguration.init(environment);
rootConfig.sdk.token = accessToken;
final config = ad.MapboxAdConfiguration(rootConfig);
config.mediaID = "ADD_MEDIA_ID_HERE";
return config;
}
/// Build `MapboxMap` private method
_buildMapboxMap(String token) {
if (_context == null) return;
_config = _getConfiguration(accessToken);
final mbx.MapWidget mapWidget = mbx.MapWidget(
key: const ValueKey("mapWidget"),
resourceOptions: mbx.ResourceOptions(accessToken: accessToken),
cameraOptions: mbx.CameraOptions(center: center, zoom: zoom),
styleUri: styleUrl,
onMapCreated: _onMapCreated,
onStyleLoadedListener: _onStyleLoadedListener,
onCameraChangeListener: _onMapIdle,
onMapIdleListener: _onCameraIdle,
onTapListener: _onMapClick);
_mapView = mapWidget;
}
/// Attach card view on `onAdDidSelect` callback
@override
onAdDidSelect(ad.MapboxAdMBPCardView view, ad.MapboxAd mapboxAd) {
if (_context != null) view.attach(_context!);
_logger.d("onAdDidSelect");
}
/// Detach card view on `onAdDidDeselect` callback
@override
onAdDidDeselect(ad.MapboxAdMBPCardView view) {
if (_context != null) view.detach(_context!);
_logger.d("onAdDidDeselect");
}
/// Attach attribution view on `onAdShowAttribution` callback
@override
onAdShowAttribution(ad.MapboxAdAttributionView view) {
if (_context != null) view.attach(_context!);
_logger.d("onAdShowAttribution");
}
@override
onAdCloseAttribution(ad.MapboxAdAttributionView view) {
_logger.d("onAdCloseAttribution");
}
/// Alert private method
_showAlert(String title, String message) {
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(title),
content: Text(message),
actions: <Widget>[
TextButton(
style: TextButton.styleFrom(
textStyle: Theme
.of(context)
.textTheme
.labelLarge,
),
child: const Text('OK'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
/// Launch url private method
Future<void> _launchUrl(String url) async {
try {
final uri = Uri.parse(url);
await launchUrl(uri);
} catch (e) {
_logger.e(e);
}
}
/// Card Tap Actions
@override
onAdDidTapCardAction(ad.MapboxAdMBPCardTapAction action, ad.MapboxAd mapboxAd,
{String url = ''}) async {
switch (action) {
case ad.MapboxAdMBPCardTapAction.navigation:
_showAlert("Open navigation", "name:${mapboxAd.name}");
break;
case ad.MapboxAdMBPCardTapAction.route:
_showAlert("Open route", "name:${mapboxAd.name}");
break;
case ad.MapboxAdMBPCardTapAction.businessHours:
_logger.d("Taped business hours: ${mapboxAd.name}");
break;
case ad.MapboxAdMBPCardTapAction.address:
_showAlert("Open address", "name:${mapboxAd.address}");
break;
case ad.MapboxAdMBPCardTapAction.externalLinkBanner:
await _launchUrl(mapboxAd.url.toString());
break;
case ad.MapboxAdMBPCardTapAction.externalLinkDetailSite:
await _launchUrl(url);
break;
case ad.MapboxAdMBPCardTapAction.externalLinkCall:
await _launchUrl(url);
break;
case ad.MapboxAdMBPCardTapAction.externalLinkCallAttributionLink:
await _launchUrl(url);
break;
}
}
/// Card Transitions
@override
onAdDidTransitionCard(ad.MapboxAdMBPCardTransition state) {
switch (state) {
case ad.MapboxAdMBPCardTransition.collapsed:
_logger.d("collapsed");
break;
case ad.MapboxAdMBPCardTransition.expanded:
_logger.d("expanded");
break;
case ad.MapboxAdMBPCardTransition.closed:
_logger.d("closed");
break;
}
}
/// App Lifecycle
@override
void initState() {
WidgetsBinding.instance.addObserver(this);
super.initState();
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
/// Call `onResume()`
case AppLifecycleState.resumed:
_adManager.onResume();
break;
/// Call `onPause()`
case AppLifecycleState.paused:
_adManager.onPause();
break;
case AppLifecycleState.inactive:
break;
case AppLifecycleState.detached:
break;
}
}
/// Build widget
@override
Widget build(BuildContext context) {
_context = context;
_buildMapboxMap(accessToken);
return Scaffold(body: _mapView);
}
}
/// Run app
void main() {
runApp(const MaterialApp(home: MapboxAdApp()));
}