preface

The company consists of three business lines, each of which has its own app. Function modules inevitably overlap ~ For example, the live broadcast function was only used in line A, but due to business expansion, now line B and C also need to use the live broadcast function. At this point, it is necessary to make the live broadcast function into an independent live broadcast component for the use of three business lines.

conceived

Now that we’re going to make live as a component, what are the aspects that need to be considered?

  1. It can run independently and test the function of the component separately. It can also be used as an SDK for other projects
  2. Unified management: deployed to the privatized warehouse, other projects can be configured reference

Based on the practice

Global control configuration

The configuration in gradle.properties can be used directly in a project

# Whether to use isModule=true as moduleCopy the code

Build. Gradle configuration

  1. Configure the Android build plug-in
If (ismodule.toboolean ()){// lib apply plugin: 'com.android.library'}else{// Apply plugin: 'com.android.library'} 'com.android.application' }Copy the code
  1. Disable the applicationId configuration

Can’t have configuration as library or compile an error: Library projects cannot set applicationId. applicationId is set to ‘com.example.live’ in default config.

android { ... defaultConfig { if(! isModule.toBoolean()){ applicationId "com.example.live" } ... }Copy the code

Androidmanifest.xml configuration

1. Run independently

To run independently, you need to configure the Application and start the Activity

// Normal template <application Android :allowBackup="true" Android :icon="@mipmap/ic_launcher" Android :label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.TestAndroidManifest"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>Copy the code

2. Use it as a module

If used as a component by other projects, the application and startup entry configurations need to be modified

Intent-filter <activity android:name=".mainActivity "intent-filter <activity android:name=".mainActivity" android:exported="true"> </activity> </application>Copy the code

There are two questions:

  1. Can the property configuration in application not be removed?

After compiling, the AndroidManifest of all modules will be merged together, and an error will be reported if the same attributes are configured differently

Manifest merger failed : Attribute application@name value=(com.example.moduledemo.MainApplication) from AndroidManifest.xml:7:9-40
	is also present at [:live] AndroidManifest.xml:11:9-56 value=(com.example.live.LiveApplication).
	Suggestion: add 'tools:replace="android:name"' to <application> element at AndroidManifest.xml:6:5-23:19 to override.
Copy the code

App-module: Replace =” Android :name”; app-Module :replace=” Android :name” The following rules can be summarized by checking the output Androidmanifest.xml file through different configuration and rebuild:

  • If only one Module is configured with a custom Application, use that application directly
  • If each module is configured with a custom Application, conflicts need to be resolved. The application of the last compiled module will be used (for example: In demo, app-Module depends on live-Module. If you configure custom application, you will use the app defined in app-Module.
  1. Intent-filter (intent-filter) ¶

The merged file contains two activities that contain the information to start them. When you install your app, you’ll notice that there are two launch ICONS on your desktop, and clicking on them will behave the same way: open the first activity with the MAIN and LAUNCHER configured. Therefore, there is no need to keep this configuration.

3. Dynamically configure the AndroidManifest

Based on the above analysis, androidmanifest.xml needs to be adjusted to be used as a module and run as a standalone app. Then it is necessary to configure and use different AndroidManifest files according to the configuration

  1. Added Androidmanifest.xml for SDK in live-Module

Build. gradle configuration in live-Module dynamically references different Androidmanifest.xml

android {
    ...
    sourceSets {
        main {
            if(isModule){
                manifest.srcFile 'src/main/module/AndroidManifest.xml'
            }else{
                manifest.srcFile 'src/main/AndroidManifest.xml'
            }
        }
    }
}
Copy the code

conclusion

At this point, you can control whether to use the Live component as library by modifying the liModule in gradle.properties. Here is a question to consider: if we have several components like Live in our project, do they all need to do such tedious configuration? Can you extract these configurations for unified management?

To optimize the

1. Extract independent APP build scripts

Create a common_app_build.gradle file in the project root directory

apply plugin: 'com.android.application' android {compileSdk 31 defaultConfig {minSdk 21 targetSdk 31 versionCode 1 versionName "1.0"  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } sourceSets { main { manifest.srcFile 'src/main/AndroidManifest.xml' } } }Copy the code

2. Extract the build Library script

Create a common_LIBRary_build.gradle file in the project root directory

apply plugin: 'com.android.library' android {compileSdk 31 defaultConfig {minSdk 21 targetSdk 31 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } sourceSets { main { manifest.srcFile 'src/main/module/AndroidManifest.xml' } } }Copy the code

3. Create a Course Module (for verification)

4. Modify build.gradle for live and Course modules

The following uses the Live Module as an example

If (isModule.toboolean ()) {apply from: '.. /common_library_build.gradle' } else { apply from: '.. /common_app_build.gradle' } android { defaultConfig { if(! isModule.toBoolean()){ applicationId "com.example.live" } } }Copy the code

Subsequent similar components require only a simple configuration to achieve the first idea

The module released

Here’s an example of how to use the Live Module: # Google Docs: Use Maven Publish plugin

Publish the Live Module to the local repository

Add the following configuration to build.gradle in the Live Module

afterEvaluate { publishing { repositories { maven { url uri(".. /repo") } } publications { maven(MavenPublication) { from components.release groupId "com.example.live" artifactId Modulelive "version "1.0.0"}}}}Copy the code

The above configuration specifies to publish live to the project /repo/ directory. After sync completes, a Publish Task appears in live

Double-clicking Publish generates the aar file in the REPo

The build configuration root. Gradle

In order to use the AAR in the REPO, you need to add configuration

buildscript {
    repositories {
        ...
        maven {
            url('repo')
        }
    }
    ...
}
Copy the code

For use in app: configure build.gradle

dependencies { ... / / no direct reference to the project/project/API (' live ') / / to the configuration implementation 'com. Example. Live: modulelive: 1.0.0'... }Copy the code

The Live component can be used normally if rebuilt.

Publish to a remote repository

Because the project environment of different business lines is different, it is inconvenient to publish to the local project directory. Consider publishing components to a private repository within the company for use by all project teams:

publishing { ... // Repository url = "http://...." The credentials {username '' password ''}}}}Copy the code

conclusion

The above has mainly covered some of the basics of Android componentization and some of the flow of how to publish components. Of course, componentization includes more than that, including:

  • Intercomponent communication
  • Component jump
  • Componentization confusion
  • Component Resource Conflict
  • .

These aspects are in the componentized design needs to think and deal with the subsequent gradually improve the content of this piece

Gitee: indicates the Demo address