The article directories

    • Multi-channel packaging configuration
    • Android Studio multichannel packaging error
    • The complete build.gralde file
      • Custom config.gardle sample format
      • Configure build.gardle under module for multi-channel information

Multi-channel packaging configuration

There are many online platforms that use third-party frameworks for packaging, such as Umeng, WALL · E of Meituan, etc. These frameworks do have powerful functions, but it is really difficult to introduce a third-party framework for your own project just to make a multi-channel package. We specify the as version because I am currently using AndroidStudio 3.2. The latest version of AndroidStudio has some problems (I don’t know whether it still exists on the earlier version).

// flavorDimensions "versionCode" // flavorDimension ProductFlavors {// The dimension "versionCode" in parentheses can delete Alia {} Xiaomi {} Huawei {} Vivo {} Oppo {} Tencent {// dimension "versionCode" } } productFlavors.all { flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: flavor.name] }Copy the code

FlavorDimensions “versionCode” above can also be written in defaultconfig for uniform latitude configuration

defaultConfig { applicationId appConfig.appId minSdkVersion versions.minSdkVersion targetSdkVersion versions.targetSdkVersion versionCode versions.versionCode versionName versions.versionName flavorDimensions "VersionCode" // flavor Dimension is the version number, the unified dimension,  testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" }Copy the code

Android Studio multichannel packaging error

If a uniform latitude is not specified in the multi-channel configuration, i.e. the flavorDimensions attribute, the following error occurs

AAPT2 error, should first find the problem in their own code, do not see it is false, has not worked.

  1. If a uniform latitude is not specified in the multi-channel configuration, i.e. the flavorDimensions attribute, the following error occurs
Daemon: AAPT2 AAPT2-3.2.1 -4818971- Windows Daemon #0Copy the code

Do not set aapT2 to false at this time, now this method is obsolete and deprecated, so in the new AndroidStudio3.2 multi-channel packaging configuration must be specified in the same latitude, so it can be seen, see

  1. Error:error: failed to read PNG signature: file does not start with PNG signature

There is a problem with your resource file. It may be that a PNG image fails to be parsed. You can edit the image and save it for later use, or change the suffix of a PNG image to a JPG format. This problem is solvable.

The complete build.gralde file

It hides the project signature file and configuration information, as well as the appkey and APPID of the third party. For security reasons, it is written in a custom. Gradle file. This custom file does not need to be uploaded during version control, which effectively protects the project security

Custom config.gardle sample format

Ext. Versions = [// Local repository version compileSdkVersion: 26, buildToolsVersion: "26.0.3", minSdkVersion: 18, targetSdkVersion: 26, versionCode: 4, versionName: "1.2.1", supportVersion: "25.3.0", loggerVersion: Ext. AppConfig = [appId: 'dingshi.com.hibook', betaName: '@string/app_name', proName: '@string/app_name', // keyAlias : 'hibook', // keyPassword : 'hibook', // storeFile : 'hibook.jks', // storePassword: 'hibook', GETUI_APP_ID : "PhmRY1Uy8A9VrK2L2H8Qz3", GETUI_APP_KEY : "VXJjCzXD0M7UqsPzFbXtT7", GETUI_APP_SECRET : "ZmO60vhutt6NxMauNZJjl8", // EASEMOB_DEBUG : "1191180110115352#hello-book-dev", EASEMOB_DEBUG : "1191180110115352#hello-book", EASEMOB_RELEASE : "1191180110115352#hello-book", LOCALHOST_DEBUG : "\"http://api.linkbooker.com/\"", // LOCALHOST_DEBUG : "\"http://testapi.linkbooker.com/\"", LOCALHOST_RELEASE: "\"http://api.linkbooker.com/\"" ] ext.channel = [ HIBOOK_TEST_NAME: "test_channel", Baidu : "Baidu", Xiaomi : "Xiaomi", Huawei : "huawei", Vivo : "vivo", Oppo : "oppo", Tencent : "tencent", Server : "server" ]Copy the code

Configure build.gardle under module for multi-channel information

apply plugin: 'com.android.application' apply from: "$rootDir/config.gradle" android { signingConfigs { config { keyAlias appConfig.keyAlias keyPassword appConfig.keyPassword storeFile file(appConfig.storeFile) storePassword appConfig.storePassword } } compileSdkVersion versions.compileSdkVersion defaultConfig { applicationId appConfig.appId minSdkVersion versions.minSdkVersion targetSdkVersion versions.targetSdkVersion versionCode versions.versionCode versionName versions.versionName FlavorDimensions "versionCode" // Flavor Dimension  testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { buildConfigField "String", "LOCALHOST", appConfig.LOCALHOST_RELEASE minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' debuggable true jniDebuggable true renderscriptDebuggable true zipAlignEnabled true } debug { buildConfigField "String", "LOCALHOST", appConfig.LOCALHOST_DEBUG debuggable true jniDebuggable true signingConfig signingConfigs.config renderscriptDebuggable true minifyEnabled true pseudoLocalesEnabled true zipAlignEnabled true } } buildToolsVersion versions.buildToolsVersion // dexOptions { // incremental true // } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 // flavorDimensions "versionCode" // flavorDimension ProductFlavors {// The dimension "versionCode" in parentheses can delete Alia {} Xiaomi {} Huawei {} Vivo {} Oppo {} Tencent {// dimension "versionCode" } } productFlavors.all { flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: Flavor. The name]} / / AS3.0 version sets the apk name * * * * * * android applicationVariants. All {variant - > the variant. The outputs. All {the if (varie.name.endswith ("Debug")) {// Debug package outputFileName = "$applicationId" _v ${defaultConfig. VersionName} _ ${getDate ()} _code ${defaultConfig. VersionCode} _debug. The apk "} else {/ / release package variant.outputs.each { output -> def appName = 'athesismentor' def oldFile = output.outputFile def buildName def releaseApkName variant.productFlavors.each { product -> buildName = product.name } releaseApkName = appName + '-' + buildName + '-' + getDate() + '_release.apk' // output.outputFile = new File(oldFile.parent, releaseApkName) outputFileName =releaseApkName // outputFileName = "$applicationId _code _v ${defaultConfig. VersionName} ${defaultConfig. VersionCode} _ ${getDate ()}. _release apk "}}}}} / / get the static timestamp def getDate() { def date = new Date() def formattedDate = date.format('yyyy-MM-dd-HH_mm') return formattedDate } configurations.all { resolutionStrategy.eachDependency { DependencyResolveDetails details -> def requested = details.requested if (requested.group == 'com.android.support') { if (! requested.name.startsWith("multidex")) { details.useVersion versions.supportVersion } } } } dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation' com. Android. Support: appcompat - v7:28.0.0 'implementation 'com. Android. Support. The constraint, the constraint - layout: 1.1.3' testImplementation junit: junit: '4.12' androidTestImplementation 'com. Android. Support. Test: runner: 1.0.2' androidTestImplementation 'com. Android. Support. Test. Espresso: espresso - core: 3.0.2' implementation "com. Orhanobut: logger: $versions. UtilVersion"}Copy the code

Build automation apK names for ##Gradle3.0 and above (3.3) can be replaced by the following method

Android {buildType{build custom APK names}} {buildType{build custom APK names}}

android.applicationVariants.all { variant -> variant.outputs.each { output -> def outputFile = output.outputFile if (outputFile ! = null && outputfile.name.endswith ('.apk')) {def fileName = outputfile.name.replace (" default system name.apk", "Want to replace the name of the ${defaultConfig. VersionName} _ ${getDate ()}. The apk"). The output outputFile = new File (outputFile. Parent, fileName)}}}Copy the code

Of course, the above getDate method is still written under the root node other than the Android {} node

Static def date () {def date = new date () def formattedDate = date.format('MMddHHmm') return formattedDate} static def date () {def date = new date () def formattedDate = date.format('MMddHHmm') return formattedDate}Copy the code