Как создать две разные версии кодов для вариантов вкуса

Я хочу создать 2 версии Fragment для разных вариантов сборки, например, весь код будет отличаться во вкусе 1 от варианта 2. Я хочу решить эту проблему, не выполняя if-else на основе параметра BuildConfig.FLAVOR в коде. Это означает, что если у меня есть MapFragment, я хочу иметь точно такой же класс с именем MapFragment с другим кодом, когда создается другой вариант. Причина, по которой я хочу это сделать, заключается в том, что я не хочу иметь никаких ссылок на этот MapFragment из другой версии (вкус в каких-либо журналах или особенностях моего приложения. Это должно работать так же, как работает локализация string.xml или dimens.xml. Есть ли какие-либо способ как этого добиться?

Причина в том, что я использую карту Huawei и службы ag-connect, а также карту Google Play. Проблема в том, что Huawei использует некоторую фоновую службу определения местоположения, которая затем отклоняет мое приложение в Google Play. Этот вариант Huawei никогда не должен быть доступен в Google Play, это как отдельная копия приложения для Huawei Shop.

Это означает, что если я создам .apk из Google Play (вариант 1), я не буду включать в него какие-либо службы или классы ag-connect, а также ссылки / импорт из Huawei и наоборот.

ОБНОВИТЬ:

Когда я проверил комментарий ниже, я попытался создать sourceSets и повторно реализовать свои вкусы для этих новых наборов. Но он по-прежнему не компилируется.

Также мне нужно знать, как сочетать эти вкусы с типами и источниками. Потому что у меня 2 основных источника: google и huawei. Затем мне нужно 4 разновидности для каждого из этих источников, таких как googleProd, googleProdTest, googleDev, googleDevTest и то же самое для huawei, а также все они должны иметь отладку / выпуск типа сборки на случай, если я захочу выпустить их в магазин Google Play для тестирования. Проблема в том, что мне нужно что-то вроде субпродуктов. Каждая разновидность huawei (prod, test, dev, dev-test) будет использовать huawei sourceSet (main + huawei), а каждая разновидность google (prod, test, dev, dev-test) будет использовать google sourceSet (main + google). Это означает, что основными источниками будет код, общий для обоих, а источники google / huawei имеют разные версии одного и того же фрагмента.

Итак, это должны быть окончательные варианты сборки:

  1. googleProd (основной + google src)
  2. googleTest (основной + google src)
  3. googleDev (основной + google src)
  4. googleDevTest (основной + google src)
  5. huaweiProd (основной + huawei src)
  6. huaweiTest (основной + huawei src)
  7. huaweiDev (основной + huawei src)
  8. huaweiDevTest (основной + huawei src)

и тип сборки выпуска / отладки для всех 8. Итого 16 вариантов.

Это означает, что мне нужно знать, как объединить google src с вкусами prod, test, dev и dev-test и huawei src с вкусами huaweiProd, huaweiTest, huaweiDev и huaweiDev-test, поэтому мне не нужно иметь 4 идентичных фрагмента huawei и 4 фрагмента Google, которые являются идентичен для всех вкусов. Он должен работать как абстрактный класс / родительский класс.

A problem occurred evaluating project ':app'.
No signature of method: build_1t7zaa85nxlbgjo4n3n9fcb4s.android() is applicable for argument types: (build_1t7zaa85nxlbgjo4n3n9fcb4s$_run_closure1) values: [build_1t7zaa85nxlbgjo4n3n9fcb4s$_run_closure1@56b08118]

Код Gradle:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
//Google Crashlytics
apply plugin: 'com.google.firebase.crashlytics'
//Google Services
apply plugin: 'com.google.gms.google-services'
//Kotlin
apply plugin: 'kotlin-android-extensions'
android {
    compileSdkVersion 29

    def code = getVersionCodeTimestamp()

    defaultConfig {
        applicationId "----"
        minSdkVersion 21
        targetSdkVersion 29
        versionCode code
        versionName "2.5.5"
        vectorDrawables.useSupportLibrary = true
    }

    lintOptions {
        checkReleaseBuilds false
        abortOnError false
    }
    packagingOptions {
        exclude 'META-INF/atomicfu.kotlin_module'
    }
    signingConfigs {
        app{
           ...
        }
    }
    buildTypes {
        release {
            manifestPlaceholders = [crashlyticsCollectionEnabled:"true"]
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.app
        }
        debug {
            manifestPlaceholders = [crashlyticsCollectionEnabled:"false"]
            signingConfig signingConfigs.app
        }
    }

    sourceSets {
        google {
            java.srcDirs('src/main/java', 'src/google/java')
        }
        huawei {
            java.srcDirs('src/main/java', 'src/hua/java')
        }
    }

    flavorDimensions "production"
    productFlavors {
        google {
            prod {
                dimension "production"
                ...
            }
            test {
                dimension "production"
                ...
            }
            dev {
                ...
            }
            dev_test {
                ...
            }
        }

        huawei {
            prod {
                dimension "production"
                ...
            }
            test {
                dimension "production"
                ...
            }
            dev {
                ...
            }
            dev_test {
                ...
            }
        }
    }
}
dependencies {
    implementation project(':pin')
    //Kotlin SDK
    implementation 'androidx.core:core-ktx:1.3.2'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

    //Glide
    implementation 'com.github.bumptech.glide:glide:4.11.0'

    //Kotlin Coroutines
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.8'

    //AndroidX
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation 'androidx.appcompat:appcompat:1.3.0-alpha02'
    implementation 'androidx.palette:palette-ktx:1.0.0'

    //Google SDK
    implementation 'com.google.android.material:material:1.3.0-alpha03'
    implementation 'com.google.android.gms:play-services-location:17.1.0'
    implementation 'com.google.android.gms:play-services-maps:17.0.0'
    implementation 'com.google.maps.android:android-maps-utils:2.0.3'
    implementation 'com.google.zxing:core:3.4.0'

    //Google Crashlytics SDK
    implementation ('com.google.firebase:firebase-crashlytics:17.2.2') {
        transitive = true
    }
    //Google Analytics SDK
    implementation 'com.google.firebase:firebase-analytics:18.0.0'

    //Google Firebase Messaging
    implementation 'com.google.firebase:firebase-messaging:21.0.0'
    implementation 'com.google.firebase:firebase-core:18.0.0'

    //Huawei SDK
    huaweiImplementation 'com.huawei.hms:identity:4.0.1.300'
    huaweiImplementation 'com.huawei.hms:location:4.0.3.303'
    huaweiImplementation 'com.huawei.hms:maps:4.0.1.301'
}

person martin1337    schedule 01.03.2021    source источник


Ответы (1)


возможно, вы можете поместить другой класс реализации в разные каталоги, но имя пакета и родительский класс или интерфейс должны быть одинаковыми, а затем сбросить srcDirs в конфигурации аромата. https://developer.android.com/studio/build/build-variants#sourcesets

Например:

  1. создать аромат src dirs
app/src/google/java
app/src/huawei/java

  1. сбросить srcDirs в app / build.gradle
plugins {
    id 'com.android.application'
}

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.3"

    defaultConfig {
        applicationId "com.example"
        minSdkVersion 21
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        debug {
            minifyEnabled false
        }

        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    flavorDimensions("map", 'type')

    productFlavors {
        google {
            dimension "map"
        }

        huawei {
            dimension "map"
            apply plugin: 'com.huawei.agconnect'
        }

        shopDev {
            dimension "type"
        }

        shopProd {
            dimension "type"
        }

        shopTest {
            dimension "type"
        }
    }

    applicationVariants.all { variant ->
        def name = variant.name
        println("Starryi: " + name)
        if (name.contains('huawei')) {
            if (name.contains('ShopDev')) {
                variant.buildConfigField("String", "APP_FLAVOR_NAME", '\"HUAWEI_SHOP_DEV\"')

            } else if (name.contains('ShopTest')) {
                variant.buildConfigField("String", "APP_FLAVOR_NAME", '\"HUAWEI_SHOP_TEST\"')

            } else if (name.contains('ShopProd')) {

                variant.buildConfigField("String", "APP_FLAVOR_NAME", '\"HUAWEI_SHOP_PROD\"')
            }
        } else if (name.contains('google')) {
            if (name.contains('ShopTest')) {
                variant.buildConfigField("String", "APP_FLAVOR_NAME", '\"GOOGLE_SHOP_DEV\"')

            } else if (name.contains('ShopDev')) {
                variant.buildConfigField("String", "APP_FLAVOR_NAME", '\"GOOGLE_SHOP_TEST\"')

            } else if (name.contains('ShopProd')) {
                variant.buildConfigField("String", "APP_FLAVOR_NAME", '\"GOOGLE_SHOP_PROD\"')
            }
        }
    }

    sourceSets {
        google {
            java.srcDirs('/src/main/java', 'src/google/java')
        }
        huawei {
            java.srcDirs('/src/main/java', 'src/huawei/java')
        }
    }
}

dependencies {
    huaweiImplementation 'com.huawei.hms:identity:4.0.1.300'
    huaweiImplementation 'com.huawei.hms:location:4.0.3.303'
    huaweiImplementation 'com.huawei.hms:maps:4.0.1.301'
}
  1. выберите в окне вариантов сборки  введите описание изображения здесь

если вы хотите полностью изолировать google sdk и huawei sdk, вы можете создать два разных библиотечных модуля, один для карты google, а другой для карты huawei (два модуля карты должны иметь одинаковые общедоступные интерфейсы по некоторой договоренности), а затем отредактировать приложение / сборку .gradle для создания аромата зависит от правильного модуля. https://developer.android.google.cn/studio/build/dependencies?hl=en#variant_aware https://developer.android.com/studio/build/build-variants#dependencies.

person Starryi    schedule 01.03.2021
comment
Если я сделаю это так, я получу ошибку компиляции Gradle: Gradle sync failed: No signature of method: build_1t7zaa85nxlbgjo4n3n9fcb4s.android() is applicable for argument types: (build_1t7zaa85nxlbgjo4n3n9fcb4s$_run_closure1) values: [build_1t7zaa85nxlbgjo4n3n9fcb4s$_run_closure1@16d101c9] - person martin1337; 01.03.2021
comment
извините, это моя ошибка, образец кода градиента исправлен, и вы можете прочитать разработчик .android.com / studio / build / build-sizes # sourcesets, на этой странице есть подробное описание того, как настроить набор исходных текстов. - person Starryi; 01.03.2021
comment
Также вызов sourceSet как main нехорош, вероятно, это проблематично, потому что его функция, которая вызывается внутри самого Gradle как основная функция. Он имеет фиолетовый цвет, поэтому это не название источника, а основная функция. - person martin1337; 01.03.2021
comment
Затем, если я хочу реализовать конкретную реализацию в зависимостях, простой вызов huaweiImplementation 'com.huawei.hms:identity:4.0.1.300' не работает - person martin1337; 01.03.2021
comment
Тем не менее такая же ошибка возникает при компиляции - person martin1337; 01.03.2021
comment
Я допустил синтаксическую ошибку Gradle. Теперь пример файла gradle успешно протестирован для com.android.tools.build:gradle:4.1.2 и gradle-6.5. - person Starryi; 01.03.2021
comment
Я изменил его, но такая же ошибка возникает для Gradle. - person martin1337; 01.03.2021
comment
не могли бы вы вставить полное содержимое файла Gradle? - person Starryi; 01.03.2021
comment
Я обновил его, чтобы показать полный контент Gradle (я удалил конфиденциальную информацию ofc) - person martin1337; 01.03.2021
comment
Я пробовал и huaImplementation, и huaweiImplementation. Тот же результат. subflavor hua должен быть похож на абстрактный класс, чтобы охватывать все вкусы huawei - person martin1337; 01.03.2021
comment
в закрытие buildTypes следует поместить настройки вариантов dev / test / product. Варианты сборки происходят из комбинации аромата и buildTypes. - person Starryi; 01.03.2021
comment
Значит, внутри будет вот так? productFlavors{ google { buildTypes { prod{} test{} dev{}} } } - person martin1337; 01.03.2021
comment
это должен быть android {buildTypes {prodc {} test {} dev {}}} - person Starryi; 01.03.2021
comment
Но каждый тип сборки имеет разные параметры для каждого вкуса. У вас есть prod для huawei и google и тест для huawei и google и т. Д. + У меня уже есть 2 типа сборки для отладки и выпуска - person martin1337; 01.03.2021
comment
параметр вкуса, настроенный в prod / test / dev, используется в коде константами? - person Starryi; 01.03.2021
comment
Да, каждый prod / test / dev имеет отдельные apiKey, serverURL и appName, определенные как параметр BuildConfig. Таким образом, это похоже на 8 различных вариантов, из которых 4 должны принадлежать Google, а 4 - Huawei. А также есть тип сборки отладки / выпуска, поэтому его 16 различных комбинаций. Также каждый продукт / тест / разработчик имеет другой applicationIdSuffix - person martin1337; 01.03.2021
comment
поэтому параметр productFlavor действительно может быть настроен в закрытии buildTypes, например buildTypes {prod {}}, закрытие prod включает константы, относящиеся к google и huawei. неиспользуемые константы будут отброшены, потому что minify - person Starryi; 01.03.2021
comment
Да, но huawei_prod и google_prod разные. У них разные константы и apiKeys. Эти сгенерированные файлы APK в основном загружаются в разные магазины. Поэтому я не могу обобщать prod в buildType. Его под источником. - person martin1337; 01.03.2021
comment
Позвольте нам продолжить это обсуждение в чате. - person Starryi; 02.03.2021
comment
Позвольте нам продолжить это обсуждение в чате. - person martin1337; 04.03.2021