programing tip

빌드 풍미 사용-소스 폴더 구조 및 올바르게 build.gradle

itbloger 2020. 6. 1. 19:05
반응형

빌드 풍미 사용-소스 폴더 구조 및 올바르게 build.gradle


참고 : Xavier의 답변 후 수정 된 답변

Android Studio에서 하나의 동일한 응용 프로그램 프로젝트에 다른 빌드 풍미 를 사용하려고합니다 . 그러나 적절하게 작동하도록 구성하는 데 끔찍한 시간이있는 것 같습니다.

단계 :

  1. 'Test'라는 새 Android Studio 프로젝트를 만듭니다.
  2. build.gradle *를 열고 다음 행을 추가하십시오.

    productFlavors {
    flavor1 {
        packageName 'com.android.studio.test.flavor1'
        }
    flavor2 {
        packageName 'com.android.studio.test.flavor2'
        }
    }
    
  3. Android Studio를 다시 시작한 후 Build Variants 섹션에 4 개의 빌드 변형이 표시 됩니다. 우리는 지금까지 제품 맛을 설정하는 데 성공했습니다. **
  4. 에 대한 새로운 소스 폴더 생성 flavor1을 ; 그러나 올바른 방법으로하고 있는지 확실하지 않습니다. 내가 한 방법은 다음과 같습니다.

    • 이 프로젝트의 패키지 이름은 다음과 같습니다. com.foo.test
    • srcflavor1의 경우 폴더를 마우스 오른쪽 버튼으로 클릭하면 실제로 구조가와 같은 방식으로 탐색기에서 개별 폴더를 만들었습니다 src/flavor1/java/com/foo/test/MainActivity.java.
    • 위의 내용은 'java'폴더가 파란색 이므로 IDE가 활성 소스 디렉토리를 알고 있음을 의미합니다. 또한 패키지가 자동으로 생성되었습니다. 그럼에도 불구하고 중복 클래스가 발견되었다는 경고가 표시됩니다. 여기 스크린 샷을 참조하십시오.
    • flavor2의 경우 패키지를 수동으로 만들려고했지만 flavor2의 'src'폴더가 파란색이 아니므로 마우스 오른쪽 버튼을 클릭하면 옵션이 다르므로 '새 패키지'를 사용할 수 없습니다. 여기 이미지를 참조하십시오.
    • flavor1의 경우 파란색으로 바뀌는 'res'디렉토리도 만들었지 만, 그럼에도 불구하고 다른 리소스를 사용하려는 경우 Android 리소스 파일 또는 Andorid 리소스 디렉토리를 만들 수는 없습니다. 다른 풍미를위한 resoruces.

내가 뭔가 잘못하고 있습니까? 아니면 뭔가 빠졌습니까? 더 많은 정보가 필요하면 알려주십시오.

* 내 프로젝트에는 두 개의 build.gradle 파일 이있는 것 같습니다 . 하나는 프로젝트 폴더의 루트 (\ GradleTest)에 있으며 비어 있습니다. 두 번째 것은 \ GradleTest의 하위 폴더 루트에 있으며 'GradleTest'(GradleTest-GradleTest)라고도합니다.이 코드는 열렸을 때 이미 코드가있는 것입니다. 그러므로 그것은 내가 편집 한 것입니다.

** gradle 설정을 확인했으며 자동 가져 오기 사용이미 활성화되어 있습니다. 그럼에도 불구하고 build.gradle 파일을 변경해도 빌드 변형이 자동으로 업데이트되지는 않습니다 . 참고 : 또한 Build-Rebuild Project 및 / 또는 Build-Make Project, no-go를 사용해 보았습니다. 여전히 프로젝트를 닫고 변경 사항을 적용하려면 다시 열어야합니다.


Studio 환경 설정에있는 경우 Gradle 섹션에서 프로젝트에 대해 자동 가져 오기를 활성화 할 수 있습니다 (나중에 기본적으로 활성화). 이렇게하면 Studio에서 build.gradle을 편집 할 때마다 다시 가져올 수 있습니다.

플레이버를 생성한다고해서 사용자 정의 코드를 사용한다는 의미는 아니므로 폴더를 생성하지 않습니다. 직접 작성해야합니다.

