How do you manage multiple environments while developing Android apps?

前端 未结 6 745
隐瞒了意图╮
隐瞒了意图╮ 2020-12-22 23:15

We\'re building an Android app that connects to the cloud. We have a test URL for our APIs and a production URL. We connect the app to our local development machines to talk

相关标签:
6条回答
  • 2020-12-22 23:21

    You can try gradle buildType and productFlavor. It will allow you to specifiy different Environment variables like url, versionName, etc And applicationId which will allow you to have dev and prod builds. For more details http://developer.android.com/tools/building/configuring-gradle.html

    0 讨论(0)
  • 2020-12-22 23:23

    I don't know what's the best practice in that case, but I do like this:

    You could make your app a LIB and create 2 apps: production app and testing app. Import your lib for those apps and build their manifests (it's almost copy paste of the old one). Then you replace your /res/ files that are different in each app... (you could create a config.xml file that have the URL).

    0 讨论(0)
  • 2020-12-22 23:28

    With android studio and gradle its simple now.

    inside your app build.gradle edit signing configs

    signingConfigs {
        debug {
            storeFile file("debug.keystore")
            storePassword "..."
            keyAlias "..."
            keyPassword "..."
        }
    
        prod {
            storeFile file("prod.keystore")
            storePassword "..."
            keyAlias "..."
            keyPassword "..."
        }
    
        dev {
            storeFile file("dev.keystore")
            storePassword "..."
            keyAlias "..."
            keyPassword "..."
        }
    }
    

    add buildTypes

    buildTypes {
    
        debug {
            buildConfigField 'String', 'BASE_URL', '"http://127.0.0.1:8080/"'
            ......
            signingConfig signingConfigs.debug
        }
    
        prod {
    
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    
            buildConfigField 'String', 'BASE_URL', '"http://prod.example.com"'
            ......
            signingConfig signingConfigs.prod
        }
    
    
        dev {
            buildConfigField 'String', 'BASE_URL', '"http://dev.example.com"'
            ......
            signingConfig signingConfigs.dev
        }
    }
    

    In your code take base url configured in gradle file by this code.

    public final static String BASE_URL = BuildConfig.BASE_URL;
    

    You can also put different KEY or whatever which is build type specific in gradle file and in code it will take according to the build type you are running.

    Its even possible to have different package name.

    productFlavors {
        my_prod {
            applicationId "com.example.packtwo"
        }
        my_dev {
            applicationId "com.example.packone"
        }
    }
    

    In recent gradle config, there are some updates in specifying package name. You have to add flavourDimensions if using productFlavours. See below code with added flavourDimensions

    flavorDimensions "pack"
    
    productFlavors {
        flavor_dev {
            applicationId 'com.example.packtwo'
            dimension "pack"
        }
    
        flavor_prod {
            applicationId 'com.example.packone'
            dimension "pack"
        }
    }
    

    This will give you more details about product flavours and dimensions

    https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html

    Check for more possibilities...

    But if you are using different flavors you might have to deal with Manifest merging and all.

    0 讨论(0)
  • 2020-12-22 23:29

    Use Ant to build at least the production versions. This way you can set certain config values/flags during building. Let's say you have a config.xml file that contains the URL to the server. You can have different Ant build targets that will change the URL to point to the appropriate server. Check out this tutorial. It explains exactly how that is done.

    0 讨论(0)
  • 2020-12-22 23:37

    This is can be achieved using product flavours.

    For achieving this requirement:

    First of all, Create 2 files under the app folder of your project say development.props and production.props. Or you can add these 2 files in a package under app folder say config.

    Basically, these 2 files contain keys and values. This key is same for both files. But their values are different. These files contain one key say “SERVER_URL” and its value. It would be written like this:

    SERVER_URL=”Server_url_value”

    In this case, only URL is different. So, I have added only one key-value pair in Props file. You can add more.

    Then, create ProductFlavours in the app build.gradle file say development and production. Now, access different props files containing URLs in their correseponding flavours like this:

    productFlavors {
        development {
            getProps('./config/development.props').each { p ->
                buildConfigField 'String', p.key, p.value
            }
        }
        production {
            getProps('./config/production.props').each { p ->
                buildConfigField 'String', p.key, p.value
            }
        }
    }
    
    def getProps(path) {
        Properties props = new Properties()
        props.load(new FileInputStream(file(path)))
        return props
    }
    

    Now, For each flavour, there is a build type And this BuildType is added in app build.gradle. For example, Build type is Debug and release. And I have two flavours i.e. development and production. So, gradle task will be created using both flavour and build type like this:

    assemble{flavourName}{BuildType}
    

    Now, you need to type these commands only. It would generate required APK with its corresponding URL. Commands are:

    ./gradlew assembleProductionRelease would generate release build with Production URL.

    ./gradlew assembleDevelopmentDebug would generate debug build with Development URL.

    ./gradlew assembleProductionDebug would generate debug build with Production URL.

    ./gradlew assembleDevelopmentRelease would generate release build with development URL.

    Top three gradle task would be very helpful. But the last task would generate Release build with development URL. But this is not recommended. So, we should stop developer to execute this task i.e. ./gradlew assembleDevelopmentRelease

    Now To restrict developer to generate release build using Development URL, add this snippet in your app build.gradle file:

    android.variantFilter { variant ->
        if(variant.buildType.name.equals('release')
                && variant.getFlavors().get(0).name.equals('development')) {
            variant.setIgnore(true);
        }
    }
    

    Now, If we try to execute task i.e. ./gradlew DevelopmentRelease. Gradle would stop generating the build and throw exception and would say: This task assembleDevelopmentRelease is not found in the root project.

    0 讨论(0)
  • 2020-12-22 23:38

    This I think is considered as the bast practice in case you use android studio with gradle.

    You may want to look at this article: http://tulipemoutarde.be/2013/10/06/gradle-build-variants-for-your-android-project.html

    Also available in youtube video: https://www.youtube.com/watch?v=7JDEK4wkN5I

    This also allows you to have two different package name for the same app.

    It uses gradle flavors to achieve exactly what you are looking for and is very easy to implement.

    0 讨论(0)
提交回复
热议问题