使用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);
}
相关推荐
白云LDC1 小时前
Android Studio新建Vecter asset一直显示Loading icons(转圈圈)的解决办法
android·ide·android studio
Rytter4 小时前
某气骑士 libtprt.so 反 Frida 机制分析与绕过
android·安全·网络安全
alexhilton5 小时前
揭密:Compose应用如何做到启动提升34%
android·kotlin·android jetpack
沐言人生7 小时前
React Native 源码分析1——HybridData 机制深度分析
android·react native
程序员陆业聪7 小时前
跨平台框架全景图:Flutter/KMP/KuiKly/RN的2026年格局
android
码云数智-园园8 小时前
Fibers(纤程)来了:打破阻塞,实现纯PHP下的异步非阻塞IO
android
shaoming377611 小时前
检查系统硬件配置是否满足PyCharm最低要求
android·spring boot·mysql
一起搞IT吧11 小时前
高通Camx功能feature分析之十五:insensor zoom介绍及实现
android·智能手机·相机
aqi0013 小时前
一文读懂 HarmonyOS 6.1 带来的十大重要升级
android·华为·harmonyos·鸿蒙·harmony
秋915 小时前
MySQL 9.7.0 使用详解:新特性、实战与避坑指南
android·数据库·mysql