使用ExoPlayer只播放广告

ExoPlayer是什么

通俗来讲,ExoPlayer是一个google开源的视频播放器,并且被youtube、google video等大型应用使用。具体介绍参考官网

ExoPlayer目前已经并入media3库中

为什么要用ExoPlayer播放广告

  • 原生的MediaPlayer 存在ANR等一系列稳定性问题
  • Google背书,内部支持各种协议以及IMA
  • Facebook、Mintegral等广告SDK内部也用的ExoPlayer [com.mbridge.msdk.playercommon.exoplayer2.video]

怎么使用ExoPlayer

简单使用去播放视频可以直接参考演示指南样例一步一步来

如果要再视频中播放广告根据官网的步骤插入广告即可,演示demo

如果只是简单的接入实现来说,整体还是比较简单的

我们应该如何去实现只播放广告资源呢

以下的代码改动都是基于演示demo,可以随改随验

1.使用MediaItem只设置广告,不设置流媒体资源

java 复制代码
MediaItem mediaItem =
    new MediaItem.Builder()
//        .setUri(contentUri)
        .setAdsConfiguration(new MediaItem.AdsConfiguration.Builder(adTagUri).build())
        .build();

确实可以只播放广告资源,但是在AdEventListener中收不到播放完成时COMPLETED的回调,此时会直接抛出异常,可以尝试tricky的做法在主流程中try-catch该异常,触发异常时认为广告播放完成,但这种做法并不推荐

2.使用MediaSource只设置广告

java 复制代码
AdsMediaSource adsMediaSource = new AdsMediaSource(
        new SilenceMediaSource(1000000), new DataSpec(adTagUri), 0, new DefaultMediaSourceFactory(this),
        adsLoader, playerView);
player.setMediaSource(adsMediaSource);

但是该adTagUri只能是网络地址,如果我们要用VAST/VMAP这种XML格式的文件,则需要使用SDK中提供的Util转化 new DataSpec(Util.getDataUriForString("application/xml", adTagUri)

然后...就出现了如下崩溃

less 复制代码
Exception in ADS_LOADER.REQUEST_ADS
com.google.ads.interactivemedia.v3.internal.zzwa: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.contains(java.lang.CharSequence)' on a null object reference
	at com.google.ads.interactivemedia.v3.internal.zzvi.zza(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.3:7)
	at com.google.ads.interactivemedia.v3.internal.zzvd.zzb(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.3:2)
	at com.google.ads.interactivemedia.v3.internal.zzhb.run(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.3:1)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
	at java.lang.Thread.run(Thread.java:764)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.contains(java.lang.CharSequence)' on a null object reference
	at com.google.ads.interactivemedia.v3.internal.zzgt.zza(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.3:1)
	at com.google.ads.interactivemedia.v3.internal.zzgx.zza(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.3:13)
	at com.google.ads.interactivemedia.v3.internal.zzdq.call(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.3:1)
	at com.google.ads.interactivemedia.v3.internal.zzvy.zza(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.3:1)
	at com.google.ads.interactivemedia.v3.internal.zzvp.run(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.3:4)
	at com.google.ads.interactivemedia.v3.internal.zzvz.run(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.3:1)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
	at java.lang.Thread.run(Thread.java:764) 

本以为是vast格式的问题,就使用googleads.github.io/googleads-i... 测试vast xml一切正常

在github中github.com/androidx/me... 得到是IMA SDK版本过高的问题,于是降低版本解决

此时总算可以正常只播放广告,且播放状态回调正常!

但随之引入了新问题 即

广告播放完成后最后一帧直接黑屏,如何解决?
  • 设置shutter view背景透明

(通过Layout Inspector工具查看布局得知有shutter view作为播放器的前景) 设置playerView.setShutterBackgroundColor(Color.TRANSPARENT);使透明

切换前后台后又是黑屏,如何解决?
  • 设置PlayerView为TextureView
xml 复制代码
<androidx.media3.ui.PlayerView
    android:id="@+id/player_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:surface_type="texture_view"/>
  • 新增ImageView,截取最后一帧bitmap并设置到ImageView上
java 复制代码
if (eventType == AdEvent.AdEventType.COMPLETED) {
  // 广告播放完成
  close.setVisibility(View.VISIBLE);
  bitmap = ((TextureView)playerView.getVideoSurfaceView()).getBitmap();

  lastFrame.setBackground(new BitmapDrawable(bitmap));
  Log.e(LOG_TAG, "ALL_ADS_COMPLETED");
}
广告点击跳转如何处理?
  • 由于混淆原因com.google.ads.interactivemedia.v3.impl.data.c不是一个定值;是SDK对应版本的com.google.ads.interactivemedia.v3.api.Ad接口的实现类
java 复制代码
private void adClick() {
  String actionUrl = ((com.google.ads.interactivemedia.v3.impl.data.c) event.getAd()).getClickThruUrl();
  if (TextUtils.isEmpty(actionUrl)) {
    return;
  }
  Intent intent = new Intent().setAction(Intent.ACTION_VIEW)
          .setData(Uri.parse(actionUrl))
          .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  startActivity(intent);
}
相关推荐
Meteors.44 分钟前
Android约束布局(ConstraintLayout)常用属性
android
alexhilton1 小时前
玩转Shader之学会如何变形画布
android·kotlin·android jetpack
whysqwhw6 小时前
安卓图片性能优化技巧
android
风往哪边走6 小时前
自定义底部筛选弹框
android
Yyyy4826 小时前
MyCAT基础概念
android
Android轮子哥7 小时前
尝试解决 Android 适配最后一公里
android
雨白8 小时前
OkHttp 源码解析:enqueue 非同步流程与 Dispatcher 调度
android
风往哪边走9 小时前
自定义仿日历组件弹框
android
没有了遇见9 小时前
Android 外接 U 盘开发实战:从权限到文件复制
android
Monkey-旭10 小时前
Android 文件存储机制全解析
android·文件存储·kolin