Проблема с зависимостями возникает при использовании общих пакетов или библиотек, от которых зависит несколько других пакетов, но при этом они зависят от разных и несовместимых версий общих пакетов. Работа разработчиков Android стала значительно проще благодаря Gradle: чтобы добавить в сборку необходимую библиотеку, достаточно просто добавить одну зависимость в build.gradle. Но что происходит, когда две зависимости зависят от разных версий одной и той же библиотеки?
Gradle может разрешать зависимости автоматически, если обе они принадлежат одной конфигурации, т. е. конфигурации приложения. Предположим, Android SDK для Audience Network зависит от библиотеки exoplayer. Если вы добавляете другую версию библиотеки exoplayer, Gradle выберет и добавит самую последнюю версию. Но если обе зависимости принадлежат разным конфигурациям — приложения и тестирования, — Gradle выдаст ошибку. Ниже мы рассмотрим различные конфликты и способы их решения.
Прежде чем продолжить, обязательно ознакомьтесь с руководствами по началу работы с Audience Network и Android.
Посмотрите пример ниже. Обе зависимости в коде ниже относятся к одной и той же конфигурации и имеют внутреннюю зависимость от библиотеки org.hamcrest:hamcrest-core. Поскольку обе зависимости внутренне используют разные версии одной и той же библиотеки, в сборку добавляется самая старшая версия. В выводе синхронизации Gradle будет указано, что версия библиотеки hamcrest в финальной сборке автоматически обновлена с 1.1 до 1.3.
// Depends on version 1.3 of org.hamcrest:hamcrest-core androidTestImplementation 'junit:junit:4.12' // Depends on version 1.1 of org.hamcrest:hamcrest-core androidTestImplementation 'org.mockito:mockito-core:1.10.19'
Если обе зависимости принадлежат разным конфигурациям — приложения и тестирования, — Gradle выдаст ошибку. Посмотрите фрагмент кода ниже. Первая зависимость принадлежит конфигурации приложения, вторая — тестовой конфигурации. При сборке проекта произойдет сбой с исключением.
При выполнении инструментальных тестов основной и тестовый APK используют один и тот же путь класса. Если основной и тестовый APK используют одну и ту же библиотеку (например, Guava), но с разными версиями, сборка Gradle завершится сбоем. Если Gradle не обнаружит этого, ваше приложение может вести себя по-разному во время тестирования и во время обычного запуска (включая сбой в одном из случаев).
// Depends on version 1.3 of org.hamcrest:hamcrest-core implementation 'junit:junit:4.12' // Depends on version 1.1 of org.hamcrest:hamcrest-core androidTestImplementation 'org.mockito:mockito-core:1.10.19'
Это самый простой способ, однако он ограничивается зависимостями в одинаковых конфигурациях. Например, ваш модуль явно зависит от конкретной версии библиотеки ExoPlayer. При этом SDK Audience Network уже содержит другую версию ExoPlayer. По умолчанию сборка содержит старшую версию. При использовании фрагмента кода ниже в выводе синхронизации Gradle будет явно указано, что версия библиотеки ExoPlayer в финальной сборке автоматически обновлена с r2.4.2 до 2.7.3.
implementation 'com.google.android.exoplayer:exoplayer-core:2.7.3' implementation 'com.google.android.exoplayer:exoplayer-dash:2.7.3' ... // audience-network-sdk depends on exoplayer-core:r2.4.2 and exoplayer-dash:r2.4.2 implementation 'com.facebook.android:audience-network-sdk:4.28.1'
В большинстве ситуаций разработчикам необходимо контролировать, какая версия библиотеки в итоге будет добавляться в сборку. Для этого можно настроить build.gradle. Например, если ваши разработчики предпочитают более раннюю версию ExoPlayer r2.4.0, а не r2.4.2 в SDK Audience Network, то вы можете исключить этот модуль при объявлении зависимости audience-network-sdk. Метка исключения применяется и к зависимостям в разных конфигурациях.
В реальном проекте будет много зависимостей, относящихся к разным версиям одной и той же библиотеки. В этом случае, чтобы вы могли добавить требуемую версию этой библиотеки, метка исключения понадобится для каждой зависимости.
Сценарий 1. Зависимости в одной и той же конфигурацииimplementation 'com.google.android.exoplayer:exoplayer-core:r2.4.0' implementation 'com.google.android.exoplayer:exoplayer-dash:r2.4.0' ... // audience-network-sdk depends on exoplayer-core:r2.4.2 and exoplayer-dash:r2.4.2 implementation ('com.facebook.android:audience-network-sdk:4.28.1') { exclude group: 'com.google.android.exoplayer', module:'exoplayer-core' exclude group: 'com.google.android.exoplayer', module:'exoplayer-dash' }Сценарий 2. Зависимости в разных конфигурациях
// Depends on version 1.3 of org.hamcrest:hamcrest-core implementation 'junit:junit:4.12' // Depends on version 1.1 of org.hamcrest:hamcrest-core androidTestImplementation ('org.mockito:mockito-core:1.10.19'){ exclude group: 'org.hamcrest', module:'hamcrest-core' }
Это более аккуратный способ разрешения конфликта для зависимостей из разных конфигураций. В этом случае мы должны явно указать версию библиотеки, которую необходимо добавить в финальную сборку для любой из конфигураций.
Хотя этот способ и является более аккуратным, у него есть свой недостаток: при обновлении фактических зависимостей, таких как junit и mockito, разработчику необходимо обновить и конфликтующую библиотеку.
// Depends on version 1.3 of org.hamcrest:hamcrest-core implementation 'junit:junit:4.12' // Depends on version 1.1 of org.hamcrest:hamcrest-core androidTestImplementation 'org.mockito:mockito-core:1.10.19' // Explictly mention that include version 1.3 of org.hamcrest:hamcrest-core androidTestCompile 'org.hamcrest:hamcrest-core:1.3'
Это ещё один способ разрешения конфликта, при котором вместо объявления для одной конфигурации мы принудительно объявляем его для всех конфигураций. В примере ниже вы можете добавить свою собственную стратегию разрешения "resolutionStrategy" в build.gradle уровня модуля, чтобы указанная версия пакета добавлялась принудительно и независимо от зависимостей в одинаковых или разных конфигурациях.
Этот подход следует применять с осторожностью. В первом примере, если audience-network-sdk будет обновлен и эти библиотеки обновят версию библиотек exoplayer-core и exoplayer-dash, мы всё равно будем вынуждены использовать более старую версию. Сценарий применим и для второго подхода к решению, однако в этом случае мы принудительно устанавливаем версию зависимости для всех конфигураций, а не одну конфигурацию.
Сценарий 1. Зависимости в одной и той же конфигурацииandroid { configurations.all { resolutionStrategy.force 'com.google.android.exoplayer:exoplayer-core:r2.4.0' resolutionStrategy.force 'com.google.android.exoplayer:exoplayer-dash:r2.4.0' } }Сценарий 2. Зависимости в разных конфигурациях
android { configurations.all { resolutionStrategy.force 'org.hamcrest:hamcrest-core:1.1' } }
Тестирование интеграции рекламы в приложение
Отправьте приложение на проверку.
Как только мы получим запрос рекламы от вашего приложения или сайта, мы проверим его на соответствие Политике Audience Network и Нормам сообщества Facebook. Подробнее о нашем процессе проверки см. здесь.
Дополнительные ресурсы |
Руководство по началу работыТехническое руководство по началу работы с Audience Network | Справка по APIСправка по Facebook SDK для iOS |