내 IO 토크 를 보면 맛과 빌드 유형의 값을 혼합하여 변형을 만드는 방법을 볼 수 있습니다.

Java 소스의 경우 :

src/main/java
src/flavor1/java
src/debug/java

3 개는 모두 단일 출력을 생성하는 데 사용됩니다. 이는 동일한 클래스를 정의 할 수 없음을 의미합니다.

두 가지 플레이버에서 동일한 클래스의 다른 버전을 사용하려면 두 가지 플레이버에서 모두 동일한 클래스를 작성해야합니다.

src/flavor1/java/com/foo/A.java
src/flavor2/java/com/foo/A.java

그리고 src / main / java의 코드는 할 수 있습니다

import com.foo.A

선택한 맛에 따라 올바른 버전의 com.foo.A가 사용됩니다.

이것은 또한 두 버전의 A가 동일한 API를 가져야 함을 의미합니다 (적어도 src / main / java / ...의 클래스가 사용하는 API에 관해서는 ...

수정 된 질문과 일치하도록 편집

또한 상호 배타적 인 소스 폴더에만 동일한 A 클래스를 배치하는 것이 중요합니다. 이 경우 src / flavor1 / java와 src / flavor2 / java는 함께 선택되지 않지만 main과 flavor1은 함께 선택됩니다.

다른 플레이버에서 다른 버전의 활동을 제공하려면 src / main / java에 두지 마십시오.

3 개의 플레이버가 있고 플레이버 1에 대한 사용자 정의 1 개만 원하는 경우, 플레이버 2와 플레이버 3는 동일한 활동을 공유하지만 다른 2 개의 활동에 대한 공통 소스 폴더를 작성할 수 있습니다. 새 소스 폴더를 만들고이를 사용하도록 소스 세트를 구성 할 때 유연성이 뛰어납니다.

다른 포인트로 :

두 번째 플레이버 소스 폴더가 파란색이 아닌 것이 정상입니다. 활성화하려면 2 차 플레이버로 전환 한 다음 내부에 패키지 및 클래스를 만들 수 있습니다. 그때까지 Studio는 소스 폴더로 간주하지 않습니다. IDE에서 비활성 소스 폴더를 인식하도록 향후이를 개선 할 수 있기를 바랍니다 .

res 폴더에 리소스 파일을 만들 수 없다는 것도 정상적인 생각입니다. 이러한 추가 리소스 폴더를 모두 처리하도록 메뉴 시스템이 업데이트되지 않았습니다. 이것은 나중에 올 것이다.


Android의 "제품 맛"

다른 호스트, 아이콘 또는 패키지 이름을 사용하여 동일한 앱의 다른 버전에 의존하는 방법에 대해 때때로 질문을 받았습니다.

이를 수행해야하는 많은 이유와 한 가지 쉬운 방법이 있습니다 : 제품 맛.

You can define on your build.gradle script these kind of things I've described before.

Product flavors Part of this article is written thinking on product flavors, so, what are they? Regarding to Android documentation:

A product flavor defines a customized version of the application build by the project. A single project can have different flavors which change the generated application.

How can you define them? You must write on your build.gradle which flavors you want to define:

productFlavors {  
        ...
        devel {
            ...
        }

        prod {
            ...
        }
    }

Now, we will have two different flavors of our app. You can check it on Android Studio too inside the Build Variants tab

Build variants

Multiple package names

What if you want to have installed on your phone one app with development state and one for production state. As you might know, you can only install one app with the same package name (if you try to install some new APK with the same as one that's installed on your phone, it will try to update it).

The only thing you have to do is to define it on each of your product flavors:

android {  
    productFlavors {
        devel {
            applicationId "zuul.com.android.devel"
        }
        prod {
            applicationId "zuul.com.android"
        }
    }
}

Send requests to multiple hosts depending on the flavor As before, you must include some params on your product flavor config field.

android {  
    productFlavors {
        devel {
            applicationId "zuul.com.android.devel"
            buildConfigField 'String', 'HOST', '"http://192.168.1.34:3000"'

        }

        prod {
            applicationId "zuul.com.android"
               buildConfigField 'String', 'HOST', '"http://api.zuul.com"'

        }
    }
}

As an example, we will try to show you how you can integrate this with Retrofit to send request to the appropiate server without handling which server you're pointing and based on the flavor. In this case this is an excerpt of the Zuul android app:

public class RetrofitModule {

    public ZuulService getRestAdapter() {
        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint(BuildConfig.HOST)
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .build();
        return restAdapter.create(ZuulService.class);
    }

}

As you can see you just have to use the BuildConfigclass to access the variable you've just defined.

Any variable available through your code The HOST variable is not the only one you can expose in your code. You can do it with whatever you want:

prod {  
    applicationId "zuul.com.android"
    buildConfigField 'String', 'HOST', '"http://api.zuul.com"'
    buildConfigField 'String', 'FLAVOR', '"prod"'
    buildConfigField "boolean", "REPORT_CRASHES", "true"
}

You can access them as follows:

BuildConfig.HOST  
BuildConfig.FLAVOR  
BuildConfig.REPORT_CRASHES  

Different icons per flavor If you want to have different icons per flavor, so you can visually detect which one you're opening (you could do it by the name too... But it could not fit the space!), you just have to define new directory structures for each of the flavors.

In the example I've just used there are two flavors: devel and prod. Then, we could define an two new directory structures so we can define the resources we want:

structure

This works with other types of resources like strings.xml, integers.xml, arrays.xml, etc.

Configure Signing Settings

To manually configure the signing configurations for your release build type using Gradle build configurations:

1.Create a keystore. A keystore is a binary file that contains a set of private keys. You must keep your keystore in a safe and secure place. 2.Create a private key. A private key represents the entity to be identified with the app, such as a person or a company. 3.Add the signing configuration to the module-level build.gradle file:

android {
...
defaultConfig {...}
signingConfigs {
    release {
        storeFile file("myreleasekey.keystore")
        storePassword "password"
        keyAlias "MyReleaseKey"
        keyPassword "password"
    }
}
buildTypes {
    release {
        ...
        signingConfig signingConfigs.release
    }
}

}

Generate a signed APK:

To generate a signed APK, select Build > Generate Signed APK from the main menu. The package in app/build/apk/app-release.apk is now signed with your release key.

ref: https://developer.android.com/studio/build/build-variants.html#signing,http://blog.brainattica.com/how-to-work-with-flavours-on-android/


It seems you need to reload your project after adding new flavors in build.gradle. After that, you will see 4 build Variants in the Build Variants view (you access it from the left edge of the window).

Regarding the additional source directories, it seems you need to create them by hand : src/flavor1/java and src/flavor2/java. You will see that changing the flavor in the "Build Variants" view will change the currently active source directories (directory is blue when it is an active source directory)

Finally, "gradle will create new sourceSets for your new flavors" means that gradle will create the objects android.sourceSets.flavor1 and android.sourceSets.flavor2 and you can use them in your build.gradle script. But those objects are created dynamically, that's why you don't see them in the build.gradle (I suggest you reading this : http://www.gradle.org/docs/current/userguide/tutorial_using_tasks.html Especially the 6.6: it explain the creation of dynamic task. A gradle script is a groovy script, so I suggest you to get familiar with groovy too)


I had the same issue when I migrated my project to Gradle. The problem was that the build didn't find the proper resources folder. I fixed it by adding this under the android element in build.gradle:

sourceSets {
        main {
            res.srcDirs = ['myProject/res']
        }
    }

Something that is important and blocked me for quite awhile is that the flavor name that needs to match the package as opposed to the package defined inside the flavor definition in gradle. For example:

src/flavor1/java/com/foo/A.java

will match

productFlavors {
  flavor1 {
    packageName 'com.android.studio.test.foobar'
  }
}

but

src/foobar/java/com/foo/A.java will not be used for the flavor1 build.


In gradle:

For Build Types you only need:

buildTypes {
   release{
    //proguard, signing etc.
   }
   debug {
    //development
   }
  }
}

And then for flavors you add the ones you need

productFlavors {
    pro {
        applicationIdSuffix '.paid'
        buildConfigField 'boolean', 'PRO', 'true'
    }
    free {
        applicationIdSuffix '.free'
        buildConfigField 'boolean', 'PRO', 'false'
    }
}

참고URL : https://stackoverflow.com/questions/16737006/using-build-flavors-structuring-source-folders-and-build-gradle-correctly

반응형