Procházet zdrojové kódy

增加多Flavor打包;

maqiang před 7 měsíci
rodič
revize
73229f56e3

+ 5 - 25
README.md

@@ -15,28 +15,8 @@ For help getting started with Flutter development, view the
15 15
 [online documentation](https://docs.flutter.dev/), which offers tutorials,
16 16
 samples, guidance on mobile development, and a full API reference.
17 17
 
18
-### 2024.03.14 app改动点:
19
-1. 扦样任务单状态新增:待领取, 检测机构收到扦样任务通知时,所有扦样人员都能看到所有任务单据,在app待扦样页面进行任务领取.√
20
-现在的开始扦样按钮改成任务领取,点击任务领取以后扦样任务单状态改成待扦样,列表页按钮变成开始扦样,点击扦样进行正常操作。√
21
-2. 扦样人员变成多选,后端提供人员接口,选择扦样人员;√
22
-3. 温度、湿度字段去掉,新增字段:天气情况:晴天/阴天/雨天,单选;√
23
-4. 扦样时间默认给当前时间;√
24
-5. 灾害污染情况给默认值:否;√
25
-6. 点击经纬度获取,自动代入省市县乡镇村;√
26
-7. 列表页显示字段修改:扦样任务单号/状态/检验指标/样品等级/采样品种;√
27
-
28
-### 2024.04.18 app改动点:
29
-1. 收获环节<扦样任务单列表>的筛选页面及功能.
30
-2. 扦样单列表:
31
-   1. <扦样人员>字段未显示的问题.√
32
-   2. <检验指标>和<扦样地区>位置互换.√
33
-   3. <检验指标>和<样品等级>为空时不展示.√
34
-3. 扦样单详情:
35
-   1. 扦样单位、监测类别、样品编号都去掉.√
36
-   2. 高德定位结果填入乡镇和村.√
37
-   3. 用药情况删除改为长按弹框确认删除.√
38
-   4. 用药情况的施药时间字段有数据时下拉箭头不显示.√
39
-   5. 下拉箭头颜色都改为高亮文本颜色.√
40
-4. 新增内容:
41
-   1. 电子签名:点击扦样单提交时跳出签名弹窗,根据扦样人数签名,按钮:重写、上一位、下一位、提交。
42
-   2. 电子签名图片上传接口:/infra/file/upload
18
+## App编译打包
19
+打包分为两个环境, 对应不同的后端服务器.
20
+Android打包方式如下:
21
+- 测试环境:flutter build apk --flavor develop --release
22
+- 生产环境:flutter build apk --flavor product --release

+ 28 - 7
android/app/build.gradle

@@ -34,7 +34,7 @@ android {
34 34
 
35 35
     sourceSets {
36 36
         main {
37
-            jniLibs.srcDirs = ['jniLibs']
37
+            jniLibs.srcDirs = ['libs']
38 38
         }
39 39
     }
40 40
 
@@ -46,6 +46,10 @@ android {
46 46
         targetSdkVersion flutter.targetSdkVersion
47 47
         versionCode flutterVersionCode.toInteger()
48 48
         versionName flutterVersionName
49
+
50
+//        ndk {
51
+//            abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64'
52
+//        }
49 53
     }
50 54
 
51 55
     println "targetSdkVersion: ${flutter.targetSdkVersion}"
@@ -67,34 +71,51 @@ android {
67 71
         release {
68 72
             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
69 73
             signingConfig signingConfigs.release
70
-            manifestPlaceholders = [APP_NAME: "国粮质检"]
74
+
71 75
             shrinkResources false // 重要,打印机有so库,fix bug: https://github.com/flutter/flutter/issues/47527
72 76
             minifyEnabled false // 重要,打印机有so库,fix bug: https://github.com/flutter/flutter/issues/47527
73 77
         }
74 78
         profile {
75 79
             signingConfig signingConfigs.release
76
-            manifestPlaceholders = [APP_NAME: "国粮质检-测试"]
77
-            applicationIdSuffix ".debug"
78 80
             shrinkResources false // 重要,打印机有so库,fix bug: https://github.com/flutter/flutter/issues/47527
79 81
             minifyEnabled false // 重要,打印机有so库,fix bug: https://github.com/flutter/flutter/issues/47527
80 82
         }
81 83
         debug {
82 84
             signingConfig signingConfigs.release
83
-            manifestPlaceholders = [APP_NAME: "国粮质检-测试"]
84
-            applicationIdSuffix ".debug"
85 85
         }
86 86
     }
87 87
     android.applicationVariants.all {
88 88
         def buildType = it.buildType.name
89
+        def flavor = it.productFlavors[0].name
89 90
         def outputFile
90 91
         it.outputs.each {
91 92
             outputFile = it.outputFile
92 93
             // 名称_环境_版本名称_版本号.apk
93 94
             // lszlgl_release_0.0.2_2.apk
94
-            it.outputFileName = "lszlgl_${buildType}_${defaultConfig.versionName}_${defaultConfig.versionCode}.apk"
95
+            it.outputFileName = "lszlgl_${flavor}_${defaultConfig.versionName}_${defaultConfig.versionCode}.apk"
95 96
         }
96 97
     }
97 98
 
99
+    // 多渠道配置
100
+    flavorDimensions "default"
101
+
102
+    productFlavors {
103
+        develop {
104
+            dimension "default"
105
+            manifestPlaceholders = [APP_NAME: "国粮质检-测试"]
106
+            applicationIdSuffix ".debug"
107
+        }
108
+        product {
109
+            dimension "default"
110
+            manifestPlaceholders = [APP_NAME: "国粮质检"]
111
+        }
112
+    }
113
+
114
+    lintOptions {
115
+        checkReleaseBuilds false
116
+        abortOnError false
117
+    }
118
+
98 119
     dependencies {
99 120
         implementation fileTree(include: ['*.jar'], dir: 'libs')
100 121
         implementation 'com.amap.api:location:5.6.0'

android/app/jniLibs/arm64-v8a/libConfigFileINI.so → android/app/libs/arm64-v8a/libConfigFileINI.so


android/app/jniLibs/arm64-v8a/libLabelPrinterSDK.so → android/app/libs/arm64-v8a/libLabelPrinterSDK.so


android/app/jniLibs/arm64-v8a/libSimpleLogModule.so → android/app/libs/arm64-v8a/libSimpleLogModule.so


android/app/jniLibs/arm64-v8a/libc++_shared.so → android/app/libs/arm64-v8a/libc++_shared.so


android/app/jniLibs/armeabi-v7a/libConfigFileINI.so → android/app/libs/armeabi-v7a/libConfigFileINI.so


android/app/jniLibs/armeabi-v7a/libLabelPrinterSDK.so → android/app/libs/armeabi-v7a/libLabelPrinterSDK.so


android/app/jniLibs/armeabi-v7a/libSimpleLogModule.so → android/app/libs/armeabi-v7a/libSimpleLogModule.so


android/app/jniLibs/armeabi-v7a/libc++_shared.so → android/app/libs/armeabi-v7a/libc++_shared.so


android/app/jniLibs/x86/libConfigFileINI.so → android/app/libs/x86/libConfigFileINI.so


android/app/jniLibs/x86/libLabelPrinterSDK.so → android/app/libs/x86/libLabelPrinterSDK.so


android/app/jniLibs/x86/libSimpleLogModule.so → android/app/libs/x86/libSimpleLogModule.so


android/app/jniLibs/x86/libc++_shared.so → android/app/libs/x86/libc++_shared.so


android/app/jniLibs/x86_64/libConfigFileINI.so → android/app/libs/x86_64/libConfigFileINI.so


android/app/jniLibs/x86_64/libLabelPrinterSDK.so → android/app/libs/x86_64/libLabelPrinterSDK.so


android/app/jniLibs/x86_64/libSimpleLogModule.so → android/app/libs/x86_64/libSimpleLogModule.so


android/app/jniLibs/x86_64/libc++_shared.so → android/app/libs/x86_64/libc++_shared.so


+ 2 - 0
android/app/src/main/java/com/szls/lszlgl/MainActivity.java

@@ -8,6 +8,7 @@ import io.flutter.embedding.android.FlutterActivity;
8 8
 import io.flutter.embedding.engine.FlutterEngine;
9 9
 import io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister;
10 10
 import io.flutter.plugins.BluetoothPlugin;
11
+import io.flutter.plugins.FlavorPlugin;
11 12
 
12 13
 public class MainActivity extends FlutterActivity {
13 14
 
@@ -23,5 +24,6 @@ public class MainActivity extends FlutterActivity {
23 24
 
24 25
         //插件实例的注册,就是自己写个类,然后实现Flutter提供的FlutterPlugin接口
25 26
         flutterEngine.getPlugins().add(new BluetoothPlugin(this));
27
+        flutterEngine.getPlugins().add(new FlavorPlugin());
26 28
     }
27 29
 }

+ 53 - 0
android/app/src/main/java/io/flutter/plugins/FlavorPlugin.java

@@ -0,0 +1,53 @@
1
+package io.flutter.plugins;
2
+
3
+
4
+import androidx.annotation.NonNull;
5
+
6
+import com.szls.lszlgl.BuildConfig;
7
+
8
+import io.flutter.embedding.engine.plugins.FlutterPlugin;
9
+import io.flutter.plugin.common.MethodCall;
10
+import io.flutter.plugin.common.MethodChannel;
11
+
12
+public class FlavorPlugin implements FlutterPlugin, MethodChannel.MethodCallHandler {
13
+
14
+    private MethodChannel mChannel;
15
+
16
+    public FlavorPlugin() {
17
+    }
18
+
19
+    @Override
20
+    public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
21
+        mChannel = new MethodChannel(binding.getBinaryMessenger(), "plugin_flavor");
22
+        mChannel.setMethodCallHandler(this);
23
+    }
24
+
25
+    @Override
26
+    public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
27
+        mChannel.setMethodCallHandler(null);
28
+        mChannel = null;
29
+    }
30
+
31
+    @Override
32
+    public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
33
+        switch (call.method) {
34
+            case "getPlatformVersion":
35
+                result.success("Android " + android.os.Build.VERSION.RELEASE);
36
+                break;
37
+            case "flavor":
38
+                getFlavor(result);
39
+                break;
40
+            default:
41
+                result.notImplemented();
42
+                break;
43
+        }
44
+    }
45
+
46
+    /**
47
+     * 获取Flavor
48
+     */
49
+    private void getFlavor(MethodChannel.Result result) {
50
+        result.success(BuildConfig.FLAVOR);
51
+    }
52
+
53
+}

