自学内容网 自学内容网

Flutter - 安卓一次打包不同包名的apk

demo 地址: https://github.com/iotjin/jh_flutter_demo
代码不定时更新,请前往github查看最新代码

有时为了方便测试,同一个app需要在一个手机上装两个,直接改包名的话比较麻烦,这时可以通过添加flavor进行多维度打包,同一份代码可以设置不同的包名,app应用名称和应用图标

效果图

请添加图片描述

flutter 一键打出不同包名、应用名、版本名、签名、应用图标、版本号的安装包
Android Studio 一个工程打包多个不同包名的APK
Android Gradle —— flavorDimensions 与 productFlavors

配置

需要修改的文件有两个,一个是 android/app/build.gradle ,一个是 android/app/src/main/AndroidManifest.xml

在这里插入图片描述

productFlavors 配置

核心代码是在 build.gradle添加 productFlavors 配置


 flavorDimensions("default") // 定义一个维度,这个维度的名字叫default,和下面的productFlavors中的dimension "default"对应
    productFlavors {
        // app1 | dev
        app1 {
            dimension "default"
            // 设置applicationId(这里很重要,两个相同applicationId的apk不能同时安装在同一台Android手机中)
            // applicationId "com.jh.demo1"
            applicationId "${defaultConfig.applicationId}.dev"
            // 自动生成@string/app_name为demo 把AndroidManifest.xml中的 android:label="demo"替换成 android:label="@string/app_name"
            // resValue "string", "app_name", "jh-demo1"
            // 定义app_icon字段,在AndroidManifest.xml文件中用到
            manifestPlaceholders = [
                    app_name: "jh-demo1",
                    app_icon: "@mipmap/ic_launcher",
            ]
        }
        // app2 | prod
        app2 {
            dimension "default"
            // applicationId "com.jh.demo2"
            applicationId "${defaultConfig.applicationId}"
            // resValue "string", "app_name", "jh-demo2"
            manifestPlaceholders = [
                    app_name: "jh-demo2",
                    app_icon: "@mipmap/ic_launcher",
            ]
        }
    }

然后需要在 AndroidManifest.xmlandroid:iconandroid:label换成上面配置的app_nameapp_icon
替换前:

    <application
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher"
        android:label="jh_flutter_demo">

替换后:

        <application
            android:name="${applicationName}"
            android:icon="${app_icon}"
            android:label="${app_name}">

新的编译和打包命令

加入flavor 后,按原来的方式调试运行或者打包会报错

编译:

 flutter run --flavor app1 -t lib/main.dart

打包:

flutter build apk --flavor app1
添加flavor后编译报错
     需要在 编辑器顶部 Run/Debug Configuration 里面 build flavors 设置对应的flavor 如 app1

    编译运行命令
        flutter run --flavor app1 -t lib/main.dart

    打包命令
        flutter build apk --flavor app1 --release
        flutter build apk --release --flavor app1 --target-platform=android-arm64

    清除build缓存并且打包app1和app2的debug和release包
    flutter clean; flutter build apk --flavor app1 --debug; flutter build apk --flavor app1 --release; flutter build apk --flavor app2 --debug; flutter build apk --flavor app2 --release


     查看包名
       aapt dump badging D:\apk\xxx.apk | findstr package
       package: name='com.jh.jh_flutter_demo.dev' versionCode='6' versionName='3.16.0'

       aapt dump badging D:\apk\xxx.apk

     安裝apk
       adb install -r D:\apk\xxx.apk

点击run 按钮运行需要配置下图:
在这里插入图片描述
在这里插入图片描述

打包报错 可以添加下面代码

请添加图片描述

  lintOptions {
        //在打包Release版本的时候不进行检测
        checkReleaseBuilds false
        // 有报错也不会停止打包
        abortOnError false
        // 防止报错:Error: The resource string/app_name has not been translated
        disable 'InvalidPackage'
    }
