Подтвердить что ты не робот

Как решить ошибку сборки для продукта, когда ссылочный, но ненужный источник/ресурс не найден?

У меня есть проект и у него есть 2 аромата продукта со своими собственными каталогами:

build.gradle:

android {
    ...
    productFlavors {
            free {
                applicationId "com.sample.free"
                 buildConfigField "boolean", "free", "true"
            }
            paid {
                applicationId "com.sample"
                buildConfigField "boolean", "free", "false"
            }
    }
}

И у меня есть класс (например, PaidOperationClass), который используется только в paid. Итак, я поместил этот класс в каталог src/paid/java. И у меня есть другой класс (например, CommonClass), который используется обоими вкусами. Поэтому я помещал это в каталог src/main/java:

src/main/  --> has CommonClass
src/free/
src/paid/  --> has PaidOperationClass

В CommonClass У меня есть метод, например:

if(!BuildConfig.FREE) {
    PaidOperationClass.doSomeStuff();
}

Таким образом, ссылка PaidOperationClass указана (имеет импорт), но никогда не используется свободной сборкой.

Если я создаю приложение для paid, все работает отлично. Но если я попытаюсь создать его для free вкуса, он терпит неудачу, потому что ссылочный, но ненужный класс не найден. Как вы решаете это без репликации кода (класса/метода) (например, помещать фиктивный PaidOperationClass под free)? Есть ли какие-либо опции gradle, которые игнорируют такие ошибки сборки при построении?

Изменить: Мне нужно решение gradle, которое не нуждается в репликации кода. Пользовательский script на основе аннотации, возможно, удаляет ненужный код для вкусов продукта во время компиляции.

4b9b3361

Ответ 1

Вы не можете этого сделать, потому что оператор импорта находится внутри CommonClass, и он не может разрешить PaidOperationClass в свободном вкусе.

Один из способов добиться этого:

Создайте пустой класс в Свободный аромат:

public class PaidOperationClass{

  public static void doSomeStuff(){
      //do nothing..    
  }
}

Ответ 2

Самым простым решением может быть создание класса: IPaidOperations, который размещается в директории /src/main, которую реализует PaidOperationClass. Затем просто используйте интерфейс в CommonClass.

Ответ 3

Вы ссылаетесь на пакет paid из пакета free независимо от того, используете ли вы:

if(!BuildConfig.FREE) {
     PaidOperationClass.doSomeStuff();
}

Поэтому я предлагаю один из двух вариантов:

1.
Итак, если у вас есть код, который никогда не используется, зачем вы его держите? Удалите его и замените его:

if(!BuildConfig.FREE) {
     // Do something within the imported packages.
}

В противном случае вы должны импортировать пакет paid.

2.
Или имеете две версии пакета free

free_paid и free_no_paid и удалите ссылку paid в free_no_paid и используйте это при компиляции без paid и используйте пакет free_paid при компиляции с paid.

Ответ 4

Другим решением является создание двух CommonClass es - как в free, так и paid исходном наборе (но не в main), которые содержат код, специфичный для конкретного аромата. Например: src/free/java/.../CommonClass.java:

doSomeStuff() {
  doSomeFreeStuff();    
}

src/paid/java/.../CommonClass.java:

doSomeStuff() {
  doSomePaidStuff();    
}

В этом случае код, расположенный в исходном наборе main, может ссылаться на CommonClass#doSomeStuff() независимо от того, какой вкус создан. Будет составлен только один CommonClass для конкретного вкуса. Другими словами, вместо использования ifs вручную вы позволяете gradle выбирать соответствующий класс для компиляции.

Вы также можете извлечь действительно общий код (который не зависит от чего-либо конкретного для free и paid) от CommonClass до абстрактного класса, т.е. BaseCommonClass помещается в исходный набор main и позволяет CommonClass расширять его.