├── .gitignore ├── .gitmodules ├── Example ├── my_flutter │ ├── README.md │ ├── build_ios.sh │ ├── get_version.sh │ ├── iOSApp │ │ └── debug │ │ │ └── App.framework │ │ │ └── App │ ├── lib │ │ └── main.dart │ ├── maven.sh │ ├── my_flutter.iml │ ├── my_flutter_android.iml │ ├── pubspec.lock │ ├── pubspec.yaml │ └── test │ │ └── widget_test.dart └── my_native │ ├── Podfile │ ├── Podfile.lock │ ├── flutterhelper.rb │ ├── maven.sh │ ├── my_native.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ ├── my_native.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── my_native │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── LICENSE ├── README.md └── Script ├── Maven ├── Flutter │ ├── build_ios.sh │ ├── get_version.sh │ ├── iOSApp │ │ └── debug │ │ │ └── App.framework │ │ │ └── App │ └── maven.sh └── Native │ ├── Podfile │ ├── flutterhelper.rb │ └── maven.sh └── git ├── Flutter ├── build_ios.sh ├── get_version.sh └── iOSApp │ └── debug │ └── App.framework │ └── App └── Native ├── Podfile └── flutterhelper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | Pods/ 4 | .build_ios/ 5 | 6 | .packages 7 | .pub/ 8 | 9 | .idea/ 10 | .vagrant/ 11 | .sconsign.dblite 12 | .svn/ 13 | 14 | *.swp 15 | profile 16 | 17 | DerivedData/ 18 | 19 | .generated/ 20 | 21 | *.pbxuser 22 | *.mode1v3 23 | *.mode2v3 24 | *.perspectivev3 25 | 26 | !default.pbxuser 27 | !default.mode1v3 28 | !default.mode2v3 29 | !default.perspectivev3 30 | 31 | xcuserdata 32 | 33 | *.moved-aside 34 | 35 | *.pyc 36 | *sync/ 37 | Icon? 38 | .tags* 39 | 40 | build/ 41 | .android/ 42 | .ios/ 43 | .flutter-plugins 44 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Example/my_flutter/.flutter"] 2 | path = Example/my_flutter/.flutter 3 | url = https://github.com/flutter/flutter.git 4 | branch = stable 5 | -------------------------------------------------------------------------------- /Example/my_flutter/README.md: -------------------------------------------------------------------------------- 1 | # my_flutter 2 | 3 | A new flutter module project. 4 | 5 | ## Getting Started 6 | 7 | For help getting started with Flutter, view our online 8 | [documentation](https://flutter.io/). 9 | -------------------------------------------------------------------------------- /Example/my_flutter/build_ios.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | BUILD_MODE="debug" 4 | ARCHS_ARM="arm64,armv7" 5 | FLUTTER_ROOT=".flutter" 6 | PRODUCT_DIR="product" 7 | PRODUCT_ZIP="product.zip" 8 | FLUTTER_WRAPPER="./flutterw" 9 | 10 | BUILD_PATH=".build_ios/${BUILD_MODE}" 11 | PRODUCT_PATH="${BUILD_PATH}/${PRODUCT_DIR}" 12 | PRODUCT_APP_PATH="${PRODUCT_PATH}/Flutter" 13 | # git repository path 14 | PRODUCT_GIT_DIR="/xx/xx/x" 15 | 16 | usage() { 17 | echo 18 | echo "build_ios.sh [-h | [-m ] [-s]]" 19 | echo "" 20 | echo "-h - Help." 21 | echo "-m - Build model, valid values are 'debug', 'profile', or 'release'. " 22 | echo " Default values: 'debug'." 23 | echo "" 24 | echo "Build product in 'build_ios//${PRODUCT_DIR}' directory." 25 | echo 26 | } 27 | 28 | EchoError() { 29 | echo "$@" 1>&2 30 | } 31 | 32 | flutter_get_packages() { 33 | echo "=================================" 34 | echo "Start get flutter app plugin" 35 | 36 | if [ -e $FLUTTER_WRAPPER ]; then 37 | echo 'flutterw installed' >/dev/null 38 | else 39 | bash -c "$(curl -fsSL https://raw.githubusercontent.com/passsy/flutter_wrapper/master/install.sh)" 40 | if [[ $? -ne 0 ]]; then 41 | EchoError "Failed to installed flutter_wrapper." 42 | exit -1 43 | fi 44 | fi 45 | 46 | ${FLUTTER_WRAPPER} packages get --verbose 47 | if [[ $? -ne 0 ]]; then 48 | EchoError "Failed to install flutter plugins." 49 | exit -1 50 | fi 51 | 52 | echo "Finish get flutter app plugin" 53 | } 54 | 55 | build_flutter_app() { 56 | echo "=================================" 57 | echo "Start Build flutter app" 58 | echo "Build mode: ${BUILD_MODE}" 59 | 60 | mkdir -p -- "${PRODUCT_APP_PATH}" 61 | 62 | local target_path="lib/main.dart" 63 | 64 | local artifact_variant="unknown" 65 | case "$BUILD_MODE" in 66 | release*) 67 | artifact_variant="ios-release" 68 | ;; 69 | profile*) 70 | artifact_variant="ios-profile" 71 | ;; 72 | debug*) 73 | artifact_variant="ios" 74 | ;; 75 | *) 76 | EchoError "========================================================================" 77 | EchoError "ERROR: Unknown FLUTTER_BUILD_MODE: ${BUILD_MODE}." 78 | EchoError "Valid values are 'debug', 'profile', or 'release'." 79 | EchoError "This is controlled by the -m environment varaible." 80 | EchoError "========================================================================" 81 | exit -1 82 | ;; 83 | esac 84 | 85 | if [[ "${BUILD_MODE}" != "debug" ]]; then 86 | if [[ $ARCHS_ARM =~ .*i386.* || $ARCHS_ARM =~ .*x86_64.* ]]; then 87 | EchoError "========================================================================" 88 | EchoError "ERROR: Flutter does not support running in profile or release mode on" 89 | EchoError "the Simulator (this build was: '$BUILD_MODE')." 90 | EchoError "mode by setting '-m debug'" 91 | EchoError "========================================================================" 92 | exit -1 93 | fi 94 | 95 | echo "Build archs: ${ARCHS_ARM}" 96 | 97 | ${FLUTTER_WRAPPER} clean 98 | 99 | ${FLUTTER_WRAPPER} build ios --${BUILD_MODE} 100 | if [[ $? -ne 0 ]]; then 101 | EchoError "Failed to build flutter app" 102 | exit -1 103 | fi 104 | 105 | cp -r -- ".ios/Flutter/App.framework" "${BUILD_PATH}/App.framework" 106 | else 107 | echo "Build archs: x86_64 ${ARCHS_ARM}" 108 | local app_framework_debug="iOSApp/Debug/App.framework" 109 | cp -r -- "${app_framework_debug}" "${BUILD_PATH}" 110 | 111 | app_plist_path=".ios/Flutter/AppFrameworkInfo.plist" 112 | cp -- "${app_plist_path}" "${BUILD_PATH}/App.framework/Info.plist" 113 | 114 | local precompilation_flag="" 115 | if [[ "$BUILD_MODE" != "debug" ]]; then 116 | precompilation_flag="--precompiled" 117 | fi 118 | 119 | # build bundle 120 | ${FLUTTER_WRAPPER} --suppress-analytics \ 121 | --verbose \ 122 | build bundle \ 123 | --target-platform=ios \ 124 | --target="${target_path}" \ 125 | --${BUILD_MODE} \ 126 | --depfile="${BUILD_PATH}/snapshot_blob.bin.d" \ 127 | --asset-dir="${BUILD_PATH}/flutter_assets" \ 128 | ${precompilation_flag} 129 | 130 | if [[ $? -ne 0 ]]; then 131 | EchoError "Failed to build flutter assets" 132 | exit -1 133 | fi 134 | 135 | cp -rf -- "${BUILD_PATH}/flutter_assets" "${BUILD_PATH}/App.framework" 136 | fi 137 | 138 | # copy flutter sdk 139 | local framework_path="${FLUTTER_ROOT}/bin/cache/artifacts/engine/${artifact_variant}" 140 | local flutter_framework="${framework_path}/Flutter.framework" 141 | local flutter_podspec="${framework_path}/Flutter.podspec" 142 | 143 | cp -r -- "${BUILD_PATH}/App.framework" "${PRODUCT_APP_PATH}" 144 | cp -r -- "${flutter_framework}" "${PRODUCT_APP_PATH}" 145 | cp -r -- "${flutter_podspec}" "${PRODUCT_APP_PATH}" 146 | 147 | # setting podspec 148 | # replace: 149 | # 'Flutter.framework' 150 | # to: 151 | # 'Flutter.framework', 'App.framework' 152 | sed -i '' -e $'s/\'Flutter.framework\'/\'Flutter.framework\', \'App.framework\'/g' ${PRODUCT_APP_PATH}/Flutter.podspec 153 | 154 | echo "Finish build flutter app" 155 | } 156 | 157 | flutter_copy_packages() { 158 | echo "=================================" 159 | echo "Start copy flutter app plugin" 160 | 161 | local flutter_plugin_registrant="FlutterPluginRegistrant" 162 | local flutter_plugin_registrant_path=".ios/Flutter/${flutter_plugin_registrant}" 163 | echo "copy 'flutter_plugin_registrant' from '${flutter_plugin_registrant_path}' to '${PRODUCT_PATH}/${flutter_plugin_registrant}'" 164 | cp -rf -- "${flutter_plugin_registrant_path}" "${PRODUCT_PATH}/${flutter_plugin_registrant}" 165 | 166 | local flutter_plugin=".flutter-plugins" 167 | if [ -e $flutter_plugin ]; then 168 | OLD_IFS="$IFS" 169 | IFS="=" 170 | cat ${flutter_plugin} | while read plugin; do 171 | local plugin_info=($plugin) 172 | local plugin_name=${plugin_info[0]} 173 | local plugin_path=${plugin_info[1]} 174 | 175 | if [ -e ${plugin_path} ]; then 176 | local plugin_path_ios="${plugin_path}ios" 177 | if [ -e ${plugin_path_ios} ]; then 178 | if [ -s ${plugin_path_ios} ]; then 179 | echo "copy plugin 'plugin_name' from '${plugin_path_ios}' to '${PRODUCT_PATH}/${plugin_name}'" 180 | cp -rf ${plugin_path_ios} "${PRODUCT_PATH}/${plugin_name}" 181 | fi 182 | fi 183 | fi 184 | done 185 | IFS="$OLD_IFS" 186 | fi 187 | 188 | echo "Finish copy flutter app plugin" 189 | } 190 | 191 | upload_product() { 192 | echo "=================================" 193 | echo "upload product" 194 | 195 | echo "${PRODUCT_APP_PATH}" 196 | echo "${PRODUCT_GIT_DIR}" 197 | 198 | cp -r -f -- "${PRODUCT_APP_PATH}" "${PRODUCT_GIT_DIR}" 199 | 200 | local app_version=$(./get_version.sh) 201 | 202 | pushd ${PRODUCT_GIT_DIR} 203 | 204 | git add . 205 | git commit -m "Flutter product ${app_version}" 206 | git push 207 | 208 | popd 209 | } 210 | 211 | start_build() { 212 | 213 | rm -rf ${BUILD_PATH} 214 | 215 | flutter_get_packages 216 | 217 | build_flutter_app 218 | 219 | flutter_copy_packages 220 | 221 | if [[ "${BUILD_MODE}" == "release" ]]; then 222 | upload_product 223 | fi 224 | 225 | echo "" 226 | echo "done!" 227 | } 228 | 229 | show_help=0 230 | while getopts "m:sh" arg; do 231 | case $arg in 232 | m) 233 | BUILD_MODE="$OPTARG" 234 | ;; 235 | h) 236 | show_help=1 237 | ;; 238 | ?) 239 | show_help=1 240 | ;; 241 | esac 242 | done 243 | 244 | if [ $show_help == 1 ]; then 245 | usage 246 | exit 0 247 | fi 248 | 249 | BUILD_PATH=".build_ios/${BUILD_MODE}" 250 | PRODUCT_PATH="${BUILD_PATH}/${PRODUCT_DIR}" 251 | PRODUCT_APP_PATH="${PRODUCT_PATH}/Flutter" 252 | 253 | start_build 254 | 255 | exit 0 256 | -------------------------------------------------------------------------------- /Example/my_flutter/get_version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | FILE_PATH="" 4 | FILE_PATH_DEF="./pubspec.yaml" 5 | # 过滤 version name 的正则表达式 6 | VERSION_NAME_REGEX="^version: " 7 | # 过滤 version code 的正则表达式 8 | VERSION_CODE_REGEX="^version_code: " 9 | 10 | throw () { 11 | echo "error: $*" >&2 12 | exit 1 13 | } 14 | 15 | usage() { 16 | echo 17 | echo "Usage: get_version.sh [-h] [--name] [--code] []" 18 | echo " [e.g.]: /get_version.sh // Get version name from def file ${FILE_PATH_DEF}." 19 | echo " [e.g.]: /get_version.sh --name example.txt // Get version name from the specified file." 20 | echo " [e.g.]: /get_version.sh --code example.txt // Get version code from the specified file." 21 | echo 22 | echo "--name - [Default] Get version name from the specified file, the def file is ${FILE_PATH_DEF}." 23 | echo "--code - Get version code from the specified file, the def file is ${FILE_PATH_DEF}." 24 | echo "-h - This help text." 25 | echo 26 | } 27 | 28 | parse_options() { 29 | set -- "$@" 30 | local ARGN=$# 31 | while [ "$ARGN" -ne 0 ] 32 | do 33 | case $1 in 34 | -h) usage 35 | exit 0 36 | ;; 37 | --name) FILE_PATH=$2 38 | get_version_name 39 | ;; 40 | --code) FILE_PATH=$2 41 | get_version_code 42 | ;; 43 | ?*) echo "ERROR: Unknown option." 44 | usage 45 | exit 0 46 | ;; 47 | esac 48 | shift 1 49 | ARGN=$((ARGN-1)) 50 | done 51 | } 52 | 53 | get_version_name() { 54 | get_file 55 | #echo "get version name from ${FILE_PATH} ..." 56 | version_name=`egrep ${VERSION_NAME_REGEX} ${FILE_PATH}` 57 | # 取`:`右边 58 | version_name=`echo ${version_name} | sed 's/^.*://g'` 59 | # 删除`;` 60 | version_name=`echo ${version_name} | sed 's/;.*$//g'` 61 | # 删除`"` 62 | version_name=`echo ${version_name} | sed 's/\"//g'` 63 | # 删除`'` 64 | version_name=`echo ${version_name} | sed "s/\'//g"` 65 | #echo "version name: 【${version_name}】" 66 | echo ${version_name} 67 | finish 68 | } 69 | 70 | get_version_code() { 71 | get_file 72 | #echo "get version code from ${FILE_PATH} ..." 73 | version_code=`egrep ${VERSION_CODE_REGEX} ${FILE_PATH}` 74 | # 取`:`右边 75 | version_code=`echo ${version_code} | sed 's/^.*://g'` 76 | # 删除`;` 77 | version_code=`echo ${version_code} | sed 's/;.*$//g'` 78 | #echo "version code: 【${version_code}】" 79 | echo ${version_code} 80 | finish 81 | } 82 | 83 | get_file() { 84 | if [ "$FILE_PATH"x = ""x ]; then 85 | FILE_PATH=${FILE_PATH_DEF} 86 | fi 87 | } 88 | 89 | finish() { 90 | exit 0 91 | } 92 | 93 | default_action() { 94 | get_version_name 95 | } 96 | 97 | if ([ "$0" = "$BASH_SOURCE" ] || ! [ -n "$BASH_SOURCE" ]); 98 | then 99 | parse_options "$@" 100 | default_action 101 | fi 102 | -------------------------------------------------------------------------------- /Example/my_flutter/iOSApp/debug/App.framework/App: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CaffreySun/iOS_Flutter_Hybrid_Project/768167a3c3ae38191e28d20d66b83cd85ea52197/Example/my_flutter/iOSApp/debug/App.framework/App -------------------------------------------------------------------------------- /Example/my_flutter/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void main() => runApp(MyApp()); 4 | 5 | class MyApp extends StatelessWidget { 6 | // This widget is the root of your application. 7 | @override 8 | Widget build(BuildContext context) { 9 | return MaterialApp( 10 | title: 'Flutter Demo', 11 | theme: ThemeData( 12 | // This is the theme of your application. 13 | // 14 | // Try running your application with "flutter run". You'll see the 15 | // application has a blue toolbar. Then, without quitting the app, try 16 | // changing the primarySwatch below to Colors.green and then invoke 17 | // "hot reload" (press "r" in the console where you ran "flutter run", 18 | // or press Run > Flutter Hot Reload in a Flutter IDE). Notice that the 19 | // counter didn't reset back to zero; the application is not restarted. 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: MyHomePage(title: 'Flutter Demo Home Page'), 23 | ); 24 | } 25 | } 26 | 27 | class MyHomePage extends StatefulWidget { 28 | MyHomePage({Key key, this.title}) : super(key: key); 29 | 30 | // This widget is the home page of your application. It is stateful, meaning 31 | // that it has a State object (defined below) that contains fields that affect 32 | // how it looks. 33 | 34 | // This class is the configuration for the state. It holds the values (in this 35 | // case the title) provided by the parent (in this case the App widget) and 36 | // used by the build method of the State. Fields in a Widget subclass are 37 | // always marked "final". 38 | 39 | final String title; 40 | 41 | @override 42 | _MyHomePageState createState() => _MyHomePageState(); 43 | } 44 | 45 | class _MyHomePageState extends State { 46 | int _counter = 0; 47 | 48 | void _incrementCounter() { 49 | setState(() { 50 | // This call to setState tells the Flutter framework that something has 51 | // changed in this State, which causes it to rerun the build method below 52 | // so that the display can reflect the updated values. If we changed 53 | // _counter without calling setState(), then the build method would not be 54 | // called again, and so nothing would appear to happen. 55 | _counter++; 56 | }); 57 | } 58 | 59 | @override 60 | Widget build(BuildContext context) { 61 | // This method is rerun every time setState is called, for instance as done 62 | // by the _incrementCounter method above. 63 | // 64 | // The Flutter framework has been optimized to make rerunning build methods 65 | // fast, so that you can just rebuild anything that needs updating rather 66 | // than having to individually change instances of widgets. 67 | return Scaffold( 68 | appBar: AppBar( 69 | // Here we take the value from the MyHomePage object that was created by 70 | // the App.build method, and use it to set our appbar title. 71 | title: Text(widget.title), 72 | ), 73 | body: Center( 74 | // Center is a layout widget. It takes a single child and positions it 75 | // in the middle of the parent. 76 | child: Column( 77 | // Column is also layout widget. It takes a list of children and 78 | // arranges them vertically. By default, it sizes itself to fit its 79 | // children horizontally, and tries to be as tall as its parent. 80 | // 81 | // Invoke "debug painting" (press "p" in the console, choose the 82 | // "Toggle Debug Paint" action from the Flutter Inspector in Android 83 | // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) 84 | // to see the wireframe for each widget. 85 | // 86 | // Column has various properties to control how it sizes itself and 87 | // how it positions its children. Here we use mainAxisAlignment to 88 | // center the children vertically; the main axis here is the vertical 89 | // axis because Columns are vertical (the cross axis would be 90 | // horizontal). 91 | mainAxisAlignment: MainAxisAlignment.center, 92 | children: [ 93 | Text( 94 | 'You have pushed the button this many times:', 95 | ), 96 | Text( 97 | '$_counter', 98 | style: Theme.of(context).textTheme.display1, 99 | ), 100 | ], 101 | ), 102 | ), 103 | floatingActionButton: FloatingActionButton( 104 | onPressed: _incrementCounter, 105 | tooltip: 'Increment', 106 | child: Icon(Icons.add), 107 | ), // This trailing comma makes auto-formatting nicer for build methods. 108 | ); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Example/my_flutter/maven.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | FILE_NAME="flutter.zip" 4 | FILE_PATH="xxx" 5 | VERSION="" 6 | MAVEN_PATH="http://xxx" 7 | MAVEN_USER="xxx:xxx" 8 | LOCAL_FILE_PATH="" 9 | 10 | throw () { 11 | echo "error: $*" >&2 12 | exit 1 13 | } 14 | 15 | usage() { 16 | echo 17 | echo "Usage: maven.sh [-h] [upload] [download]" 18 | echo 19 | echo "upload - Upload to maven. [e.g.]: ./maven.sh upload 1.0.0 localFile.zip" 20 | echo "download - Download from maven. [e.g.]: ./maven.sh download 1.0.1" 21 | echo "-h - This help text." 22 | echo 23 | } 24 | 25 | parse_options() { 26 | set -- "$@" 27 | local ARGN=$# 28 | while [ "$ARGN" -ne 0 ] 29 | do 30 | case $1 in 31 | -h) usage 32 | exit 0 33 | ;; 34 | upload) VERSION=$2 35 | LOCAL_FILE_PATH=$3 36 | upload 37 | ;; 38 | download) VERSION=$2 39 | download 40 | ;; 41 | ?*) echo "ERROR: Unknown option." 42 | usage 43 | exit 0 44 | ;; 45 | esac 46 | shift 1 47 | ARGN=$((ARGN-1)) 48 | done 49 | } 50 | 51 | upload() { 52 | if [ "$VERSION"x = ""x ]; then 53 | throw "version null" 54 | fi 55 | if [ "$LOCAL_FILE_PATH"x = ""x ]; then 56 | throw "file null" 57 | fi 58 | if ! [ -f $LOCAL_FILE_PATH ]; then 59 | throw "file $LOCAL_FILE_PATH not exist" 60 | fi 61 | echo 62 | echo "Uploading..." 63 | echo "$LOCAL_FILE_PATH -> $MAVEN_PATH/$FILE_PATH/$VERSION/$FILE_NAME" 64 | curl -u$MAVEN_USER -T $LOCAL_FILE_PATH "$MAVEN_PATH/$FILE_PATH/$VERSION/$FILE_NAME" 65 | echo 66 | echo "Done!" 67 | echo 68 | exit 0 69 | } 70 | 71 | download() { 72 | if [ "$VERSION"x = ""x ]; then 73 | throw "version null" 74 | fi 75 | echo 76 | echo "Downloading..." 77 | echo "$MAVEN_PATH/$FILE_PATH/$VERSION/$FILE_NAME" 78 | curl -u$MAVEN_USER -O "$MAVEN_PATH/$FILE_PATH/$VERSION/$FILE_NAME" 79 | echo "Done!" 80 | echo 81 | exit 0 82 | } 83 | 84 | if ([ "$0" = "$BASH_SOURCE" ] || ! [ -n "$BASH_SOURCE" ]); 85 | then 86 | parse_options "$@" 87 | usage 88 | exit 0 89 | fi 90 | -------------------------------------------------------------------------------- /Example/my_flutter/my_flutter.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Example/my_flutter/my_flutter_android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Example/my_flutter/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://www.dartlang.org/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.flutter-io.cn" 9 | source: hosted 10 | version: "2.0.8" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.flutter-io.cn" 16 | source: hosted 17 | version: "1.0.4" 18 | charcode: 19 | dependency: transitive 20 | description: 21 | name: charcode 22 | url: "https://pub.flutter-io.cn" 23 | source: hosted 24 | version: "1.1.2" 25 | collection: 26 | dependency: transitive 27 | description: 28 | name: collection 29 | url: "https://pub.flutter-io.cn" 30 | source: hosted 31 | version: "1.14.11" 32 | cupertino_icons: 33 | dependency: "direct main" 34 | description: 35 | name: cupertino_icons 36 | url: "https://pub.flutter-io.cn" 37 | source: hosted 38 | version: "0.1.2" 39 | flutter: 40 | dependency: "direct main" 41 | description: flutter 42 | source: sdk 43 | version: "0.0.0" 44 | flutter_test: 45 | dependency: "direct dev" 46 | description: flutter 47 | source: sdk 48 | version: "0.0.0" 49 | matcher: 50 | dependency: transitive 51 | description: 52 | name: matcher 53 | url: "https://pub.flutter-io.cn" 54 | source: hosted 55 | version: "0.12.3+1" 56 | meta: 57 | dependency: transitive 58 | description: 59 | name: meta 60 | url: "https://pub.flutter-io.cn" 61 | source: hosted 62 | version: "1.1.6" 63 | path: 64 | dependency: transitive 65 | description: 66 | name: path 67 | url: "https://pub.flutter-io.cn" 68 | source: hosted 69 | version: "1.6.2" 70 | quiver: 71 | dependency: transitive 72 | description: 73 | name: quiver 74 | url: "https://pub.flutter-io.cn" 75 | source: hosted 76 | version: "2.0.1" 77 | sky_engine: 78 | dependency: transitive 79 | description: flutter 80 | source: sdk 81 | version: "0.0.99" 82 | source_span: 83 | dependency: transitive 84 | description: 85 | name: source_span 86 | url: "https://pub.flutter-io.cn" 87 | source: hosted 88 | version: "1.4.1" 89 | stack_trace: 90 | dependency: transitive 91 | description: 92 | name: stack_trace 93 | url: "https://pub.flutter-io.cn" 94 | source: hosted 95 | version: "1.9.3" 96 | stream_channel: 97 | dependency: transitive 98 | description: 99 | name: stream_channel 100 | url: "https://pub.flutter-io.cn" 101 | source: hosted 102 | version: "1.6.8" 103 | string_scanner: 104 | dependency: transitive 105 | description: 106 | name: string_scanner 107 | url: "https://pub.flutter-io.cn" 108 | source: hosted 109 | version: "1.0.4" 110 | term_glyph: 111 | dependency: transitive 112 | description: 113 | name: term_glyph 114 | url: "https://pub.flutter-io.cn" 115 | source: hosted 116 | version: "1.0.1" 117 | test_api: 118 | dependency: transitive 119 | description: 120 | name: test_api 121 | url: "https://pub.flutter-io.cn" 122 | source: hosted 123 | version: "0.2.1" 124 | typed_data: 125 | dependency: transitive 126 | description: 127 | name: typed_data 128 | url: "https://pub.flutter-io.cn" 129 | source: hosted 130 | version: "1.1.6" 131 | vector_math: 132 | dependency: transitive 133 | description: 134 | name: vector_math 135 | url: "https://pub.flutter-io.cn" 136 | source: hosted 137 | version: "2.0.8" 138 | sdks: 139 | dart: ">=2.0.0 <3.0.0" 140 | -------------------------------------------------------------------------------- /Example/my_flutter/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: my_flutter 2 | description: A new flutter module project. 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # Read more about versioning at semver.org. 10 | # 11 | # This version is used _only_ for the Runner app, which is used if you just do 12 | # a `flutter run` or a `flutter make-host-app-editable`. It has no impact 13 | # on any other native host app that you embed your Flutter project into. 14 | version: 1.0.0+1 15 | 16 | environment: 17 | sdk: ">=2.0.0-dev.68.0 <3.0.0" 18 | 19 | dependencies: 20 | flutter: 21 | sdk: flutter 22 | 23 | # The following adds the Cupertino Icons font to your application. 24 | # Use with the CupertinoIcons class for iOS style icons. 25 | cupertino_icons: ^0.1.2 26 | 27 | dev_dependencies: 28 | flutter_test: 29 | sdk: flutter 30 | 31 | # For information on the generic Dart part of this file, see the 32 | # following page: https://www.dartlang.org/tools/pub/pubspec 33 | 34 | flutter: 35 | # The following line ensures that the Material Icons font is 36 | # included with your application, so that you can use the icons in 37 | # the material Icons class. 38 | uses-material-design: true 39 | 40 | # To add Flutter specific assets to your application, add an assets section, 41 | # like this: 42 | # assets: 43 | # - images/a_dot_burr.jpeg 44 | # - images/a_dot_ham.jpeg 45 | 46 | # An image asset can refer to one or more resolution-specific "variants", see 47 | # https://flutter.io/assets-and-images/#resolution-aware. 48 | 49 | # For details regarding adding assets from package dependencies, see 50 | # https://flutter.io/assets-and-images/#from-packages 51 | 52 | # To add Flutter specific custom fonts to your application, add a fonts 53 | # section here, in this "flutter" section. Each entry in this list should 54 | # have a "family" key with the font family name, and a "fonts" key with a 55 | # list giving the asset and other descriptors for the font. For 56 | # example: 57 | # fonts: 58 | # - family: Schyler 59 | # fonts: 60 | # - asset: fonts/Schyler-Regular.ttf 61 | # - asset: fonts/Schyler-Italic.ttf 62 | # style: italic 63 | # - family: Trajan Pro 64 | # fonts: 65 | # - asset: fonts/TrajanPro.ttf 66 | # - asset: fonts/TrajanPro_Bold.ttf 67 | # weight: 700 68 | # 69 | # For details regarding fonts from package dependencies, 70 | # see https://flutter.io/custom-fonts/#from-packages 71 | 72 | 73 | # This section identifies your Flutter project as a module meant for 74 | # embedding in a native host app. These identifiers should _not_ ordinarily 75 | # be changed after generation - they are used to ensure that the tooling can 76 | # maintain consistency when adding or modifying assets and plugins. 77 | # They also do not have any bearing on your native host application's 78 | # identifiers, which may be completely independent or the same as these. 79 | module: 80 | androidPackage: com.example.myflutter 81 | iosBundleIdentifier: com.example.myFlutter 82 | -------------------------------------------------------------------------------- /Example/my_flutter/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:my_flutter/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /Example/my_native/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'my_native' do 5 | # Uncomment the next line if you're using Swift or would like to use dynamic frameworks 6 | # use_frameworks! 7 | 8 | # Pods for TestMoreFlutter 9 | end 10 | 11 | # 是否进行调试 flutter app, 12 | # 为true时,为使用产物的方式从下面git地址拉取产物 13 | # 为false时,为使用源码的方式从下面git地址拉取源码 14 | FLUTTER_DEBUG_APP = true 15 | 16 | # Flutter App git地址,从git拉取的内容放在当前工程目录下的.flutter/app目录 17 | # 如果指定了FLUTTER_APP_PATH,则此配置失效 18 | FLUTTER_APP_URL = 'gut://xxx.git' 19 | # flutter git 分支,默认为master 20 | # 如果指定了FLUTTER_APP_PATH,则此配置失效 21 | FLUTTER_APP_BRANCH = 'master' 22 | 23 | # flutter本地工程目录,绝对路径或者相对路径, 24 | # FLUTTER_DEBUG_APP == false时才有效,如果 != nil 则git相关的配置无效 25 | FLUTTER_APP_PATH = '../my_flutter' 26 | 27 | eval(File.read(File.join(__dir__, 'flutterhelper.rb')), binding) 28 | -------------------------------------------------------------------------------- /Example/my_native/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODFILE CHECKSUM: 405c7caa08d03acffa45db98cf70b7826c1dc26e 2 | 3 | COCOAPODS: 1.5.3 4 | -------------------------------------------------------------------------------- /Example/my_native/flutterhelper.rb: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # 3 | # 脚本使用方式: 4 | # 你需要在 Podfile 添加以下=begin =end 之间的内容: 5 | =begin 6 | 7 | # 是否进行调试 flutter app, 8 | # 为true时,为使用产物的方式从下面git地址拉取产物 9 | # 为false时,为使用源码的方式从下面git地址拉取源码 10 | FLUTTER_DEBUG_APP=false 11 | 12 | # Flutter App git地址,从git拉取的内容放在当前工程目录下的.flutter/app目录 13 | # 如果指定了FLUTTER_APP_PATH,则此配置失效 14 | FLUTTER_APP_URL="gut://xxx.git" 15 | # flutter git 分支,默认为master 16 | # 如果指定了FLUTTER_APP_PATH,则此配置失效 17 | FLUTTER_APP_BRANCH="master" 18 | 19 | # flutter本地工程目录,绝对路径或者相对路径, 20 | # FLUTTER_DEBUG_APP == false时才有效,如果 != nil 则git相关的配置无效 21 | FLUTTER_APP_PATH=nil 22 | 23 | eval(File.read(File.join(__dir__, 'flutterhelper.rb')), binding) 24 | 25 | =end 26 | # 27 | ############################################################################## 28 | 29 | # 拉取代码方法 30 | def update_flutter_app(path, url, branche) 31 | # 如果flutter项目不存在,则clone 32 | if !File.exist?(path) 33 | `git clone #{url} #{path}` 34 | end 35 | `cd #{path} && git fetch --all -v && \ 36 | git reset --hard origin/master && \ 37 | git pull && \ 38 | git checkout -B #{branche} origin/#{branche}` 39 | end 40 | 41 | # 安装开发环境app 42 | def install_debug_flutter_app 43 | 44 | puts "如果是第一次运行开发环境Flutter项目,此过程可能会较慢" 45 | puts "请耐心等️待☕️️️️️☕️☕️\n" 46 | 47 | # 默认Flutter App 目录 48 | flutter_application_path = __dir__ + "/.flutter/app" 49 | flutter_application_url = "" 50 | flutter_application_branch = 'master' 51 | 52 | if FLUTTER_APP_PATH != nil 53 | File.expand_path(FLUTTER_APP_PATH) 54 | if File.exist?(FLUTTER_APP_PATH) 55 | flutter_application_path = FLUTTER_APP_PATH 56 | else 57 | flutter_application_path = File.expand_path(FLUTTER_APP_PATH) 58 | if !File.exist?(flutter_application_path) 59 | raise "Error: #{FLUTTER_APP_PATH} 地址不存在!" 60 | end 61 | end 62 | 63 | puts "\nFlutter App路径: "+flutter_application_path 64 | else 65 | if FLUTTER_APP_URL != nil 66 | flutter_application_url = FLUTTER_APP_URL 67 | if FLUTTER_APP_BRANCH != nil 68 | flutter_application_branch = FLUTTER_APP_BRANCH 69 | end 70 | else 71 | raise "Error: 请在'Podfile'里增加Flutter App git地址配置,配置格式请查看'flutterhelper.rb'文件" 72 | end 73 | puts "\n拉取 Flutter App 代码" 74 | puts "Flutter App路径: "+flutter_application_path 75 | update_flutter_app(flutter_application_path, flutter_application_url, flutter_application_branch) 76 | end 77 | 78 | puts "\n编译 Flutter App" 79 | `export PUB_HOSTED_URL=https://pub.flutter-io.cn && \ 80 | export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn && \ 81 | cd #{flutter_application_path} && \ 82 | #{flutter_application_path}/build_ios.sh -m debug` 83 | 84 | if $?.to_i == 0 85 | flutter_package_path = "#{flutter_application_path}/.build_ios/debug/product" 86 | # 开始安装 87 | install_release_flutter_app_pod(flutter_package_path) 88 | else 89 | raise "Error: 编译 Flutter App失败" 90 | end 91 | end 92 | 93 | # 将 Flutter app 通过 pod 安装 94 | def install_release_flutter_app_pod(product_path) 95 | if product_path.nil? 96 | raise "Error: 无效的 flutter app 目录" 97 | end 98 | 99 | puts "将 flutter app 通过 pod 导入到 工程" 100 | 101 | Dir.foreach product_path do |sub| 102 | # 忽略隐藏文件 103 | if sub =~ /\.(.*)/ 104 | next 105 | end 106 | 107 | sub_abs_path = File.join(product_path, sub) 108 | pod sub, :path=>sub_abs_path 109 | end 110 | 111 | post_install do |installer| 112 | installer.pods_project.targets.each do |target| 113 | target.build_configurations.each do |config| 114 | config.build_settings['ENABLE_BITCODE'] = 'NO' 115 | end 116 | end 117 | end 118 | end 119 | 120 | # 安装正式环境环境app 121 | def install_release_flutter_app 122 | if FLUTTER_APP_URL.nil? 123 | raise "Error: 请在 Podfile 里设置要安装的 Flutter app 的产物地址 ,例如:FLUTTER_APP_URL='git://xxx'" 124 | end 125 | 126 | flutter_app_url = FLUTTER_APP_URL 127 | 128 | # 存放产物的目录 129 | flutter_release_path = File.expand_path('.flutter_release') 130 | 131 | flutter_app_branch = FLUTTER_APP_BRANCH 132 | 133 | if FLUTTER_APP_BRANCH.nil? 134 | flutter_app_branch = "master" 135 | end 136 | 137 | update_flutter_app(flutter_release_path, flutter_app_url, flutter_app_branch) 138 | 139 | # 开始安装 140 | install_release_flutter_app_pod(flutter_release_path) 141 | end 142 | 143 | if FLUTTER_DEBUG_APP.nil? || FLUTTER_DEBUG_APP == false 144 | # 使用 flutter release 模式 145 | puts "开始安装 release mode flutter app" 146 | install_release_flutter_app() 147 | else 148 | # 存在debug配置,使用 flutter debug 模式 149 | puts "开始安装 debug mode flutter app" 150 | install_debug_flutter_app() 151 | end 152 | -------------------------------------------------------------------------------- /Example/my_native/maven.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | FILE_NAME="flutter.zip" 4 | FILE_PATH="xxx" 5 | VERSION="" 6 | MAVEN_PATH="http://xxx" 7 | MAVEN_USER="xxx:xxx" 8 | LOCAL_FILE_PATH="" 9 | 10 | throw () { 11 | echo "error: $*" >&2 12 | exit 1 13 | } 14 | 15 | usage() { 16 | echo 17 | echo "Usage: maven.sh [-h] [upload] [download]" 18 | echo 19 | echo "upload - Upload to maven. [e.g.]: ./maven.sh upload 1.0.0 localFile.zip" 20 | echo "download - Download from maven. [e.g.]: ./maven.sh download 1.0.1" 21 | echo "-h - This help text." 22 | echo 23 | } 24 | 25 | parse_options() { 26 | set -- "$@" 27 | local ARGN=$# 28 | while [ "$ARGN" -ne 0 ] 29 | do 30 | case $1 in 31 | -h) usage 32 | exit 0 33 | ;; 34 | upload) VERSION=$2 35 | LOCAL_FILE_PATH=$3 36 | upload 37 | ;; 38 | download) VERSION=$2 39 | download 40 | ;; 41 | ?*) echo "ERROR: Unknown option." 42 | usage 43 | exit 0 44 | ;; 45 | esac 46 | shift 1 47 | ARGN=$((ARGN-1)) 48 | done 49 | } 50 | 51 | upload() { 52 | if [ "$VERSION"x = ""x ]; then 53 | throw "version null" 54 | fi 55 | if [ "$LOCAL_FILE_PATH"x = ""x ]; then 56 | throw "file null" 57 | fi 58 | if ! [ -f $LOCAL_FILE_PATH ]; then 59 | throw "file $LOCAL_FILE_PATH not exist" 60 | fi 61 | echo 62 | echo "Uploading..." 63 | echo "$LOCAL_FILE_PATH -> $MAVEN_PATH/$FILE_PATH/$VERSION/$FILE_NAME" 64 | curl -u$MAVEN_USER -T $LOCAL_FILE_PATH "$MAVEN_PATH/$FILE_PATH/$VERSION/$FILE_NAME" 65 | echo 66 | echo "Done!" 67 | echo 68 | exit 0 69 | } 70 | 71 | download() { 72 | if [ "$VERSION"x = ""x ]; then 73 | throw "version null" 74 | fi 75 | echo 76 | echo "Downloading..." 77 | echo "$MAVEN_PATH/$FILE_PATH/$VERSION/$FILE_NAME" 78 | curl -u$MAVEN_USER -O "$MAVEN_PATH/$FILE_PATH/$VERSION/$FILE_NAME" 79 | echo "Done!" 80 | echo 81 | exit 0 82 | } 83 | 84 | if ([ "$0" = "$BASH_SOURCE" ] || ! [ -n "$BASH_SOURCE" ]); 85 | then 86 | parse_options "$@" 87 | usage 88 | exit 0 89 | fi 90 | -------------------------------------------------------------------------------- /Example/my_native/my_native.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 048793DC21EB2D2A0073FFD1 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 048793DB21EB2D2A0073FFD1 /* AppDelegate.m */; }; 11 | 048793DF21EB2D2A0073FFD1 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 048793DE21EB2D2A0073FFD1 /* ViewController.m */; }; 12 | 048793E221EB2D2A0073FFD1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 048793E021EB2D2A0073FFD1 /* Main.storyboard */; }; 13 | 048793E421EB2D2A0073FFD1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 048793E321EB2D2A0073FFD1 /* Assets.xcassets */; }; 14 | 048793E721EB2D2A0073FFD1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 048793E521EB2D2A0073FFD1 /* LaunchScreen.storyboard */; }; 15 | 048793EA21EB2D2A0073FFD1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 048793E921EB2D2A0073FFD1 /* main.m */; }; 16 | 65F7867929EBCC13CD0FC27E /* libPods-my_native.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A7A8A6BF5E10F413F87B8018 /* libPods-my_native.a */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 048793D721EB2D2A0073FFD1 /* my_native.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = my_native.app; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | 048793DA21EB2D2A0073FFD1 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 22 | 048793DB21EB2D2A0073FFD1 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 23 | 048793DD21EB2D2A0073FFD1 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 24 | 048793DE21EB2D2A0073FFD1 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 25 | 048793E121EB2D2A0073FFD1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 26 | 048793E321EB2D2A0073FFD1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 27 | 048793E621EB2D2A0073FFD1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 28 | 048793E821EB2D2A0073FFD1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 29 | 048793E921EB2D2A0073FFD1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 30 | 0E0AC92F4FF81CF71EA2B060 /* Pods-my_native.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-my_native.debug.xcconfig"; path = "Pods/Target Support Files/Pods-my_native/Pods-my_native.debug.xcconfig"; sourceTree = ""; }; 31 | A7A8A6BF5E10F413F87B8018 /* libPods-my_native.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-my_native.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | D2BBDA0B77FF6879643460EF /* Pods-my_native.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-my_native.release.xcconfig"; path = "Pods/Target Support Files/Pods-my_native/Pods-my_native.release.xcconfig"; sourceTree = ""; }; 33 | /* End PBXFileReference section */ 34 | 35 | /* Begin PBXFrameworksBuildPhase section */ 36 | 048793D421EB2D2A0073FFD1 /* Frameworks */ = { 37 | isa = PBXFrameworksBuildPhase; 38 | buildActionMask = 2147483647; 39 | files = ( 40 | 65F7867929EBCC13CD0FC27E /* libPods-my_native.a in Frameworks */, 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXFrameworksBuildPhase section */ 45 | 46 | /* Begin PBXGroup section */ 47 | 048793CE21EB2D290073FFD1 = { 48 | isa = PBXGroup; 49 | children = ( 50 | 048793D921EB2D2A0073FFD1 /* my_native */, 51 | 048793D821EB2D2A0073FFD1 /* Products */, 52 | F04B1007FD7BD0D3F866E7C7 /* Pods */, 53 | 5A4C95FB5C05D97EA6BA495D /* Frameworks */, 54 | ); 55 | sourceTree = ""; 56 | }; 57 | 048793D821EB2D2A0073FFD1 /* Products */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | 048793D721EB2D2A0073FFD1 /* my_native.app */, 61 | ); 62 | name = Products; 63 | sourceTree = ""; 64 | }; 65 | 048793D921EB2D2A0073FFD1 /* my_native */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | 048793DA21EB2D2A0073FFD1 /* AppDelegate.h */, 69 | 048793DB21EB2D2A0073FFD1 /* AppDelegate.m */, 70 | 048793DD21EB2D2A0073FFD1 /* ViewController.h */, 71 | 048793DE21EB2D2A0073FFD1 /* ViewController.m */, 72 | 048793E021EB2D2A0073FFD1 /* Main.storyboard */, 73 | 048793E321EB2D2A0073FFD1 /* Assets.xcassets */, 74 | 048793E521EB2D2A0073FFD1 /* LaunchScreen.storyboard */, 75 | 048793E821EB2D2A0073FFD1 /* Info.plist */, 76 | 048793E921EB2D2A0073FFD1 /* main.m */, 77 | ); 78 | path = my_native; 79 | sourceTree = ""; 80 | }; 81 | 5A4C95FB5C05D97EA6BA495D /* Frameworks */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | A7A8A6BF5E10F413F87B8018 /* libPods-my_native.a */, 85 | ); 86 | name = Frameworks; 87 | sourceTree = ""; 88 | }; 89 | F04B1007FD7BD0D3F866E7C7 /* Pods */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 0E0AC92F4FF81CF71EA2B060 /* Pods-my_native.debug.xcconfig */, 93 | D2BBDA0B77FF6879643460EF /* Pods-my_native.release.xcconfig */, 94 | ); 95 | name = Pods; 96 | sourceTree = ""; 97 | }; 98 | /* End PBXGroup section */ 99 | 100 | /* Begin PBXNativeTarget section */ 101 | 048793D621EB2D2A0073FFD1 /* my_native */ = { 102 | isa = PBXNativeTarget; 103 | buildConfigurationList = 048793ED21EB2D2A0073FFD1 /* Build configuration list for PBXNativeTarget "my_native" */; 104 | buildPhases = ( 105 | 8966380AC6AF07230ADF4541 /* [CP] Check Pods Manifest.lock */, 106 | 048793D321EB2D2A0073FFD1 /* Sources */, 107 | 048793D421EB2D2A0073FFD1 /* Frameworks */, 108 | 048793D521EB2D2A0073FFD1 /* Resources */, 109 | ); 110 | buildRules = ( 111 | ); 112 | dependencies = ( 113 | ); 114 | name = my_native; 115 | productName = my_native; 116 | productReference = 048793D721EB2D2A0073FFD1 /* my_native.app */; 117 | productType = "com.apple.product-type.application"; 118 | }; 119 | /* End PBXNativeTarget section */ 120 | 121 | /* Begin PBXProject section */ 122 | 048793CF21EB2D290073FFD1 /* Project object */ = { 123 | isa = PBXProject; 124 | attributes = { 125 | LastUpgradeCheck = 0940; 126 | ORGANIZATIONNAME = mac; 127 | TargetAttributes = { 128 | 048793D621EB2D2A0073FFD1 = { 129 | CreatedOnToolsVersion = 9.4.1; 130 | }; 131 | }; 132 | }; 133 | buildConfigurationList = 048793D221EB2D290073FFD1 /* Build configuration list for PBXProject "my_native" */; 134 | compatibilityVersion = "Xcode 9.3"; 135 | developmentRegion = en; 136 | hasScannedForEncodings = 0; 137 | knownRegions = ( 138 | en, 139 | Base, 140 | ); 141 | mainGroup = 048793CE21EB2D290073FFD1; 142 | productRefGroup = 048793D821EB2D2A0073FFD1 /* Products */; 143 | projectDirPath = ""; 144 | projectRoot = ""; 145 | targets = ( 146 | 048793D621EB2D2A0073FFD1 /* my_native */, 147 | ); 148 | }; 149 | /* End PBXProject section */ 150 | 151 | /* Begin PBXResourcesBuildPhase section */ 152 | 048793D521EB2D2A0073FFD1 /* Resources */ = { 153 | isa = PBXResourcesBuildPhase; 154 | buildActionMask = 2147483647; 155 | files = ( 156 | 048793E721EB2D2A0073FFD1 /* LaunchScreen.storyboard in Resources */, 157 | 048793E421EB2D2A0073FFD1 /* Assets.xcassets in Resources */, 158 | 048793E221EB2D2A0073FFD1 /* Main.storyboard in Resources */, 159 | ); 160 | runOnlyForDeploymentPostprocessing = 0; 161 | }; 162 | /* End PBXResourcesBuildPhase section */ 163 | 164 | /* Begin PBXShellScriptBuildPhase section */ 165 | 8966380AC6AF07230ADF4541 /* [CP] Check Pods Manifest.lock */ = { 166 | isa = PBXShellScriptBuildPhase; 167 | buildActionMask = 2147483647; 168 | files = ( 169 | ); 170 | inputFileListPaths = ( 171 | ); 172 | inputPaths = ( 173 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 174 | "${PODS_ROOT}/Manifest.lock", 175 | ); 176 | name = "[CP] Check Pods Manifest.lock"; 177 | outputFileListPaths = ( 178 | ); 179 | outputPaths = ( 180 | "$(DERIVED_FILE_DIR)/Pods-my_native-checkManifestLockResult.txt", 181 | ); 182 | runOnlyForDeploymentPostprocessing = 0; 183 | shellPath = /bin/sh; 184 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 185 | showEnvVarsInLog = 0; 186 | }; 187 | /* End PBXShellScriptBuildPhase section */ 188 | 189 | /* Begin PBXSourcesBuildPhase section */ 190 | 048793D321EB2D2A0073FFD1 /* Sources */ = { 191 | isa = PBXSourcesBuildPhase; 192 | buildActionMask = 2147483647; 193 | files = ( 194 | 048793DF21EB2D2A0073FFD1 /* ViewController.m in Sources */, 195 | 048793EA21EB2D2A0073FFD1 /* main.m in Sources */, 196 | 048793DC21EB2D2A0073FFD1 /* AppDelegate.m in Sources */, 197 | ); 198 | runOnlyForDeploymentPostprocessing = 0; 199 | }; 200 | /* End PBXSourcesBuildPhase section */ 201 | 202 | /* Begin PBXVariantGroup section */ 203 | 048793E021EB2D2A0073FFD1 /* Main.storyboard */ = { 204 | isa = PBXVariantGroup; 205 | children = ( 206 | 048793E121EB2D2A0073FFD1 /* Base */, 207 | ); 208 | name = Main.storyboard; 209 | sourceTree = ""; 210 | }; 211 | 048793E521EB2D2A0073FFD1 /* LaunchScreen.storyboard */ = { 212 | isa = PBXVariantGroup; 213 | children = ( 214 | 048793E621EB2D2A0073FFD1 /* Base */, 215 | ); 216 | name = LaunchScreen.storyboard; 217 | sourceTree = ""; 218 | }; 219 | /* End PBXVariantGroup section */ 220 | 221 | /* Begin XCBuildConfiguration section */ 222 | 048793EB21EB2D2A0073FFD1 /* Debug */ = { 223 | isa = XCBuildConfiguration; 224 | buildSettings = { 225 | ALWAYS_SEARCH_USER_PATHS = NO; 226 | CLANG_ANALYZER_NONNULL = YES; 227 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 228 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 229 | CLANG_CXX_LIBRARY = "libc++"; 230 | CLANG_ENABLE_MODULES = YES; 231 | CLANG_ENABLE_OBJC_ARC = YES; 232 | CLANG_ENABLE_OBJC_WEAK = YES; 233 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 234 | CLANG_WARN_BOOL_CONVERSION = YES; 235 | CLANG_WARN_COMMA = YES; 236 | CLANG_WARN_CONSTANT_CONVERSION = YES; 237 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 238 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 239 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 240 | CLANG_WARN_EMPTY_BODY = YES; 241 | CLANG_WARN_ENUM_CONVERSION = YES; 242 | CLANG_WARN_INFINITE_RECURSION = YES; 243 | CLANG_WARN_INT_CONVERSION = YES; 244 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 245 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 246 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 247 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 248 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 249 | CLANG_WARN_STRICT_PROTOTYPES = YES; 250 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 251 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 252 | CLANG_WARN_UNREACHABLE_CODE = YES; 253 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 254 | CODE_SIGN_IDENTITY = "iPhone Developer"; 255 | COPY_PHASE_STRIP = NO; 256 | DEBUG_INFORMATION_FORMAT = dwarf; 257 | ENABLE_STRICT_OBJC_MSGSEND = YES; 258 | ENABLE_TESTABILITY = YES; 259 | GCC_C_LANGUAGE_STANDARD = gnu11; 260 | GCC_DYNAMIC_NO_PIC = NO; 261 | GCC_NO_COMMON_BLOCKS = YES; 262 | GCC_OPTIMIZATION_LEVEL = 0; 263 | GCC_PREPROCESSOR_DEFINITIONS = ( 264 | "DEBUG=1", 265 | "$(inherited)", 266 | ); 267 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 268 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 269 | GCC_WARN_UNDECLARED_SELECTOR = YES; 270 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 271 | GCC_WARN_UNUSED_FUNCTION = YES; 272 | GCC_WARN_UNUSED_VARIABLE = YES; 273 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 274 | MTL_ENABLE_DEBUG_INFO = YES; 275 | ONLY_ACTIVE_ARCH = YES; 276 | SDKROOT = iphoneos; 277 | }; 278 | name = Debug; 279 | }; 280 | 048793EC21EB2D2A0073FFD1 /* Release */ = { 281 | isa = XCBuildConfiguration; 282 | buildSettings = { 283 | ALWAYS_SEARCH_USER_PATHS = NO; 284 | CLANG_ANALYZER_NONNULL = YES; 285 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 286 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 287 | CLANG_CXX_LIBRARY = "libc++"; 288 | CLANG_ENABLE_MODULES = YES; 289 | CLANG_ENABLE_OBJC_ARC = YES; 290 | CLANG_ENABLE_OBJC_WEAK = YES; 291 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 292 | CLANG_WARN_BOOL_CONVERSION = YES; 293 | CLANG_WARN_COMMA = YES; 294 | CLANG_WARN_CONSTANT_CONVERSION = YES; 295 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 296 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 297 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 298 | CLANG_WARN_EMPTY_BODY = YES; 299 | CLANG_WARN_ENUM_CONVERSION = YES; 300 | CLANG_WARN_INFINITE_RECURSION = YES; 301 | CLANG_WARN_INT_CONVERSION = YES; 302 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 303 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 304 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 305 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 306 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 307 | CLANG_WARN_STRICT_PROTOTYPES = YES; 308 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 309 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 310 | CLANG_WARN_UNREACHABLE_CODE = YES; 311 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 312 | CODE_SIGN_IDENTITY = "iPhone Developer"; 313 | COPY_PHASE_STRIP = NO; 314 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 315 | ENABLE_NS_ASSERTIONS = NO; 316 | ENABLE_STRICT_OBJC_MSGSEND = YES; 317 | GCC_C_LANGUAGE_STANDARD = gnu11; 318 | GCC_NO_COMMON_BLOCKS = YES; 319 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 320 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 321 | GCC_WARN_UNDECLARED_SELECTOR = YES; 322 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 323 | GCC_WARN_UNUSED_FUNCTION = YES; 324 | GCC_WARN_UNUSED_VARIABLE = YES; 325 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 326 | MTL_ENABLE_DEBUG_INFO = NO; 327 | SDKROOT = iphoneos; 328 | VALIDATE_PRODUCT = YES; 329 | }; 330 | name = Release; 331 | }; 332 | 048793EE21EB2D2A0073FFD1 /* Debug */ = { 333 | isa = XCBuildConfiguration; 334 | baseConfigurationReference = 0E0AC92F4FF81CF71EA2B060 /* Pods-my_native.debug.xcconfig */; 335 | buildSettings = { 336 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 337 | CODE_SIGN_STYLE = Automatic; 338 | INFOPLIST_FILE = my_native/Info.plist; 339 | LD_RUNPATH_SEARCH_PATHS = ( 340 | "$(inherited)", 341 | "@executable_path/Frameworks", 342 | ); 343 | PRODUCT_BUNDLE_IDENTIFIER = "caffrey.my-native"; 344 | PRODUCT_NAME = "$(TARGET_NAME)"; 345 | TARGETED_DEVICE_FAMILY = "1,2"; 346 | }; 347 | name = Debug; 348 | }; 349 | 048793EF21EB2D2A0073FFD1 /* Release */ = { 350 | isa = XCBuildConfiguration; 351 | baseConfigurationReference = D2BBDA0B77FF6879643460EF /* Pods-my_native.release.xcconfig */; 352 | buildSettings = { 353 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 354 | CODE_SIGN_STYLE = Automatic; 355 | INFOPLIST_FILE = my_native/Info.plist; 356 | LD_RUNPATH_SEARCH_PATHS = ( 357 | "$(inherited)", 358 | "@executable_path/Frameworks", 359 | ); 360 | PRODUCT_BUNDLE_IDENTIFIER = "caffrey.my-native"; 361 | PRODUCT_NAME = "$(TARGET_NAME)"; 362 | TARGETED_DEVICE_FAMILY = "1,2"; 363 | }; 364 | name = Release; 365 | }; 366 | /* End XCBuildConfiguration section */ 367 | 368 | /* Begin XCConfigurationList section */ 369 | 048793D221EB2D290073FFD1 /* Build configuration list for PBXProject "my_native" */ = { 370 | isa = XCConfigurationList; 371 | buildConfigurations = ( 372 | 048793EB21EB2D2A0073FFD1 /* Debug */, 373 | 048793EC21EB2D2A0073FFD1 /* Release */, 374 | ); 375 | defaultConfigurationIsVisible = 0; 376 | defaultConfigurationName = Release; 377 | }; 378 | 048793ED21EB2D2A0073FFD1 /* Build configuration list for PBXNativeTarget "my_native" */ = { 379 | isa = XCConfigurationList; 380 | buildConfigurations = ( 381 | 048793EE21EB2D2A0073FFD1 /* Debug */, 382 | 048793EF21EB2D2A0073FFD1 /* Release */, 383 | ); 384 | defaultConfigurationIsVisible = 0; 385 | defaultConfigurationName = Release; 386 | }; 387 | /* End XCConfigurationList section */ 388 | }; 389 | rootObject = 048793CF21EB2D290073FFD1 /* Project object */; 390 | } 391 | -------------------------------------------------------------------------------- /Example/my_native/my_native.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/my_native/my_native.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/my_native/my_native.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/my_native/my_native.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/my_native/my_native/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // my_native 4 | // 5 | // Created by mac on 2019/1/13. 6 | // Copyright © 2019 mac. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface AppDelegate : FlutterAppDelegate 13 | 14 | @property (nonatomic,strong) FlutterEngine *flutterEngine; 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /Example/my_native/my_native/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // my_native 4 | // 5 | // Created by mac on 2019/1/13. 6 | // Copyright © 2019 mac. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | self.flutterEngine = [[FlutterEngine alloc] initWithName:@"io.flutter" project:nil]; 21 | [self.flutterEngine runWithEntrypoint:nil]; 22 | [GeneratedPluginRegistrant registerWithRegistry:self.flutterEngine]; 23 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 24 | } 25 | 26 | 27 | - (void)applicationWillResignActive:(UIApplication *)application { 28 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 29 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 30 | } 31 | 32 | 33 | - (void)applicationDidEnterBackground:(UIApplication *)application { 34 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 35 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 36 | } 37 | 38 | 39 | - (void)applicationWillEnterForeground:(UIApplication *)application { 40 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 41 | } 42 | 43 | 44 | - (void)applicationDidBecomeActive:(UIApplication *)application { 45 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 46 | } 47 | 48 | 49 | - (void)applicationWillTerminate:(UIApplication *)application { 50 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 51 | } 52 | 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /Example/my_native/my_native/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Example/my_native/my_native/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/my_native/my_native/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Example/my_native/my_native/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Example/my_native/my_native/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Example/my_native/my_native/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // my_native 4 | // 5 | // Created by mac on 2019/1/13. 6 | // Copyright © 2019 mac. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Example/my_native/my_native/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // my_native 4 | // 5 | // Created by mac on 2019/1/13. 6 | // Copyright © 2019 mac. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "AppDelegate.h" 11 | #import 12 | 13 | @interface ViewController () 14 | 15 | @end 16 | 17 | @implementation ViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 22 | [button addTarget:self 23 | action:@selector(handleButtonAction) 24 | forControlEvents:UIControlEventTouchUpInside]; 25 | [button setTitle:@"Press me" forState:UIControlStateNormal]; 26 | [button setBackgroundColor:[UIColor blueColor]]; 27 | button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0); 28 | [self.view addSubview:button]; 29 | } 30 | 31 | - (void)viewWillAppear:(BOOL)animated { 32 | [super viewWillAppear:animated]; 33 | [self.navigationController setNavigationBarHidden:YES animated:animated]; 34 | } 35 | 36 | - (void)handleButtonAction { 37 | FlutterEngine *flutterEngine = [(AppDelegate *)[[UIApplication sharedApplication] delegate] flutterEngine]; 38 | FlutterViewController *flutterViewController = [[FlutterViewController alloc] initWithEngine:flutterEngine nibName:nil bundle:nil]; 39 | [self.navigationController pushViewController:flutterViewController animated:YES]; 40 | } 41 | 42 | 43 | - (void)didReceiveMemoryWarning { 44 | [super didReceiveMemoryWarning]; 45 | // Dispose of any resources that can be recreated. 46 | } 47 | 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /Example/my_native/my_native/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // my_native 4 | // 5 | // Created by mac on 2019/1/13. 6 | // Copyright © 2019 mac. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 CaffreySun 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iOS_Flutter_Hybrid_Project 2 | 3 | [![](https://badge.juejin.im/entry/5c3afcf26fb9a049f1546e7d/likes.svg?style=flat-square)](https://juejin.im/post/5c3ae5ef518825242165c5ca) 4 | [![Gitter](https://badges.gitter.im/iOS_Flutter_Hybrid_Project/community.svg)](https://gitter.im/iOS_Flutter_Hybrid_Project/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) 5 | 6 | [从零搭建 iOS Native Flutter 混合工程](https://juejin.im/post/5c3ae5ef518825242165c5ca) 7 | ## 使用说明 8 | 9 | 本仓库为创建 iOS Flutter 混合工程的脚本和例子。 10 | 11 | 使用本仓库搭建混合工程步骤: 12 | 13 | 使用git方式管理产物: 14 | 1. 使用`flutter create -t module my_flutter`创建 Flutter Module 工程。 15 | 2. 复制"Script/git/Flutter"目录内的所有文件到 Flutter 工程根目录. 16 | 3. 修改复制的 build_ios.sh 里参数"PRODUCT_GIT_DIR",使其指向用来保存产物的git仓库的路径,**是路径** 不是git地址。 17 | 4. 复制"Script/git/Native"中除了Podfile外的文件到 Native 根目录。 18 | 5. 复制"Script/git/Native/Podfile"文件内 "end" 后面的配置内容到自己 Native 工程的 Podfile。并根据自己的工程修改配置。 19 | 6. 在Flutter工程目录下使用 build_ios.sh -m release/debug 进行打包,会自动将产物复制到git仓库目录,并执行git push。 20 | 7. 在Native工程执行 pod install,会自动从git拉取产物并安装。 21 | 22 | 使用Maven方式管理产物: 23 | 1. 使用`flutter create -t module my_flutter`创建 Flutter Module 工程。 24 | 2. 复制"Script/Maven/Flutter"目录内的所有文件到 Flutter Module 工程根目录. 25 | 3. 修改 Maven.sh,将Maven服务器地址、用户名、项目地址改成自己的。 26 | 4. 复制"Script/Maven/Native"中出Podfile外的文件到 Native 根目录。 27 | 5. 复制"Script/Maven/Native/Podfile"文件内 "end" 后面的配置内容到自己 Native 工程的 Podfile。并根据自己的工程修改配置。 28 | 6. 修改 Native 工程目录里的 Maven.sh,将Maven服务器地址、用户名、项目地址改成自己的。 29 | 7. 在Flutter工程下使用build_ios.sh -m release/debug 进行打包,会自动将产物上传到maven。 30 | 8. 在Native工程执行 pod install,会自动从maven下载Flutter产物并安装。 31 | 32 | ## 常见问题 33 | 34 | 1、Release 模式签名错误,错误输出如下: 35 | ``` 36 | Xcode's output: 37 | ↳ 38 | === BUILD TARGET Runner OF PROJECT Runner WITH CONFIGURATION Release === 39 | Code Signing Error: Failed to create provisioning profile. The app ID "com.example.myFlutter" cannot be registered to your development team. Change your bundle 40 | identifier to a unique string to try again. 41 | Code Signing Error: No profiles for 'com.example.myFlutter' were found: Xcode couldn't find any iOS App Development provisioning profiles matching 42 | 'com.example.myFlutter'. 43 | Code Signing Error: Code signing is required for product type 'Application' in SDK 'iOS 12.2' 44 | Code Signing Error: Code signing is required for product type 'Application' in SDK 'iOS 12.2' 45 | Code Signing Error: Code signing is required for product type 'Application' in SDK 'iOS 12.2' 46 | 47 | 48 | It appears that your application still contains the default signing identifier. 49 | Try replacing 'com.example' with your signing id in Xcode: 50 | open ios/Runner.xcworkspace 51 | Encountered error while building for device. 52 | 53 | ``` 54 | 请用xCode打开Flutter工程目录下的.ios/Runner.xcworkspace工程,然后修改BundleId为自己的BundleId,然后重新执行release编译。 -------------------------------------------------------------------------------- /Script/Maven/Flutter/build_ios.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | BUILD_MODE="debug" 4 | ARCHS_ARM="arm64,armv7" 5 | FLUTTER_ROOT=".flutter" 6 | PRODUCT_DIR="product" 7 | PRODUCT_ZIP="product.zip" 8 | FLUTTER_WRAPPER="./flutterw" 9 | 10 | BUILD_PATH=".build_ios/${BUILD_MODE}" 11 | PRODUCT_PATH="${BUILD_PATH}/${PRODUCT_DIR}" 12 | PRODUCT_APP_PATH="${PRODUCT_PATH}/Flutter" 13 | 14 | usage() { 15 | echo 16 | echo "build_ios.sh [-h | [-m ] [-s]]" 17 | echo "" 18 | echo "-h - Help." 19 | echo "-m - Build model, valid values are 'debug', 'profile', or 'release'. " 20 | echo " Default values: 'debug'." 21 | echo "" 22 | echo "Build product in 'build_ios//${PRODUCT_DIR}' directory." 23 | echo 24 | } 25 | 26 | EchoError() { 27 | echo "$@" 1>&2 28 | } 29 | 30 | flutter_get_packages() { 31 | echo "=================================" 32 | echo "Start get flutter app plugin" 33 | 34 | if [ -e $FLUTTER_WRAPPER ]; then 35 | echo 'flutterw installed' >/dev/null 36 | else 37 | bash -c "$(curl -fsSL https://raw.githubusercontent.com/passsy/flutter_wrapper/master/install.sh)" 38 | if [[ $? -ne 0 ]]; then 39 | EchoError "Failed to installed flutter_wrapper." 40 | exit -1 41 | fi 42 | fi 43 | 44 | ${FLUTTER_WRAPPER} packages get --verbose 45 | if [[ $? -ne 0 ]]; then 46 | EchoError "Failed to install flutter plugins." 47 | exit -1 48 | fi 49 | 50 | echo "Finish get flutter app plugin" 51 | } 52 | 53 | build_flutter_app() { 54 | echo "=================================" 55 | echo "Start Build flutter app" 56 | echo "Build mode: ${BUILD_MODE}" 57 | 58 | mkdir -p -- "${PRODUCT_APP_PATH}" 59 | 60 | local target_path="lib/main.dart" 61 | 62 | local artifact_variant="unknown" 63 | case "$BUILD_MODE" in 64 | release*) 65 | artifact_variant="ios-release" 66 | ;; 67 | profile*) 68 | artifact_variant="ios-profile" 69 | ;; 70 | debug*) 71 | artifact_variant="ios" 72 | ;; 73 | *) 74 | EchoError "========================================================================" 75 | EchoError "ERROR: Unknown FLUTTER_BUILD_MODE: ${BUILD_MODE}." 76 | EchoError "Valid values are 'debug', 'profile', or 'release'." 77 | EchoError "This is controlled by the -m environment varaible." 78 | EchoError "========================================================================" 79 | exit -1 80 | ;; 81 | esac 82 | 83 | if [[ "${BUILD_MODE}" != "debug" ]]; then 84 | if [[ $ARCHS_ARM =~ .*i386.* || $ARCHS_ARM =~ .*x86_64.* ]]; then 85 | EchoError "========================================================================" 86 | EchoError "ERROR: Flutter does not support running in profile or release mode on" 87 | EchoError "the Simulator (this build was: '$BUILD_MODE')." 88 | EchoError "mode by setting '-m debug'" 89 | EchoError "========================================================================" 90 | exit -1 91 | fi 92 | 93 | echo "Build archs: ${ARCHS_ARM}" 94 | 95 | ${FLUTTER_WRAPPER} clean 96 | 97 | ${FLUTTER_WRAPPER} build ios --${BUILD_MODE} 98 | 99 | if [[ $? -ne 0 ]]; then 100 | EchoError "Failed to build flutter app" 101 | exit -1 102 | fi 103 | 104 | cp -r -- ".ios/Flutter/App.framework" "${BUILD_PATH}/App.framework" 105 | else 106 | echo "Build archs: x86_64 ${ARCHS_ARM}" 107 | local app_framework_debug="iOSApp/Debug/App.framework" 108 | cp -r -- "${app_framework_debug}" "${BUILD_PATH}" 109 | 110 | app_plist_path=".ios/Flutter/AppFrameworkInfo.plist" 111 | cp -- "${app_plist_path}" "${BUILD_PATH}/App.framework/Info.plist" 112 | 113 | local precompilation_flag="" 114 | if [[ "$BUILD_MODE" != "debug" ]]; then 115 | precompilation_flag="--precompiled" 116 | fi 117 | 118 | # build bundle 119 | ${FLUTTER_WRAPPER} --suppress-analytics \ 120 | --verbose \ 121 | build bundle \ 122 | --target-platform=ios \ 123 | --target="${target_path}" \ 124 | --${BUILD_MODE} \ 125 | --depfile="${BUILD_PATH}/snapshot_blob.bin.d" \ 126 | --asset-dir="${BUILD_PATH}/flutter_assets" \ 127 | ${precompilation_flag} 128 | 129 | if [[ $? -ne 0 ]]; then 130 | EchoError "Failed to build flutter assets" 131 | exit -1 132 | fi 133 | 134 | cp -rf -- "${BUILD_PATH}/flutter_assets" "${BUILD_PATH}/App.framework" 135 | fi 136 | 137 | # copy flutter sdk 138 | local framework_path="${FLUTTER_ROOT}/bin/cache/artifacts/engine/${artifact_variant}" 139 | local flutter_framework="${framework_path}/Flutter.framework" 140 | local flutter_podspec="${framework_path}/Flutter.podspec" 141 | 142 | cp -r -- "${BUILD_PATH}/App.framework" "${PRODUCT_APP_PATH}" 143 | cp -r -- "${flutter_framework}" "${PRODUCT_APP_PATH}" 144 | cp -r -- "${flutter_podspec}" "${PRODUCT_APP_PATH}" 145 | 146 | # setting podspec 147 | # replace: 148 | # 'Flutter.framework' 149 | # to: 150 | # 'Flutter.framework', 'App.framework' 151 | sed -i '' -e $'s/\'Flutter.framework\'/\'Flutter.framework\', \'App.framework\'/g' ${PRODUCT_APP_PATH}/Flutter.podspec 152 | 153 | echo "Finish build flutter app" 154 | } 155 | 156 | flutter_copy_packages() { 157 | echo "=================================" 158 | echo "Start copy flutter app plugin" 159 | 160 | local flutter_plugin_registrant="FlutterPluginRegistrant" 161 | local flutter_plugin_registrant_path=".ios/Flutter/${flutter_plugin_registrant}" 162 | echo "copy 'flutter_plugin_registrant' from '${flutter_plugin_registrant_path}' to '${PRODUCT_PATH}/${flutter_plugin_registrant}'" 163 | cp -rf -- "${flutter_plugin_registrant_path}" "${PRODUCT_PATH}/${flutter_plugin_registrant}" 164 | 165 | local flutter_plugin=".flutter-plugins" 166 | if [ -e $flutter_plugin ]; then 167 | OLD_IFS="$IFS" 168 | IFS="=" 169 | cat ${flutter_plugin} | while read plugin; do 170 | local plugin_info=($plugin) 171 | local plugin_name=${plugin_info[0]} 172 | local plugin_path=${plugin_info[1]} 173 | 174 | if [ -e ${plugin_path} ]; then 175 | local plugin_path_ios="${plugin_path}ios" 176 | if [ -e ${plugin_path_ios} ]; then 177 | if [ -s ${plugin_path_ios} ]; then 178 | echo "copy plugin 'plugin_name' from '${plugin_path_ios}' to '${PRODUCT_PATH}/${plugin_name}'" 179 | cp -rf ${plugin_path_ios} "${PRODUCT_PATH}/${plugin_name}" 180 | fi 181 | fi 182 | fi 183 | done 184 | IFS="$OLD_IFS" 185 | fi 186 | 187 | echo "Finish copy flutter app plugin" 188 | } 189 | 190 | zip_product() { 191 | echo "=================================" 192 | echo "Start zip product" 193 | 194 | pushd ${BUILD_PATH} 195 | zip -r "${PRODUCT_ZIP}" "${PRODUCT_DIR}" 196 | if [[ $? -ne 0 ]]; then 197 | EchoError "Failed to zip product" 198 | exit -1 199 | fi 200 | 201 | popd 202 | 203 | echo "Finish zip product" 204 | } 205 | 206 | maven_upload() { 207 | echo "=================================" 208 | echo "Start upload ${PRODUCT_ZIP} to maven" 209 | 210 | local app_version=$(./get_version.sh) 211 | 212 | echo "Upload version: ${app_version}" 213 | 214 | ./maven.sh upload ${app_version} ${BUILD_PATH}/${PRODUCT_ZIP} 215 | 216 | if [[ $? -ne 0 ]]; then 217 | EchoError "Failed to upload maven" 218 | exit -1 219 | fi 220 | 221 | echo "Finish upload ${PRODUCT_ZIP} to maven" 222 | } 223 | 224 | start_build() { 225 | 226 | rm -rf ${BUILD_PATH} 227 | 228 | flutter_get_packages 229 | 230 | build_flutter_app 231 | 232 | flutter_copy_packages 233 | 234 | if [[ "${BUILD_MODE}" == "release" ]]; then 235 | 236 | zip_product 237 | 238 | maven_upload 239 | fi 240 | 241 | echo "" 242 | echo "done!" 243 | } 244 | 245 | show_help=0 246 | while getopts "m:sh" arg; do 247 | case $arg in 248 | m) 249 | BUILD_MODE="$OPTARG" 250 | ;; 251 | h) 252 | show_help=1 253 | ;; 254 | ?) 255 | show_help=1 256 | ;; 257 | esac 258 | done 259 | 260 | if [ $show_help == 1 ]; then 261 | usage 262 | exit 0 263 | fi 264 | 265 | BUILD_PATH=".build_ios/${BUILD_MODE}" 266 | PRODUCT_PATH="${BUILD_PATH}/${PRODUCT_DIR}" 267 | PRODUCT_APP_PATH="${PRODUCT_PATH}/Flutter" 268 | 269 | start_build 270 | 271 | exit 0 272 | -------------------------------------------------------------------------------- /Script/Maven/Flutter/get_version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | FILE_PATH="" 4 | FILE_PATH_DEF="./pubspec.yaml" 5 | # 过滤 version name 的正则表达式 6 | VERSION_NAME_REGEX="^version: " 7 | # 过滤 version code 的正则表达式 8 | VERSION_CODE_REGEX="^version_code: " 9 | 10 | throw () { 11 | echo "error: $*" >&2 12 | exit 1 13 | } 14 | 15 | usage() { 16 | echo 17 | echo "Usage: get_version.sh [-h] [--name] [--code] []" 18 | echo " [e.g.]: /get_version.sh // Get version name from def file ${FILE_PATH_DEF}." 19 | echo " [e.g.]: /get_version.sh --name example.txt // Get version name from the specified file." 20 | echo " [e.g.]: /get_version.sh --code example.txt // Get version code from the specified file." 21 | echo 22 | echo "--name - [Default] Get version name from the specified file, the def file is ${FILE_PATH_DEF}." 23 | echo "--code - Get version code from the specified file, the def file is ${FILE_PATH_DEF}." 24 | echo "-h - This help text." 25 | echo 26 | } 27 | 28 | parse_options() { 29 | set -- "$@" 30 | local ARGN=$# 31 | while [ "$ARGN" -ne 0 ] 32 | do 33 | case $1 in 34 | -h) usage 35 | exit 0 36 | ;; 37 | --name) FILE_PATH=$2 38 | get_version_name 39 | ;; 40 | --code) FILE_PATH=$2 41 | get_version_code 42 | ;; 43 | ?*) echo "ERROR: Unknown option." 44 | usage 45 | exit 0 46 | ;; 47 | esac 48 | shift 1 49 | ARGN=$((ARGN-1)) 50 | done 51 | } 52 | 53 | get_version_name() { 54 | get_file 55 | #echo "get version name from ${FILE_PATH} ..." 56 | version_name=`egrep ${VERSION_NAME_REGEX} ${FILE_PATH}` 57 | # 取`:`右边 58 | version_name=`echo ${version_name} | sed 's/^.*://g'` 59 | # 删除`;` 60 | version_name=`echo ${version_name} | sed 's/;.*$//g'` 61 | # 删除`"` 62 | version_name=`echo ${version_name} | sed 's/\"//g'` 63 | # 删除`'` 64 | version_name=`echo ${version_name} | sed "s/\'//g"` 65 | #echo "version name: 【${version_name}】" 66 | echo ${version_name} 67 | finish 68 | } 69 | 70 | get_version_code() { 71 | get_file 72 | #echo "get version code from ${FILE_PATH} ..." 73 | version_code=`egrep ${VERSION_CODE_REGEX} ${FILE_PATH}` 74 | # 取`:`右边 75 | version_code=`echo ${version_code} | sed 's/^.*://g'` 76 | # 删除`;` 77 | version_code=`echo ${version_code} | sed 's/;.*$//g'` 78 | #echo "version code: 【${version_code}】" 79 | echo ${version_code} 80 | finish 81 | } 82 | 83 | get_file() { 84 | if [ "$FILE_PATH"x = ""x ]; then 85 | FILE_PATH=${FILE_PATH_DEF} 86 | fi 87 | } 88 | 89 | finish() { 90 | exit 0 91 | } 92 | 93 | default_action() { 94 | get_version_name 95 | } 96 | 97 | if ([ "$0" = "$BASH_SOURCE" ] || ! [ -n "$BASH_SOURCE" ]); 98 | then 99 | parse_options "$@" 100 | default_action 101 | fi 102 | -------------------------------------------------------------------------------- /Script/Maven/Flutter/iOSApp/debug/App.framework/App: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CaffreySun/iOS_Flutter_Hybrid_Project/768167a3c3ae38191e28d20d66b83cd85ea52197/Script/Maven/Flutter/iOSApp/debug/App.framework/App -------------------------------------------------------------------------------- /Script/Maven/Flutter/maven.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | FILE_NAME="flutter.zip" 4 | FILE_PATH="xxx" 5 | VERSION="" 6 | MAVEN_PATH="http://xxx" 7 | MAVEN_USER="xxx:xxx" 8 | LOCAL_FILE_PATH="" 9 | 10 | throw () { 11 | echo "error: $*" >&2 12 | exit 1 13 | } 14 | 15 | usage() { 16 | echo 17 | echo "Usage: maven.sh [-h] [upload] [download]" 18 | echo 19 | echo "upload - Upload to maven. [e.g.]: ./maven.sh upload 1.0.0 localFile.zip" 20 | echo "download - Download from maven. [e.g.]: ./maven.sh download 1.0.1" 21 | echo "-h - This help text." 22 | echo 23 | } 24 | 25 | parse_options() { 26 | set -- "$@" 27 | local ARGN=$# 28 | while [ "$ARGN" -ne 0 ] 29 | do 30 | case $1 in 31 | -h) usage 32 | exit 0 33 | ;; 34 | upload) VERSION=$2 35 | LOCAL_FILE_PATH=$3 36 | upload 37 | ;; 38 | download) VERSION=$2 39 | download 40 | ;; 41 | ?*) echo "ERROR: Unknown option." 42 | usage 43 | exit 0 44 | ;; 45 | esac 46 | shift 1 47 | ARGN=$((ARGN-1)) 48 | done 49 | } 50 | 51 | upload() { 52 | if [ "$VERSION"x = ""x ]; then 53 | throw "version null" 54 | fi 55 | if [ "$LOCAL_FILE_PATH"x = ""x ]; then 56 | throw "file null" 57 | fi 58 | if ! [ -f $LOCAL_FILE_PATH ]; then 59 | throw "file $LOCAL_FILE_PATH not exist" 60 | fi 61 | echo 62 | echo "Uploading..." 63 | echo "$LOCAL_FILE_PATH -> $MAVEN_PATH/$FILE_PATH/$VERSION/$FILE_NAME" 64 | curl -u$MAVEN_USER -T $LOCAL_FILE_PATH "$MAVEN_PATH/$FILE_PATH/$VERSION/$FILE_NAME" 65 | echo 66 | echo "Done!" 67 | echo 68 | exit 0 69 | } 70 | 71 | download() { 72 | if [ "$VERSION"x = ""x ]; then 73 | throw "version null" 74 | fi 75 | echo 76 | echo "Downloading..." 77 | echo "$MAVEN_PATH/$FILE_PATH/$VERSION/$FILE_NAME" 78 | curl -u$MAVEN_USER -O "$MAVEN_PATH/$FILE_PATH/$VERSION/$FILE_NAME" 79 | echo "Done!" 80 | echo 81 | exit 0 82 | } 83 | 84 | if ([ "$0" = "$BASH_SOURCE" ] || ! [ -n "$BASH_SOURCE" ]); 85 | then 86 | parse_options "$@" 87 | usage 88 | exit 0 89 | fi 90 | -------------------------------------------------------------------------------- /Script/Maven/Native/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'TestMoreFlutter' do 5 | # Uncomment the next line if you're using Swift or would like to use dynamic frameworks 6 | # use_frameworks! 7 | 8 | # Pods for TestMoreFlutter 9 | 10 | end 11 | 12 | 13 | # 设置要引入的 flutter app 的版本 14 | FLUTTER_APP_VERSION="4.01.01" 15 | 16 | # 是否进行调试 flutter app, 17 | # 为true时FLUTTER_APP_VERSION配置失效,下面的三项配置生效 18 | # 为false时FLUTTER_APP_VERSION配置生效,下面的三项配置失效 19 | FLUTTER_DEBUG_APP=false 20 | 21 | # Flutter App git地址,从git拉取的内容放在当前工程目录下的.flutter/app目录 22 | # 如果指定了FLUTTER_APP_PATH,则此配置失效 23 | FLUTTER_APP_URL="ssh://gerrit.yimi.com:29418/flutter-client" 24 | # flutter git 分支,默认为master 25 | # 如果指定了FLUTTER_APP_PATH,则此配置失效 26 | FLUTTER_APP_BRANCH="master" 27 | 28 | # flutter本地工程目录,绝对路径或者相对路径,如果 != nil 则git相关的配置无效 29 | FLUTTER_APP_PATH=nil 30 | 31 | eval(File.read(File.join(__dir__, 'flutterhelper.rb')), binding) -------------------------------------------------------------------------------- /Script/Maven/Native/flutterhelper.rb: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # 3 | # 脚本使用方式: 4 | # 你需要在 Podfile 添加以下=begin =end 之间的内容: 5 | =begin 6 | 7 | # 设置要引入的 flutter app 的版本 8 | FLUTTER_APP_VERSION="4.01.01" 9 | 10 | # 是否进行调试 flutter app, 11 | # 为true时FLUTTER_APP_VERSION配置失效,下面的配置生效 12 | # 为false时FLUTTER_APP_VERSION配置生效,下面的配置失效 13 | FLUTTER_DEBUG_APP=false 14 | 15 | # Flutter App git地址,从git拉取的内容放在当前工程目录下的.flutter/app目录 16 | # 如果指定了FLUTTER_APP_PATH,则此配置失效 17 | FLUTTER_APP_URL="gut://xxx.git" 18 | # flutter git 分支,默认为master 19 | # 如果指定了FLUTTER_APP_PATH,则此配置失效 20 | FLUTTER_APP_BRANCH="master" 21 | 22 | # flutter本地工程目录,绝对路径或者相对路径, 23 | # FLUTTER_DEBUG_APP == false时才有效,如果 != nil 则git相关的配置无效 24 | FLUTTER_APP_PATH=nil 25 | 26 | eval(File.read(File.join(__dir__, 'flutterhelper.rb')), binding) 27 | 28 | =end 29 | # 30 | ############################################################################## 31 | 32 | # 拉取代码方法 33 | def update_flutter_app(path, url, branche) 34 | # 如果flutter项目不存在,则clone 35 | if !File.exist?(path) 36 | `git clone #{url} #{path}` 37 | end 38 | `cd #{path} && git fetch --all -v && \ 39 | git reset --hard origin/master && \ 40 | git pull && \ 41 | git checkout -B #{branche} origin/#{branche}` 42 | end 43 | 44 | # 安装开发环境app 45 | def install_debug_flutter_app 46 | 47 | puts "如果是第一次运行开发环境Flutter项目,此过程可能会较慢" 48 | puts "请耐心等️待☕️️️️️☕️☕️\n" 49 | 50 | # 默认Flutter App 目录 51 | flutter_application_path = __dir__ + "/.flutter/app" 52 | flutter_application_url = "" 53 | flutter_application_branch = 'master' 54 | 55 | if FLUTTER_APP_PATH != nil 56 | File.expand_path(FLUTTER_APP_PATH) 57 | if File.exist?(FLUTTER_APP_PATH) 58 | flutter_application_path = FLUTTER_APP_PATH 59 | else 60 | flutter_application_path = File.expand_path(FLUTTER_APP_PATH) 61 | if !File.exist?(flutter_application_path) 62 | raise "Error: #{FLUTTER_APP_PATH} 地址不存在!" 63 | end 64 | end 65 | 66 | puts "\nFlutter App路径: "+flutter_application_path 67 | else 68 | if FLUTTER_APP_URL != nil 69 | flutter_application_url = FLUTTER_APP_URL 70 | if FLUTTER_APP_BRANCH != nil 71 | flutter_application_branch = FLUTTER_APP_BRANCH 72 | end 73 | else 74 | raise "Error: 请在'Podfile'里增加Flutter App git地址配置,配置格式请查看'flutterhelper.rb'文件" 75 | end 76 | puts "\n拉取 Flutter App 代码" 77 | puts "Flutter App路径: "+flutter_application_path 78 | update_flutter_app(flutter_application_path, flutter_application_url, flutter_application_branch) 79 | end 80 | 81 | puts "\n编译 Flutter App" 82 | `export PUB_HOSTED_URL=https://pub.flutter-io.cn && \ 83 | export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn && \ 84 | cd #{flutter_application_path} && \ 85 | #{flutter_application_path}/build_ios.sh -m debug` 86 | 87 | if $?.to_i == 0 88 | flutter_package_path = "#{flutter_application_path}/.build_ios/debug/product" 89 | # 开始安装 90 | install_release_flutter_app_pod(flutter_package_path) 91 | else 92 | raise "Error: 编译 Flutter App失败" 93 | end 94 | end 95 | 96 | # 解压flutter app file 97 | def unzip_release_flutter_fill(zip_file, package_unzip, package_path) 98 | if package_path.nil? || package_path.nil? || package_path.nil? 99 | return false 100 | end 101 | 102 | puts "开始解压 flutter app #{zip_file}" 103 | 104 | # 删除标志物 105 | FileUtils.rm_rf(package_unzip) 106 | # 解压 107 | `unzip #{zip_file} -d #{package_path}` 108 | if $?.to_i == 0 109 | # 解压成功,创建标志物 110 | FileUtils.touch(package_unzip) 111 | 112 | return true 113 | else 114 | return false 115 | end 116 | end 117 | 118 | # 解压flutter app 119 | def unzip_release_flutter_app(package_path, zip_file) 120 | # 产物包已解压标志 121 | flutter_package_unzip = File.join(package_path, "unzip.ok") 122 | # 产物包解压后的目录 123 | flutter_package_path = File.join(package_path, "product") 124 | 125 | if File.exist? flutter_package_unzip 126 | if File.exist? flutter_package_path 127 | return flutter_package_path 128 | else 129 | unziped = unzip_release_flutter_fill(zip_file, flutter_package_unzip, package_path) 130 | if unziped == true 131 | return flutter_package_path 132 | else 133 | raise "Error: Flutter app 解压失败 #{zip_file}" 134 | end 135 | end 136 | else 137 | FileUtils.rm_rf(flutter_package_path) 138 | unziped = unzip_release_flutter_fill(zip_file, flutter_package_unzip, package_path) 139 | if unziped == true 140 | return flutter_package_path 141 | else 142 | raise "Error: Flutter app 解压失败 #{zip_file}" 143 | end 144 | end 145 | end 146 | 147 | # 下载 release 产物 148 | def download_release_flutter_app(app_version, download_path, downloaded_file) 149 | 150 | if app_version.nil? || download_path.nil? 151 | raise "Error: 请在 Podfile 里设置要安装的 Flutter app 版本 ,例如:FLUTTER_APP_VERSION='1.0.0'" 152 | end 153 | 154 | if download_path.nil? 155 | raise "Error: 无效的下载路径" 156 | end 157 | 158 | if downloaded_file.nil? 159 | raise "Error: 无效的下载产物路径" 160 | end 161 | 162 | puts "开始下载 #{app_version} 版本 flutter app" 163 | `./maven.sh download #{app_version}` 164 | 165 | if $?.to_i == 0 166 | # 移动产物 167 | FileUtils.mv('flutter.zip', download_path) 168 | # 下载成功,创建标志物 169 | FileUtils.touch(downloaded_file) 170 | else 171 | raise "Error: 下载失败 #{app_version} 版本 flutter app" 172 | end 173 | end 174 | 175 | # 将 Flutter app 通过 pod 安装 176 | def install_release_flutter_app_pod(product_path) 177 | if product_path.nil? 178 | raise "Error: 无效的 flutter app 目录" 179 | end 180 | 181 | puts "将 flutter app 通过 pod 导入到 工程" 182 | 183 | Dir.foreach product_path do |sub| 184 | # 忽略隐藏文件夹 185 | if sub =~ /\.(.*)/ 186 | next 187 | end 188 | 189 | sub_abs_path = File.join(product_path, sub) 190 | pod sub, :path=>sub_abs_path 191 | end 192 | 193 | post_install do |installer| 194 | installer.pods_project.targets.each do |target| 195 | target.build_configurations.each do |config| 196 | config.build_settings['ENABLE_BITCODE'] = 'NO' 197 | end 198 | end 199 | end 200 | end 201 | 202 | 203 | # 安装正式环境环境app 204 | def install_release_flutter_app 205 | if FLUTTER_APP_VERSION.nil? 206 | raise "Error: 请在 Podfile 里设置要安装的 Flutter app 版本 ,例如:FLUTTER_APP_VERSION='1.0.0'" 207 | else 208 | puts "当前安装的 flutter app 版本为 #{FLUTTER_APP_VERSION}" 209 | end 210 | 211 | # 存放产物的目录 212 | flutter_release_path = File.expand_path('.flutter_release') 213 | has_version_file = true 214 | if !File.exist? flutter_release_path 215 | FileUtils.mkdir_p(flutter_release_path) 216 | has_version_file = false 217 | end 218 | 219 | # 存放当前版本产物的目录 220 | flutter_release_version_path = File.join(flutter_release_path, FLUTTER_APP_VERSION) 221 | if !File.exist? flutter_release_version_path 222 | FileUtils.mkdir_p(flutter_release_version_path) 223 | has_version_file = false 224 | end 225 | 226 | # 产物包 227 | flutter_package = "flutter.zip" 228 | flutter_release_zip_file = File.join(flutter_release_version_path, flutter_package) 229 | if !File.exist? flutter_release_zip_file 230 | has_version_file = false 231 | end 232 | 233 | # 产物包下载完成标志 234 | flutter_package_downloaded = File.join(flutter_release_version_path, "download.ok") 235 | if !File.exist? flutter_package_downloaded 236 | has_version_file = false 237 | end 238 | 239 | if has_version_file == true 240 | # 解压 241 | flutter_package_path = unzip_release_flutter_app(flutter_release_version_path, flutter_release_zip_file) 242 | # 开始安装 243 | install_release_flutter_app_pod(flutter_package_path) 244 | else 245 | # 删除老文件 246 | FileUtils.rm_rf(flutter_release_zip_file) 247 | # 删除标志物 248 | FileUtils.rm_rf(flutter_package_downloaded) 249 | 250 | # 下载 251 | download_release_flutter_app(FLUTTER_APP_VERSION, flutter_release_zip_file, flutter_package_downloaded) 252 | # 解压 253 | flutter_package_path = unzip_release_flutter_app(flutter_release_version_path, flutter_release_zip_file) 254 | # 开始安装 255 | install_release_flutter_app_pod(flutter_package_path) 256 | end 257 | end 258 | 259 | if FLUTTER_DEBUG_APP.nil? || FLUTTER_DEBUG_APP == false 260 | # 使用 flutter release 模式 261 | puts "开始安装 release mode flutter app" 262 | install_release_flutter_app() 263 | else 264 | # 存在debug配置,使用 flutter debug 模式 265 | puts "开始安装 debug mode flutter app" 266 | install_debug_flutter_app() 267 | end 268 | -------------------------------------------------------------------------------- /Script/Maven/Native/maven.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | FILE_NAME="flutter.zip" 4 | FILE_PATH="xxx" 5 | VERSION="" 6 | MAVEN_PATH="http://xxx" 7 | MAVEN_USER="xxx:xxx" 8 | LOCAL_FILE_PATH="" 9 | 10 | throw () { 11 | echo "error: $*" >&2 12 | exit 1 13 | } 14 | 15 | usage() { 16 | echo 17 | echo "Usage: maven.sh [-h] [upload] [download]" 18 | echo 19 | echo "upload - Upload to maven. [e.g.]: ./maven.sh upload 1.0.0 localFile.zip" 20 | echo "download - Download from maven. [e.g.]: ./maven.sh download 1.0.1" 21 | echo "-h - This help text." 22 | echo 23 | } 24 | 25 | parse_options() { 26 | set -- "$@" 27 | local ARGN=$# 28 | while [ "$ARGN" -ne 0 ] 29 | do 30 | case $1 in 31 | -h) usage 32 | exit 0 33 | ;; 34 | upload) VERSION=$2 35 | LOCAL_FILE_PATH=$3 36 | upload 37 | ;; 38 | download) VERSION=$2 39 | download 40 | ;; 41 | ?*) echo "ERROR: Unknown option." 42 | usage 43 | exit 0 44 | ;; 45 | esac 46 | shift 1 47 | ARGN=$((ARGN-1)) 48 | done 49 | } 50 | 51 | upload() { 52 | if [ "$VERSION"x = ""x ]; then 53 | throw "version null" 54 | fi 55 | if [ "$LOCAL_FILE_PATH"x = ""x ]; then 56 | throw "file null" 57 | fi 58 | if ! [ -f $LOCAL_FILE_PATH ]; then 59 | throw "file $LOCAL_FILE_PATH not exist" 60 | fi 61 | echo 62 | echo "Uploading..." 63 | echo "$LOCAL_FILE_PATH -> $MAVEN_PATH/$FILE_PATH/$VERSION/$FILE_NAME" 64 | curl -u$MAVEN_USER -T $LOCAL_FILE_PATH "$MAVEN_PATH/$FILE_PATH/$VERSION/$FILE_NAME" 65 | echo 66 | echo "Done!" 67 | echo 68 | exit 0 69 | } 70 | 71 | download() { 72 | if [ "$VERSION"x = ""x ]; then 73 | throw "version null" 74 | fi 75 | echo 76 | echo "Downloading..." 77 | echo "$MAVEN_PATH/$FILE_PATH/$VERSION/$FILE_NAME" 78 | curl -u$MAVEN_USER -O "$MAVEN_PATH/$FILE_PATH/$VERSION/$FILE_NAME" 79 | echo "Done!" 80 | echo 81 | exit 0 82 | } 83 | 84 | if ([ "$0" = "$BASH_SOURCE" ] || ! [ -n "$BASH_SOURCE" ]); 85 | then 86 | parse_options "$@" 87 | usage 88 | exit 0 89 | fi 90 | -------------------------------------------------------------------------------- /Script/git/Flutter/build_ios.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | BUILD_MODE="debug" 4 | ARCHS_ARM="arm64,armv7" 5 | FLUTTER_ROOT=".flutter" 6 | PRODUCT_DIR="product" 7 | PRODUCT_ZIP="product.zip" 8 | FLUTTER_WRAPPER="./flutterw" 9 | 10 | BUILD_PATH=".build_ios/${BUILD_MODE}" 11 | PRODUCT_PATH="${BUILD_PATH}/${PRODUCT_DIR}" 12 | PRODUCT_APP_PATH="${PRODUCT_PATH}/Flutter" 13 | # git repository path 14 | PRODUCT_GIT_DIR="/xx/xx/x" 15 | 16 | usage() { 17 | echo 18 | echo "build_ios.sh [-h | [-m ] [-s]]" 19 | echo "" 20 | echo "-h - Help." 21 | echo "-m - Build model, valid values are 'debug', 'profile', or 'release'. " 22 | echo " Default values: 'debug'." 23 | echo "" 24 | echo "Build product in 'build_ios//${PRODUCT_DIR}' directory." 25 | echo 26 | } 27 | 28 | EchoError() { 29 | echo "$@" 1>&2 30 | } 31 | 32 | flutter_get_packages() { 33 | echo "=================================" 34 | echo "Start get flutter app plugin" 35 | 36 | if [ -e $FLUTTER_WRAPPER ]; then 37 | echo 'flutterw installed' >/dev/null 38 | else 39 | bash -c "$(curl -fsSL https://raw.githubusercontent.com/passsy/flutter_wrapper/master/install.sh)" 40 | if [[ $? -ne 0 ]]; then 41 | EchoError "Failed to installed flutter_wrapper." 42 | exit -1 43 | fi 44 | fi 45 | 46 | ${FLUTTER_WRAPPER} packages get --verbose 47 | if [[ $? -ne 0 ]]; then 48 | EchoError "Failed to install flutter plugins." 49 | exit -1 50 | fi 51 | 52 | echo "Finish get flutter app plugin" 53 | } 54 | 55 | build_flutter_app() { 56 | echo "=================================" 57 | echo "Start Build flutter app" 58 | echo "Build mode: ${BUILD_MODE}" 59 | 60 | mkdir -p -- "${PRODUCT_APP_PATH}" 61 | 62 | local target_path="lib/main.dart" 63 | 64 | local artifact_variant="unknown" 65 | case "$BUILD_MODE" in 66 | release*) 67 | artifact_variant="ios-release" 68 | ;; 69 | profile*) 70 | artifact_variant="ios-profile" 71 | ;; 72 | debug*) 73 | artifact_variant="ios" 74 | ;; 75 | *) 76 | EchoError "========================================================================" 77 | EchoError "ERROR: Unknown FLUTTER_BUILD_MODE: ${BUILD_MODE}." 78 | EchoError "Valid values are 'debug', 'profile', or 'release'." 79 | EchoError "This is controlled by the -m environment varaible." 80 | EchoError "========================================================================" 81 | exit -1 82 | ;; 83 | esac 84 | 85 | if [[ "${BUILD_MODE}" != "debug" ]]; then 86 | if [[ $ARCHS_ARM =~ .*i386.* || $ARCHS_ARM =~ .*x86_64.* ]]; then 87 | EchoError "========================================================================" 88 | EchoError "ERROR: Flutter does not support running in profile or release mode on" 89 | EchoError "the Simulator (this build was: '$BUILD_MODE')." 90 | EchoError "mode by setting '-m debug'" 91 | EchoError "========================================================================" 92 | exit -1 93 | fi 94 | 95 | echo "Build archs: ${ARCHS_ARM}" 96 | 97 | ${FLUTTER_WRAPPER} clean 98 | 99 | ${FLUTTER_WRAPPER} build ios --${BUILD_MODE} 100 | 101 | if [[ $? -ne 0 ]]; then 102 | EchoError "Failed to build flutter app" 103 | exit -1 104 | fi 105 | 106 | cp -r -- ".ios/Flutter/App.framework" "${BUILD_PATH}/App.framework" 107 | else 108 | echo "Build archs: x86_64 ${ARCHS_ARM}" 109 | local app_framework_debug="iOSApp/Debug/App.framework" 110 | cp -r -- "${app_framework_debug}" "${BUILD_PATH}" 111 | 112 | app_plist_path=".ios/Flutter/AppFrameworkInfo.plist" 113 | cp -- "${app_plist_path}" "${BUILD_PATH}/App.framework/Info.plist" 114 | 115 | local precompilation_flag="" 116 | if [[ "$BUILD_MODE" != "debug" ]]; then 117 | precompilation_flag="--precompiled" 118 | fi 119 | 120 | # build bundle 121 | ${FLUTTER_WRAPPER} --suppress-analytics \ 122 | --verbose \ 123 | build bundle \ 124 | --target-platform=ios \ 125 | --target="${target_path}" \ 126 | --${BUILD_MODE} \ 127 | --depfile="${BUILD_PATH}/snapshot_blob.bin.d" \ 128 | --asset-dir="${BUILD_PATH}/flutter_assets" \ 129 | ${precompilation_flag} 130 | 131 | if [[ $? -ne 0 ]]; then 132 | EchoError "Failed to build flutter assets" 133 | exit -1 134 | fi 135 | 136 | cp -rf -- "${BUILD_PATH}/flutter_assets" "${BUILD_PATH}/App.framework" 137 | fi 138 | 139 | # copy flutter sdk 140 | local framework_path="${FLUTTER_ROOT}/bin/cache/artifacts/engine/${artifact_variant}" 141 | local flutter_framework="${framework_path}/Flutter.framework" 142 | local flutter_podspec="${framework_path}/Flutter.podspec" 143 | 144 | cp -r -- "${BUILD_PATH}/App.framework" "${PRODUCT_APP_PATH}" 145 | cp -r -- "${flutter_framework}" "${PRODUCT_APP_PATH}" 146 | cp -r -- "${flutter_podspec}" "${PRODUCT_APP_PATH}" 147 | 148 | # setting podspec 149 | # replace: 150 | # 'Flutter.framework' 151 | # to: 152 | # 'Flutter.framework', 'App.framework' 153 | sed -i '' -e $'s/\'Flutter.framework\'/\'Flutter.framework\', \'App.framework\'/g' ${PRODUCT_APP_PATH}/Flutter.podspec 154 | 155 | echo "Finish build flutter app" 156 | } 157 | 158 | flutter_copy_packages() { 159 | echo "=================================" 160 | echo "Start copy flutter app plugin" 161 | 162 | local flutter_plugin_registrant="FlutterPluginRegistrant" 163 | local flutter_plugin_registrant_path=".ios/Flutter/${flutter_plugin_registrant}" 164 | echo "copy 'flutter_plugin_registrant' from '${flutter_plugin_registrant_path}' to '${PRODUCT_PATH}/${flutter_plugin_registrant}'" 165 | cp -rf -- "${flutter_plugin_registrant_path}" "${PRODUCT_PATH}/${flutter_plugin_registrant}" 166 | 167 | local flutter_plugin=".flutter-plugins" 168 | if [ -e $flutter_plugin ]; then 169 | OLD_IFS="$IFS" 170 | IFS="=" 171 | cat ${flutter_plugin} | while read plugin; do 172 | local plugin_info=($plugin) 173 | local plugin_name=${plugin_info[0]} 174 | local plugin_path=${plugin_info[1]} 175 | 176 | if [ -e ${plugin_path} ]; then 177 | local plugin_path_ios="${plugin_path}ios" 178 | if [ -e ${plugin_path_ios} ]; then 179 | if [ -s ${plugin_path_ios} ]; then 180 | echo "copy plugin 'plugin_name' from '${plugin_path_ios}' to '${PRODUCT_PATH}/${plugin_name}'" 181 | if [[ "${BUILD_MODE}" == "release" ]]; then 182 | cp -rf ${plugin_path_ios} "${PRODUCT_PATH}/${plugin_name}" 183 | else 184 | ln -s ${plugin_path_ios} "${PRODUCT_PATH}/${plugin_name}" 185 | fi 186 | fi 187 | fi 188 | fi 189 | done 190 | IFS="$OLD_IFS" 191 | fi 192 | 193 | echo "Finish copy flutter app plugin" 194 | } 195 | 196 | upload_product() { 197 | echo "=================================" 198 | echo "upload product" 199 | 200 | echo "${PRODUCT_PATH}" 201 | echo "${PRODUCT_GIT_DIR}" 202 | 203 | cp -r -f -- "${PRODUCT_PATH}/" "${PRODUCT_GIT_DIR}" 204 | 205 | local app_version=$(./get_version.sh) 206 | 207 | pushd ${PRODUCT_GIT_DIR} 208 | 209 | git add . 210 | git commit -m "Flutter product ${app_version}" 211 | git push 212 | 213 | popd 214 | } 215 | 216 | start_build() { 217 | 218 | rm -rf ${BUILD_PATH} 219 | 220 | flutter_get_packages 221 | 222 | build_flutter_app 223 | 224 | flutter_copy_packages 225 | 226 | if [[ "${BUILD_MODE}" == "release" ]]; then 227 | upload_product 228 | fi 229 | 230 | echo "" 231 | echo "done!" 232 | } 233 | 234 | show_help=0 235 | while getopts "m:sh" arg; do 236 | case $arg in 237 | m) 238 | BUILD_MODE="$OPTARG" 239 | ;; 240 | h) 241 | show_help=1 242 | ;; 243 | ?) 244 | show_help=1 245 | ;; 246 | esac 247 | done 248 | 249 | if [ $show_help == 1 ]; then 250 | usage 251 | exit 0 252 | fi 253 | 254 | BUILD_PATH=".build_ios/${BUILD_MODE}" 255 | PRODUCT_PATH="${BUILD_PATH}/${PRODUCT_DIR}" 256 | PRODUCT_APP_PATH="${PRODUCT_PATH}/Flutter" 257 | 258 | start_build 259 | 260 | exit 0 261 | -------------------------------------------------------------------------------- /Script/git/Flutter/get_version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | FILE_PATH="" 4 | FILE_PATH_DEF="./pubspec.yaml" 5 | # 过滤 version name 的正则表达式 6 | VERSION_NAME_REGEX="^version: " 7 | # 过滤 version code 的正则表达式 8 | VERSION_CODE_REGEX="^version_code: " 9 | 10 | throw () { 11 | echo "error: $*" >&2 12 | exit 1 13 | } 14 | 15 | usage() { 16 | echo 17 | echo "Usage: get_version.sh [-h] [--name] [--code] []" 18 | echo " [e.g.]: /get_version.sh // Get version name from def file ${FILE_PATH_DEF}." 19 | echo " [e.g.]: /get_version.sh --name example.txt // Get version name from the specified file." 20 | echo " [e.g.]: /get_version.sh --code example.txt // Get version code from the specified file." 21 | echo 22 | echo "--name - [Default] Get version name from the specified file, the def file is ${FILE_PATH_DEF}." 23 | echo "--code - Get version code from the specified file, the def file is ${FILE_PATH_DEF}." 24 | echo "-h - This help text." 25 | echo 26 | } 27 | 28 | parse_options() { 29 | set -- "$@" 30 | local ARGN=$# 31 | while [ "$ARGN" -ne 0 ] 32 | do 33 | case $1 in 34 | -h) usage 35 | exit 0 36 | ;; 37 | --name) FILE_PATH=$2 38 | get_version_name 39 | ;; 40 | --code) FILE_PATH=$2 41 | get_version_code 42 | ;; 43 | ?*) echo "ERROR: Unknown option." 44 | usage 45 | exit 0 46 | ;; 47 | esac 48 | shift 1 49 | ARGN=$((ARGN-1)) 50 | done 51 | } 52 | 53 | get_version_name() { 54 | get_file 55 | #echo "get version name from ${FILE_PATH} ..." 56 | version_name=`egrep ${VERSION_NAME_REGEX} ${FILE_PATH}` 57 | # 取`:`右边 58 | version_name=`echo ${version_name} | sed 's/^.*://g'` 59 | # 删除`;` 60 | version_name=`echo ${version_name} | sed 's/;.*$//g'` 61 | # 删除`"` 62 | version_name=`echo ${version_name} | sed 's/\"//g'` 63 | # 删除`'` 64 | version_name=`echo ${version_name} | sed "s/\'//g"` 65 | #echo "version name: 【${version_name}】" 66 | echo ${version_name} 67 | finish 68 | } 69 | 70 | get_version_code() { 71 | get_file 72 | #echo "get version code from ${FILE_PATH} ..." 73 | version_code=`egrep ${VERSION_CODE_REGEX} ${FILE_PATH}` 74 | # 取`:`右边 75 | version_code=`echo ${version_code} | sed 's/^.*://g'` 76 | # 删除`;` 77 | version_code=`echo ${version_code} | sed 's/;.*$//g'` 78 | #echo "version code: 【${version_code}】" 79 | echo ${version_code} 80 | finish 81 | } 82 | 83 | get_file() { 84 | if [ "$FILE_PATH"x = ""x ]; then 85 | FILE_PATH=${FILE_PATH_DEF} 86 | fi 87 | } 88 | 89 | finish() { 90 | exit 0 91 | } 92 | 93 | default_action() { 94 | get_version_name 95 | } 96 | 97 | if ([ "$0" = "$BASH_SOURCE" ] || ! [ -n "$BASH_SOURCE" ]); 98 | then 99 | parse_options "$@" 100 | default_action 101 | fi 102 | -------------------------------------------------------------------------------- /Script/git/Flutter/iOSApp/debug/App.framework/App: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CaffreySun/iOS_Flutter_Hybrid_Project/768167a3c3ae38191e28d20d66b83cd85ea52197/Script/git/Flutter/iOSApp/debug/App.framework/App -------------------------------------------------------------------------------- /Script/git/Native/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'TestMoreFlutter' do 5 | # Uncomment the next line if you're using Swift or would like to use dynamic frameworks 6 | # use_frameworks! 7 | 8 | # Pods for TestMoreFlutter 9 | 10 | end 11 | 12 | 13 | # 是否进行调试 flutter app, 14 | # 为false时,为使用产物的方式从下面git地址拉取产物 15 | # 为true时,为使用源码的方式从下面git地址拉取源码 16 | FLUTTER_DEBUG_APP=false 17 | 18 | # Flutter App git地址,从git拉取的内容放在当前工程目录下的.flutter/app目录 19 | # 如果指定了FLUTTER_APP_PATH,则此配置失效 20 | FLUTTER_APP_URL="gut://xxx.git" 21 | # flutter git 分支,默认为master 22 | # 如果指定了FLUTTER_APP_PATH,则此配置失效 23 | FLUTTER_APP_BRANCH="master" 24 | 25 | # flutter本地工程目录,绝对路径或者相对路径, 26 | # FLUTTER_DEBUG_APP == true时才有效,如果 != nil 则git相关的配置无效 27 | FLUTTER_APP_PATH=nil 28 | 29 | eval(File.read(File.join(__dir__, 'flutterhelper.rb')), binding) -------------------------------------------------------------------------------- /Script/git/Native/flutterhelper.rb: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # 3 | # 脚本使用方式: 4 | # 你需要在 Podfile 添加以下=begin =end 之间的内容: 5 | =begin 6 | 7 | # 是否进行调试 flutter app, 8 | # 为true时,为使用产物的方式从下面git地址拉取产物 9 | # 为false时,为使用源码的方式从下面git地址拉取源码 10 | FLUTTER_DEBUG_APP=false 11 | 12 | # Flutter App git地址,从git拉取的内容放在当前工程目录下的.flutter/app目录 13 | # 如果指定了FLUTTER_APP_PATH,则此配置失效 14 | FLUTTER_APP_URL="gut://xxx.git" 15 | # flutter git 分支,默认为master 16 | # 如果指定了FLUTTER_APP_PATH,则此配置失效 17 | FLUTTER_APP_BRANCH="master" 18 | 19 | # flutter本地工程目录,绝对路径或者相对路径, 20 | # FLUTTER_DEBUG_APP == false时才有效,如果 != nil 则git相关的配置无效 21 | FLUTTER_APP_PATH=nil 22 | 23 | eval(File.read(File.join(__dir__, 'flutterhelper.rb')), binding) 24 | 25 | =end 26 | # 27 | ############################################################################## 28 | 29 | # 拉取代码方法 30 | def update_flutter_app(path, url, branche) 31 | # 如果flutter项目不存在,则clone 32 | if !File.exist?(path) 33 | `git clone #{url} #{path}` 34 | end 35 | `cd #{path} && git fetch --all -v && \ 36 | git reset --hard origin/master && \ 37 | git pull && \ 38 | git checkout -B #{branche} origin/#{branche}` 39 | end 40 | 41 | # 安装开发环境app 42 | def install_debug_flutter_app 43 | 44 | puts "如果是第一次运行开发环境Flutter项目,此过程可能会较慢" 45 | puts "请耐心等️待☕️️️️️☕️☕️\n" 46 | 47 | # 默认Flutter App 目录 48 | flutter_application_path = __dir__ + "/.flutter/app" 49 | flutter_application_url = "" 50 | flutter_application_branch = 'master' 51 | 52 | if FLUTTER_APP_PATH != nil 53 | File.expand_path(FLUTTER_APP_PATH) 54 | if File.exist?(FLUTTER_APP_PATH) 55 | flutter_application_path = FLUTTER_APP_PATH 56 | else 57 | flutter_application_path = File.expand_path(FLUTTER_APP_PATH) 58 | if !File.exist?(flutter_application_path) 59 | raise "Error: #{FLUTTER_APP_PATH} 地址不存在!" 60 | end 61 | end 62 | 63 | puts "\nFlutter App路径: "+flutter_application_path 64 | else 65 | if FLUTTER_APP_URL != nil 66 | flutter_application_url = FLUTTER_APP_URL 67 | if FLUTTER_APP_BRANCH != nil 68 | flutter_application_branch = FLUTTER_APP_BRANCH 69 | end 70 | else 71 | raise "Error: 请在'Podfile'里增加Flutter App git地址配置,配置格式请查看'flutterhelper.rb'文件" 72 | end 73 | puts "\n拉取 Flutter App 代码" 74 | puts "Flutter App路径: "+flutter_application_path 75 | update_flutter_app(flutter_application_path, flutter_application_url, flutter_application_branch) 76 | end 77 | 78 | puts "\n编译 Flutter App" 79 | `export PUB_HOSTED_URL=https://pub.flutter-io.cn && \ 80 | export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn && \ 81 | cd #{flutter_application_path} && \ 82 | #{flutter_application_path}/build_ios.sh -m debug` 83 | 84 | if $?.to_i == 0 85 | flutter_package_path = "#{flutter_application_path}/.build_ios/debug/product" 86 | # 开始安装 87 | install_release_flutter_app_pod(flutter_package_path) 88 | else 89 | raise "Error: 编译 Flutter App失败" 90 | end 91 | end 92 | 93 | # 将 Flutter app 通过 pod 安装 94 | def install_release_flutter_app_pod(product_path) 95 | if product_path.nil? 96 | raise "Error: 无效的 flutter app 目录" 97 | end 98 | 99 | puts "将 flutter app 通过 pod 导入到 工程" 100 | 101 | Dir.foreach product_path do |sub| 102 | # 忽略隐藏文件 103 | if sub =~ /\.(.*)/ 104 | next 105 | end 106 | 107 | sub_abs_path = File.realpath(File.join(product_path, sub)) 108 | pod sub, :path=>sub_abs_path 109 | end 110 | 111 | post_install do |installer| 112 | installer.pods_project.targets.each do |target| 113 | target.build_configurations.each do |config| 114 | config.build_settings['ENABLE_BITCODE'] = 'NO' 115 | end 116 | end 117 | end 118 | end 119 | 120 | # 安装正式环境环境app 121 | def install_release_flutter_app 122 | if FLUTTER_APP_URL.nil? 123 | raise "Error: 请在 Podfile 里设置要安装的 Flutter app 的产物地址 ,例如:FLUTTER_APP_URL='git://xxx'" 124 | end 125 | 126 | flutter_app_url = FLUTTER_APP_URL 127 | 128 | # 存放产物的目录 129 | flutter_release_path = File.expand_path('.flutter_release') 130 | 131 | flutter_app_branch = FLUTTER_APP_BRANCH 132 | 133 | if FLUTTER_APP_BRANCH.nil? 134 | flutter_app_branch = "master" 135 | end 136 | 137 | update_flutter_app(flutter_release_path, flutter_app_url, flutter_app_branch) 138 | 139 | # 开始安装 140 | install_release_flutter_app_pod(flutter_release_path) 141 | end 142 | 143 | if FLUTTER_DEBUG_APP.nil? || FLUTTER_DEBUG_APP == false 144 | # 使用 flutter release 模式 145 | puts "开始安装 release mode flutter app" 146 | install_release_flutter_app() 147 | else 148 | # 存在debug配置,使用 flutter debug 模式 149 | puts "开始安装 debug mode flutter app" 150 | install_debug_flutter_app() 151 | end 152 | --------------------------------------------------------------------------------