+ 43 - 0
lib/config/app_config.dart

@@ -0,0 +1,43 @@
1
+import 'package:lszlgl/plugin/flavor_plugin.dart';
2
+import 'package:package_info_plus/package_info_plus.dart';
3
+
4
+import '../network/my_api.dart';
5
+
6
+enum AppEnvironment {
7
+  /// 开发环境
8
+  develop,
9
+
10
+  /// 生产环境
11
+  product,
12
+}
13
+
14
+class AppConfig {
15
+  AppConfig._();
16
+
17
+  /// 环境信息
18
+  static late AppEnvironment env;
19
+
20
+  /// 包信息
21
+  static late PackageInfo packageInfo;
22
+
23
+  static Future<void> init() async {
24
+    packageInfo = await PackageInfo.fromPlatform();
25
+
26
+    env = await _initEnv();
27
+
28
+    /// 初始化网络请求
29
+    MyApi.init(env);
30
+  }
31
+
32
+  /// 初始化环境
33
+  static Future<AppEnvironment> _initEnv() async {
34
+    // 获取flavor
35
+    var name = await FlavorPlugin.instance.getFlavor();
36
+    // 转为环境数据
37
+    return switch (name) {
38
+      'develop' => AppEnvironment.develop,
39
+      'product' => AppEnvironment.product,
40
+      _ => AppEnvironment.product,
41
+    };
42
+  }
43
+}

