第6周

1. 如何理解Gradle?Gradle在Android的构建过程中有什么作用?

Gradle 是基于 Groovy 的 DSL(domain specific language),即领域专用语言。可以理解为用于在某个特定领域下解决问题的小语言。DSL 分为外部 DSL 和内部 DSL。像 Android 中使用 xml 描述布局文件,使用 json 描述数据信息,sql 语句操作数据库,都属于外部 DSL。而 Gradle 属于内部 DSL,基于 Groovy 语言,定义了各种语义来构建。

Gradle 是一种构建工具。
在 Android 中的作用:

  1. 差异化管理。我们每天都在 build,clean,签名,打包,发布, 这些过程都可以被代码描述出来,关键是可以被我们复用。在 Android 中,通常面对国内 N 个市场需要多渠道打包,或者针对不同手机品牌,不同手机尺寸做定制化的处理。通过 gradle 的 productFlavor 与 buildtype 可以是实现这种差异管理。
  2. 方便的依赖管理。只需要一个具体的坐标地址就可以加载各种库。库的版本也很方便,直接指定就可以,不同工程重复依赖最终只有一份。
  3. 项目部署。通过插件自动将项目上传到指定仓库。

2. 实践如下问题。

问题:我们都知道,Android中时常需要发布渠道包,需要将渠道信息附加到apk中,然后在程序启动的时候读取渠道信息。
动态指定一个渠道号(比如1001),那么构建的apk中,请在它的AndroidManifest.xml文件里面的application节点下面添加如下meta-data,请写一段Gradle脚本来自动完成:

 
        

要求:当通过如下命令来构建渠道包的时候,将渠道号自动添加到apk的manifest中。
./gradlew clean assembleRelease -P channel=1001

实践

基本思路是通过在 AndroidManifest.xml 中定义 metameta 中的 channel 值使用 ${name} 形式的占位符动态设置渠道号的值。

占位符使用 manifestPlaceholders 指定:

manifestPlaceholders = [CHANNEL: channel]

指定的时候需要指定一个变量 channel。这个变量 channel 的值我们接下来在 -P 命令中设置。此时直接编译通不过,因为 channel 是没有被定义过的。
在 gradle.properies 文件中定义 channel:

通过 gradle 的 -P 命令可以为某个属性设置值,哪怕这个属性没有定义。gradle -P channel=10001 就是给 channel 属性设置了一个 10001 值。

最终通过获取 meta 的值获取动态设置的渠道号。

android {
  compileSdkVersion 27
  defaultConfig {
    applicationId "me.luwenjie.gradledemo"
    minSdkVersion 21
    targetSdkVersion 27
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    manifestPlaceholders = [CHANNEL: channel]
  }

  signingConfigs {
    release {
      storeFile file("key.jks")
      storePassword "123456"
      keyAlias "demo"
      keyPassword "123456"
      v1SigningEnabled true
      v2SigningEnabled true
    }
  }

  buildTypes {
    release {
      signingConfig signingConfigs.release
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }
}

AndroidManifest.xml 设置占位符:


    

        

在 MainActivity 中获取渠道号。

public class MainActivity extends AppCompatActivity {

  @SuppressLint("SetTextI18n") @Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    TextView textView = findViewById(R.id.text);
    textView.setText("渠道号 = " + getChannel(this));
  }

  public static String getChannel(Context context) {
    try {
      return context.getPackageManager()
          .getApplicationInfo(context.getPackageName(),
              PackageManager.GET_META_DATA).metaData.getInt("channel", 0) + "";
    } catch (PackageManager.NameNotFoundException e) {
      e.printStackTrace();
      return "0";
    }
  }
}

最后运行 ./gradlew clean assembleRelease -P channel=1001channel 设置值。就可以打出不同的渠道号包。

你可能感兴趣的:(第6周)