//    https://github.com/flutter/flutter/issues/58247
//    https://issuetracker.google.com/issues/158753935

完整build.gradle代码

def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
    localPropertiesFile.withReader('UTF-8') { reader ->
        localProperties.load(reader)
    }
}

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
    flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
    flutterVersionName = '1.0'
}

apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('app/key/key.properties')  // 上面放置的路径
if (keystorePropertiesFile.exists()) {
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}

android {
    compileSdkVersion 33

    lintOptions {
        disable 'InvalidPackage'
    }

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "com.jh.jh_flutter_demo"
        minSdkVersion 21
        targetSdkVersion 33
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        multiDexEnabled true
        ndk {
            abiFilters  'armeabi-v7a', 'arm64-v8a', 'x86_64' // 'armeabi','x86'
        }
    }

    signingConfigs {
        release {
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
            storePassword keystoreProperties['storePassword']
            // v1SigningEnabled true
            // v2SigningEnabled true
        }
    }

    buildTypes {
//        debug {
//            signingConfig signingConfigs.release
//        }
        release {
            // TODO: Add your own signing config for the release build.
            // Signing with the debug keys for now, so `flutter run --release` works.
            signingConfig signingConfigs.release
        }
    }

    /*
     一次打包不同的apk

     添加flavor后编译报错
     需要在 编辑器顶部 Run/Debug Configuration 里面 build flavors 设置对应的flavor 如 app1

    编译运行命令
        flutter run --flavor app1 -t lib/main.dart

    打包命令
        flutter build apk --flavor app1 --release
        flutter build apk --release --flavor app1 --target-platform=android-arm64

    清除build缓存并且打包app1和app2的debug和release包
    flutter clean; flutter build apk --flavor app1 --debug; flutter build apk --flavor app1 --release; flutter build apk --flavor app2 --debug; flutter build apk --flavor app2 --release


     查看包名
       aapt dump badging D:\apk\xxx.apk | findstr package
       package: name='com.jh.jh_flutter_demo.dev' versionCode='6' versionName='3.16.0'

       aapt dump badging D:\apk\xxx.apk

     安裝apk
       adb install -r D:\apk\xxx.apk


     */

    flavorDimensions("default") // 定义一个维度,这个维度的名字叫default,和下面的productFlavors中的dimension "default"对应
    productFlavors {
        // app1 | dev
        app1 {
            dimension "default"
            // 设置applicationId(这里很重要,两个相同applicationId的apk不能同时安装在同一台Android手机中)
            // applicationId "com.jh.demo1"
            applicationId "${defaultConfig.applicationId}.dev"
            // 自动生成@string/app_name为demo 把AndroidManifest.xml中的 android:label="demo"替换成 android:label="@string/app_name"
            // resValue "string", "app_name", "jh-demo1"
            // 定义app_icon字段,在AndroidManifest.xml文件中用到
            manifestPlaceholders = [
                    app_name: "jh-demo1",
                    app_icon: "@mipmap/ic_launcher",
            ]
        }
        // app2 | prod
        app2 {
            dimension "default"
            // applicationId "com.jh.demo2"
            applicationId "${defaultConfig.applicationId}"
            // resValue "string", "app_name", "jh-demo2"
            manifestPlaceholders = [
                    app_name: "jh-demo2",
                    app_icon: "@mipmap/ic_launcher",
            ]
        }
    }

//    lintOptions {
//        //在打包Release版本的时候不进行检测
//        checkReleaseBuilds false
//        // 有报错也不会停止打包
//        abortOnError false
//        // 防止报错:Error: The resource string/app_name has not been translated
//        disable 'InvalidPackage'
//    }

//    https://github.com/flutter/flutter/issues/58247
//    https://issuetracker.google.com/issues/158753935

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }

}

flutter {
    source '../..'
}

dependencies {
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}


原文地址:https://blog.csdn.net/iotjin/article/details/138211933

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!