• AndroidX项目接入穿山甲广告填坑


            本文旨在记录初步接入过程遇到的一点点小问题,更详细的文档还是要参考官方文档

    一、项目版本

    GradlePlugin:8.0.2

    Gradle:8.0

    Kotlin:1.7.20

    compileSdk:34

    compose-bom:2022.10.00

    AS:2022.2.1

    穿山甲:5.6.0.7

    二、接入穿山甲SDK

    1.添加穿山甲SDK下载仓库
    1. maven {
    2. url 'https://artifact.bytedance.com/repository/pangle'
    3. }
     2.添加穿山甲SDK
    implementation 'com.pangle.cn:ads-sdk-pro:5.6.0.7'
    3.添加必要权限

            在当下隐私政策要求越来越严,如果不是必要场景尽量不要添加可选权限,且在初始化的时候配置SDK不可主动获取。

    1. <uses-permission android:name="android.permission.INTERNET" />
    2. <permission
    3. android:name="${applicationId}.openadsdk.permission.TT_PANGOLIN"
    4. android:protectionLevel="signature" />
    5. <uses-permission android:name="${applicationId}.openadsdk.permission.TT_PANGOLIN" />
    6. <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    7. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    8. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    9. <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    10. <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    11. <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
    12. <uses-permission android:name="android.permission.GET_TASKS"/>
    13. <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    14. <uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
    15. <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    16. <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
    17. <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
    4.添加provider
    1. <provider
    2. android:name="com.bytedance.sdk.openadsdk.TTFileProvider"
    3. android:authorities="${applicationId}.TTFileProvider"
    4. android:exported="false"
    5. android:grantUriPermissions="true">
    6. <meta-data
    7. android:name="android.support.FILE_PROVIDER_PATHS"
    8. android:resource="@xml/file_paths" />
    9. </provider>
    10. <provider
    11. android:name="com.bytedance.sdk.openadsdk.multipro.TTMultiProvider"
    12. android:authorities="com.lee.tts.TTMultiProvider"
    13. android:exported="false" />
    5.添加so库构架

            官网表示其他构架需要联系其技术支持。

    1. ndk {
    2. abiFilters 'armeabi-v7a', 'arm64-v8a'
    3. }
    6.初始化SDK
    1. //强烈建议在应用对应的Application#onCreate()方法中调用,避免出现contentnull的异常
    2. TTAdSdk.init(mContext, TTAdConfig.Builder()
    3. .appId("5438863")//xxxxxxx为穿山甲媒体平台注册的应用ID
    4. .useTextureView(true) //默认使用SurfaceView播放视频广告,当有SurfaceView冲突的场景,可以使用TextureView
    5. .appName("文本转语音助手")
    6. .titleBarTheme(TTAdConstant.TITLE_BAR_THEME_DARK)//落地页主题
    7. .allowShowNotify(true) //是否允许sdk展示通知栏提示,若设置为false则会导致通知栏不显示下载进度,存在违规风险,请勿随意更改
    8. .debug(true) //测试阶段打开,可以通过日志排查问题,上线时去除该调用
    9. .directDownloadNetworkType(TTAdConstant.NETWORK_STATE_WIFI) //允许直接下载的网络状态集合,没有设置的网络下点击下载apk会有二次确认弹窗,弹窗中会披露应用信息
    10. .supportMultiProcess(false) //是否支持多进程,true支持
    11. .customController(object : TTCustomController() { // 隐私信息控制开关
    12. /**
    13. * 是否允许SDK主动使用地理位置信息
    14. *
    15. * @return true可以获取,false禁止获取。默认为true
    16. */
    17. override fun isCanUseLocation(): Boolean {
    18. return false
    19. }
    20. /**
    21. * 当isCanUseLocation=false时,可传入地理位置信息,穿山甲sdk使用您传入的地理位置信息
    22. *
    23. * @return 地理位置参数
    24. */
    25. // override fun getTTLocation(): TTLocation? {
    26. // return null
    27. // }
    28. /**
    29. * 是否允许SDK主动使用手机硬件参数,如:imei
    30. *
    31. * @return true可以使用,false禁止使用。默认为true
    32. */
    33. override fun isCanUsePhoneState(): Boolean {
    34. return false
    35. }
    36. /**
    37. * 当isCanUsePhoneState=false时,可传入imei信息,穿山甲sdk使用您传入的imei信息
    38. *
    39. * @return imei信息
    40. */
    41. // override fun getDevImei(): String? {
    42. // return null
    43. // }
    44. /**
    45. * 是否允许SDK主动使用ACCESS_WIFI_STATE权限
    46. *
    47. * @return true可以使用,false禁止使用。默认为true
    48. */
    49. // override fun isCanUseWifiState(): Boolean {
    50. // return true
    51. // }
    52. /**
    53. * 是否允许SDK主动使用WRITE_EXTERNAL_STORAGE权限
    54. *
    55. * @return true可以使用,false禁止使用。默认为true
    56. */
    57. override fun isCanUseWriteExternal(): Boolean {
    58. return false
    59. }
    60. /**
    61. * 开发者可以传入oaid
    62. * 信通院OAID的相关采集——如何获取OAID:
    63. * 1. 移动安全联盟官网http://www.msa-alliance.cn/
    64. * 2. 信通院统一SDK下载http://msa-alliance.cn/col.jsp?id=120
    65. * @return oaid
    66. */
    67. // override fun getDevOaid(): String? {
    68. // return null
    69. // }
    70. /**
    71. * 是否允许SDK主动获取设备上应用安装列表的采集权限
    72. *
    73. * @return true可以使用,false禁止使用。默认为true
    74. */
    75. override fun alist(): Boolean {
    76. return false
    77. }
    78. /**
    79. * 是否允许SDK主动获取ANDROID_ID
    80. *
    81. * 4600新增
    82. *
    83. * @return 默认true 允许 , false 不允许
    84. */
    85. // override fun isCanUseAndroidId(): Boolean {
    86. // return true
    87. // }
    88. /**
    89. * 是否允许SDK在申明和授权了的情况下使用录音权限
    90. *
    91. * @return true 允许 false 不允许
    92. */
    93. // override fun isCanUsePermissionRecordAudio(): Boolean {
    94. // return true
    95. // }
    96. })
    97. .build())

    7.启动SDK

            穿山甲需要启动才能正常使用。 

    1. TTAdSdk.start(object : TTAdSdk.Callback {
    2. override fun success() {
    3. Log.d(TAG, "TTAdSdk.start success.")
    4. }
    5. override fun fail(code: Int, msg: String?) {
    6. Log.d(TAG, "TTAdSdk.start fail. code=$code, msg=$msg")
    7. }
    8. })

    三、填坑

    1.FileProvider

            从第二节第4点可以看到provider的meta-data是android.support.FILE_PROVIDER_PATHS,正常来说我们升级到AndroidX用的应该是androidx.core.content.FileProvider,我们先保持跟穿山甲文档一致然后运行。

    Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.v4.content.FileProvider"

            我们可以看到报错了,那改成 androidx.core.content.FileProvider再运行呢?还是一样的错,那就不是这个问题,如果有过support项目升级的经验,我们就知道在升级AndroidX的时候AS在gradle.properties添加了如下配置:

    1. android.useAndroidX=true
    2. # Automatically convert third-party libraries to use AndroidX
    3. android.enableJetifier=true

            useAndroidX不用说,关键是enableJetifier=true,看注释说的是自动将第三方SDK转换成使用AndroidX。看到这里就知道了,首先TTFileProvider用的是android.support的FileProvider,只能通过设置enableJetifier去转换。那么meta-data到底能不能改呢?带着这个疑问,我们继续运行:

    java.lang.RuntimeException: Unable to get provider com.bytedance.sdk.openadsdk.TTFileProvider: java.lang.IllegalArgumentException: Missing android.support.FILE_PROVIDER_PATHS meta-data

             看到报错就知道还是只能照着文档写,不能改!

    2.ClassNotFoundException

            解决完FileProvider问题后继续运行,这时候又有报错了。

    Caused by: java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/fragment/app/FragmentActivity;

    Caused by: java.lang.ClassNotFoundException: Didn't find class "androidx.appcompat.view.ContextThemeWrapper"

            这两个问题其实跟FileProvider是相连的,第三方SDK在enableJetifier=true时转换成AndroidX了,但是新建的项目并没有引用AndroidX的fragment,所以就报错了,加上就可以了。其实如果不是新建项目改成了compose应该是没有这个问题的,我记得compose之前创建项目会有相关依赖。

    1. implementation 'androidx.appcompat:appcompat:1.6.1'
    2. implementation 'androidx.fragment:fragment-ktx:1.5.5'

    四、开屏广告

            前面配置好了到这一步其实就简单了,只是有始有终再多写两句。

            首先,我们需要在穿山甲平台创建一个应用,具体截图就不插入了,没什么难点。

            然后,从文档了解到,如果需要播放广告,我们需要为应用新建广告位,比如开屏广告位,新建好之后会有个广告代码位字符串,这是我们请求相应广告位广告的关键。

            最后,上代码。

    1. mTTAdNative = TTAdSdk.getAdManager().createAdNative(this)
    2. val adSlot = AdSlot.Builder()
    3. .setCodeId("888565580")
    4. //不区分渲染方式,要求开发者同时设置setImageAcceptedSize(单位:px)和setExpressViewAcceptedSize(单位:dp )接口,不同时设置可能会导致展示异常。
    5. .setImageAcceptedSize(resources.displayMetrics.widthPixels, resources.displayMetrics.heightPixels)
    6. .setExpressViewAcceptedSize(resources.displayMetrics.widthPixels / resources.displayMetrics.density + 0.5f, resources.displayMetrics.heightPixels / resources.displayMetrics.density + 0.5f)
    7. .setAdLoadType(TTAdLoadType.PRELOAD)//推荐使用,用于标注此次的广告请求用途为预加载(当做缓存)还是实时加载,方便后续为开发者优化相关策略
    8. .build()
    9. mTTAdNative.loadSplashAd(adSlot, object : TTAdNative.CSJSplashAdListener {
    10. //开屏素材加载成功
    11. override fun onSplashLoadSuccess() {
    12. Log.d(TAG, "onSplashLoadSuccess")
    13. }
    14. //加载开屏素材失败
    15. override fun onSplashLoadFail(p0: CSJAdError?) {
    16. Log.d(TAG, "onSplashLoadFail=${p0?.msg}")
    17. //开发者处理跳转到APP主页面逻辑
    18. gotoMain()
    19. }
    20. //开屏渲染成功,可以展示开屏
    21. override fun onSplashRenderSuccess(ad: CSJSplashAd?) {
    22. Log.d(TAG, "onSplashRenderSuccess")
    23. ad?.let {
    24. mSplashView = it.splashView
    25. return
    26. }
    27. //开发者处理跳转到APP主页面逻辑
    28. gotoMain()
    29. }
    30. override fun onSplashRenderFail(ad: CSJSplashAd?, err: CSJAdError?) {
    31. Log.d(TAG, "onSplashRenderFail=${err?.msg}")
    32. //开发者处理跳转到APP主页面逻辑
    33. gotoMain()
    34. }
    35. }, 3500)

            至此穿山甲SDK的接入就已经完成了,后续的业务请根据自身需求进行开发。

    五、Demo代码

  • 相关阅读:
    golang学习笔记——fmt.Printf()、fmt.Print() 和 fmt.Println()区别
    第二周 优化算法实战
    不用电的计算机(二)
    C#连接MySql数据库详细步骤
    python从数据库导出电子表格
    ZYNQ_project:key_breath
    leetcode0207 链表相交
    12 个适合做外包项目的开源后台管理系统
    uniapp微信小程序地图实现周边
    Python 教程之控制流(4)Python 中的循环技术
  • 原文地址:https://blog.csdn.net/lr123838/article/details/133848159