+ 6 - 7
lib/main.dart

@@ -1,8 +1,4 @@
1 1
 import 'dart:async';
2
-import 'dart:io';
3
-import 'package:drift/drift.dart' as drift;
4
-import 'package:drift/native.dart';
5
-import 'package:flutter/foundation.dart';
6 2
 import 'package:flutter/material.dart';
7 3
 import 'package:flutter/services.dart';
8 4
 import 'package:flutter_localizations/flutter_localizations.dart';
@@ -12,6 +8,8 @@ import 'package:lszlgl/config/colors.dart';
12 8
 import 'package:lszlgl/drfit/database.dart';
13 9
 import 'package:lszlgl/router/my_navigator.dart';
14 10
 
11
+import 'config/app_config.dart';
12
+
15 13
 late Logger logger;
16 14
 late MyDatabase database;
17 15
 
@@ -24,8 +22,9 @@ void main() async {
24 22
       DeviceOrientation.portraitUp,
25 23
       DeviceOrientation.portraitDown,
26 24
     ]);
27
-
28
-    runApp(const MyApp());
25
+    AppConfig.init().then((value) {
26
+      runApp(const MyApp());
27
+    });
29 28
     database = MyDatabase();
30 29
   });
31 30
 }
@@ -66,7 +65,7 @@ class MyApp extends StatelessWidget {
66 65
   Widget build(BuildContext context) {
67 66
     var theme = Theme.of(context);
68 67
     return MaterialApp(
69
-      title: '粮食质量管理${kReleaseMode ? '' : '-测试'}',
68
+      title: AppConfig.packageInfo.appName,
70 69
       theme: ThemeData(
71 70
         colorScheme: ColorScheme.fromSeed(
72 71
           seedColor: Colors.blue,

+ 17 - 8
lib/network/my_api.dart

@@ -1,21 +1,30 @@
1 1
 import 'package:dio/dio.dart';
2
-import 'package:flutter/foundation.dart';
2
+import 'package:lszlgl/config/app_config.dart';
3 3
 
4 4
 import 'api.dart';
5 5
 
6 6
 class MyApi {
7 7
   MyApi._();
8 8
 
9
+  /// 生产url
9 10
   static String productUrl = 'http://121.36.17.6:49099';
11
+
12
+  /// 测试url
10 13
   static String testUrl = 'http://121.36.17.6:19090';
11 14
 
12
-  static Api get({Dio? dio, String? baseUrl}) {
15
+  static late String globalUrl;
13 16
 
14
-    if (kReleaseMode) {
15
-      baseUrl ??= productUrl;
16
-    } else {
17
-      baseUrl ??= testUrl;
18
-    }
19
-    return Api(dio: dio, baseUrl: baseUrl);
17
+  static void init(AppEnvironment env) {
18
+    globalUrl = switch (env) {
19
+      AppEnvironment.develop => testUrl,
20
+      AppEnvironment.product => productUrl,
21
+    };
22
+  }
23
+
24
+  static Api get({Dio? dio, String? baseUrl}) {
25
+    return Api(
26
+      dio: dio,
27
+      baseUrl: baseUrl ?? globalUrl,
28
+    );
20 29
   }
21 30
 }

+ 2 - 9
lib/page/user_center/setting_page.dart

@@ -1,9 +1,9 @@
1 1
 import 'package:flutter/material.dart';
2 2
 import 'package:lszlgl/base/base_state.dart';
3
+import 'package:lszlgl/config/app_config.dart';
3 4
 import 'package:lszlgl/service/upgrade_service.dart';
4 5
 import 'package:lszlgl/widget/button.dart';
5 6
 import 'package:lszlgl/widget/card_item.dart';
6
-import 'package:package_info_plus/package_info_plus.dart';
7 7
 
8 8
 /// 设置
9 9
 class SettingPage extends StatefulWidget {
@@ -16,7 +16,6 @@ class SettingPage extends StatefulWidget {
16 16
 class _SettingPageState extends BaseState<SettingPage> {
17 17
   bool sound = true;
18 18
   bool shake = true;
19
-  String version = '';
20 19
 
21 20
   void onSave() {
22 21
     MyNavigator.showToast('保存成功');
@@ -30,12 +29,6 @@ class _SettingPageState extends BaseState<SettingPage> {
30 29
   @override
31 30
   void initState() {
32 31
     super.initState();
33
-
34
-    PackageInfo.fromPlatform().then((packageInfo) {
35
-      setState(() {
36
-        version = packageInfo.version;
37
-      });
38
-    });
39 32
   }
40 33
 
41 34
   @override
@@ -79,7 +72,7 @@ class _SettingPageState extends BaseState<SettingPage> {
79 72
             rightChild: buildSwitch(shake, (value) => setState(() => shake = value)),
80 73
             bottomLine: true,
81 74
           ),
82
-          CardItemWidget('版本信息', rightText: 'V$version', onTap: onVersionTap),
75
+          CardItemWidget('版本信息', rightText: 'V${AppConfig.packageInfo.version}', onTap: onVersionTap),
83 76
         ],
84 77
       ),
85 78
     );

+ 21 - 0
lib/plugin/flavor_plugin.dart

@@ -0,0 +1,21 @@
1
+import 'dart:async';
2
+
3
+import 'package:flutter/services.dart';
4
+
5
+class FlavorPlugin {
6
+  FlavorPlugin._();
7
+
8
+  static FlavorPlugin? _instance;
9
+
10
+  static FlavorPlugin get instance => _instance ??= FlavorPlugin._();
11
+
12
+  final MethodChannel _channel = const MethodChannel('plugin_flavor');
13
+
14
+  Future<String?> get platformVersion async {
15
+    final String? version = await _channel.invokeMethod('getPlatformVersion');
16
+    return version;
17
+  }
18
+
19
+  /// 获取Flavor
20
+  Future<String?> getFlavor() => _channel.invokeMethod('flavor');
21
+}

+ 2 - 2
lib/service/upgrade_service.dart

@@ -2,7 +2,7 @@ import 'dart:io';
2 2
 
3 3
 import 'package:dio/dio.dart';
4 4
 import 'package:install_plugin/install_plugin.dart';
5
-import 'package:package_info_plus/package_info_plus.dart';
5
+import 'package:lszlgl/config/app_config.dart';
6 6
 import 'package:path_provider/path_provider.dart';
7 7
 import 'package:permission_handler/permission_handler.dart';
8 8
 
@@ -70,7 +70,7 @@ class UpgradeService {
70 70
         // 获取线上版本 lszlgl_release_0.0.2_2.apk
71 71
         List<String> nameSplit = UpgradeService.getName(path).split('_');
72 72
         int onlineCode = int.parse(nameSplit[nameSplit.length - 1].split('.').first);
73
-        int localCode = int.parse((await PackageInfo.fromPlatform()).buildNumber);
73
+        int localCode = int.parse(AppConfig.packageInfo.buildNumber);
74 74
         logger.d('versionUpgrade:localCode:$localCode onlineCode:$onlineCode');
75 75
         if (localCode >= onlineCode) {
76 76
           if (showLoading) MyNavigator.showToast('已是最新版本');