Flutter搭建环境的下载Gradle Wrapper的问题的一个解决方式

Flutter搭建环境的下载Gradle Wrapper的问题的一个解决方式

按照https://flutter.io/或者https://codelabs.developers.google.com/codelabs/flutter/#1的步骤搭建环境:

flutter doctor: 编译源码,下载依赖

Building flutter tool...
Downloading Material fonts...                         0.7s
Downloading package sky_engine...                     0.6s
Downloading common tools...                           1.0s
Downloading darwin-x64 tools...                       8.3s
Downloading darwin-x64 tools...                       8.9s
Downloading android-arm-profile/darwin-x64 tools...   1.8s
Downloading android-arm-release/darwin-x64 tools...   1.0s
Downloading android-x86 tools...                      4.1s
Downloading android-x64 tools...                      4.2s
Downloading android-arm tools...                      2.1s
Downloading android-arm-profile tools...              1.6s
Downloading android-arm-release tools...              1.7s
Downloading ios tools...                              6.9s
Downloading ios-profile tools...                      5.4s
Downloading ios-release tools...                      7.4s
Downloading Gradle Wrapper...

结果在bin/cache目录下生成了:

artifacts
dart-sdk
dart-sdk.stamp
engine.stamp
flutter_tools.snapshot
flutter_tools.stamp
lockfile
material_fonts.stamp
pkg

这一步卡住了:Downloading Gradle Wrapper…

SocketException: SocketException: Connection failed (OS Error: No route to host, errno = 65), address = android.googlesource.com, port = 443

或者其他错误,总之原因就是连接不上android.googlesource.com(但是浏览器却可以打开)

于是查到这些文章:

https://github.com/getlantern/forum/issues/29
https://github.com/getlantern/lantern/issues/3341
http://www.jianshu.com/p/411a60f415a5

无论是设置(Lantern):

export http_proxy=127.0.0.1:61537
export https_proxy=127.0.0.1:61538

还是设置(Shadowsocks):

export http_proxy=socks5://127.0.0.1:1080
export https_proxy=$http_proxy

结果是:

curl https://android.googlesource.com/

没有问题,但是

curl https://www.google.com/

出错:Server aborted the SSL handshake。并且flutter doctor依旧出错(仍然是https://android.googlesource.com/无法访问;但是https://storage.googleapis.com/flutter_infra/flutter/$version/却可以访问)。

于是查看log:

SocketException: SocketException: Connection failed (OS Error: No route to host, errno = 65), address = android.googlesource.com, port = 443
 10
 11 ```
 12 #0      fetchUrl (package:flutter_tools/src/base/net.dart:18)
 13 
 14 #1      _downloadFile (package:flutter_tools/src/cache.dart:408)
 15 
 16 #2      _downloadZippedTarball. (package:flutter_tools/src/cache.dart:424)
 17 
 18 #3      _withTemporaryFile (package:flutter_tools/src/cache.dart:436)
 19 
 20 #4      _downloadZippedTarball (package:flutter_tools/src/cache.dart:423)
 21 #5      GradleWrapper.updateInner (package:flutter_tools/src/cache.dart:397)
 22 
 23 #6      CachedArtifact.update (package:flutter_tools/src/cache.dart:223)
 24 
 25 #7      Cache.updateAll (package:flutter_tools/src/cache.dart:196)
 26 
 27 #8      FlutterCommand.verifyThenRunCommand (package:flutter_tools/src/runner/flutter_command.dart:225)
 28 
 29 #9      FlutterCommand.run (package:flutter_tools/src/runner/flutter_command.dart:181)
 30 
 31 #10     CommandRunner.runCommand (package:args/command_runner.dart:194)
 32 
 33 #11     FlutterCommandRunner.runCommand (package:flutter_tools/src/runner/flutter_command_runner.dart:276)
 34 
 35 #12     CommandRunner.run. (package:args/command_runner.dart:109)
 36 #13     new Future.sync (dart:async/future.dart:222)
 37 #14     CommandRunner.run (package:args/command_runner.dart:109)
 38 #15     FlutterCommandRunner.run (package:flutter_tools/src/runner/flutter_command_runner.dart:161)
 39 #16     run. (package:flutter_tools/executable.dart:143)
 40 
 41 #17     AppContext._run (package:flutter_tools/src/base/context.dart:76)
 42 
 43 #18     AppContext.runInZone. (package:flutter_tools/src/base/context.dart:66)
 44 #19     _rootRun (dart:async/zone.dart:1120)
 45 #20     _CustomZone.run (dart:async/zone.dart:1001)
 46 #21     runZoned (dart:async/zone.dart:1467)
 47 #22     AppContext.runInZone (package:flutter_tools/src/base/context.dart:65)
 48 #23     run (package:flutter_tools/executable.dart:114)

于是打开源文件修改:packages/flutter_tools/lib/src/cache.dart:

   bool isUpToDate() {
    ////////////////////////////////////////这些log是我加上的////////////////////////////////////////
    var stamp = cache.getStampFor(name);
    // logger.writeToStdOut
    logger.writeToStdOut('\n==============isUpToDate? location, version, getStampFor: ');
    logger.writeToStdOut('\nname: ');
    logger.writeToStdOut( name );

    logger.writeToStdOut('\nlocation: ');
    logger.writeToStdOut( location.path );
    logger.writeToStdOut('\nversion: ');
    logger.writeToStdOut( version );
    logger.writeToStdOut('\nstamp: ');
    logger.writeToStdOut( stamp);
    logger.writeToStdOut('\n');
    ////////////////////////////////////////////这些log是我加上的////////////////////////////////////

     if (!location.existsSync()) {
        // 目标文件夹是否存在,不存在去下载
       logger.writeToStdOut('\nlocation not exists');
       return false;
     }
     if (version != cache.getStampFor(name)) {
        // 目标文件夹存在,检查version的stamp(理解为版本号)是否与version相同,不同就去下载
       logger.writeToStdOut('\nStamp not match');
       return false;
     }
     // 默认一直下载
     return isUpToDateInner();
   }


   /// Download a file from the given [url] and write it to [location].
   Future _downloadFile(Uri url, File location) async {
     _ensureExists(location.parent);
     ////////////////////////////////////////////这些log是我加上的////////////////////////////////////
     logger.writeToStdOut('\n_downloadFile path : ' + location.path);
     ////////////////////////////////////////////这些log是我加上的////////////////////////////////////

     final List<int> fileBytes = await fetchUrl(url);

     location.writeAsBytesSync(fileBytes, flush: true);
   }

   /// Download a zip archive from the given [url] and unzip it to [location].
   Future _downloadZipArchive(Uri url, Directory location) {
       ////////////////////////////////////////////这些log是我加上的////////////////////////////////////
    logger.writeToStdOut('\n_downloadZip : ' + location.path);
        ////////////////////////////////////////////这些log是我加上的////////////////////////////////////
     return _withTemporaryFile('download.zip', (File tempFile) async {

       await _downloadFile(url, tempFile);
       _ensureExists(location);
       os.unzip(tempFile, location);
     });
   }

   /// Download a gzipped tarball from the given [url] and unpack it to [location].
   Future _downloadZippedTarball(Uri url, Directory location) {
       ////////////////////////////////////////////这些log是我加上的////////////////////////////////////
    logger.writeToStdOut('\n_downloadZipped:' + location.path);
        ////////////////////////////////////////////这些log是我加上的////////////////////////////////////
   return _withTemporaryFile('download.tgz', (File tempFile) async {
       await _downloadFile(url, tempFile);
       _ensureExists(location);
       os.unpack(tempFile, location);
     });
   }

做了些修改,发现里面的逻辑很简单:

  Future updateAll() async {
    if (!_lockEnabled)
      return null;
    for (CachedArtifact artifact in _artifacts) {
      if (!artifact.isUpToDate())
      // 如果需要更新,那么更新
        await artifact.update();
    }
  }

artifact.update里面的逻辑就是检查文件是否存在、版本是否一致,满足条件,就不用更新,否则下载。下载的逻辑就是先下载到一个临时目录,然后解压到bin/cache,并且创建一个xxx.stamp文件记录版本号。

然后删除bin/cache目录下的flutter_tools.stamp和flutter_tools.snapshot,再次执行flutter doctor:

==============isUpToDate? location, version, getStampFor:
name: material_fonts
location: /Users/wangshenglong/flutter/bin/cache/artifacts/material_fonts
version: https://storage.googleapis.com/flutter_infra/flutter/fonts/13ac995daa9dda0a6ba0a45f1fccc541e616a74c/fonts.zip
stamp: https://storage.googleapis.com/flutter_infra/flutter/fonts/13ac995daa9dda0a6ba0a45f1fccc541e616a74c/fonts.zip

==============isUpToDate? location, version, getStampFor:
name: engine
location: /Users/wangshenglong/flutter/bin/cache/artifacts/engine
version: 31d03de019794a4b0e3c98c04cf7be501fb962fb
stamp: 31d03de019794a4b0e3c98c04cf7be501fb962fb

==============isUpToDate? location, version, getStampFor:
name: gradle_wrapper
location: /Users/wangshenglong/flutter/bin/cache/artifacts/gradle_wrapper
version: 0b5c1398d1d04ac245a310de98825cb7b3278e2a
stamp: null
Downloading Gradle Wrapper...https://android.googlesource.com/platform/tools/base/+archive/0b5c1398d1d04ac245a310de98825cb7b3278e2a/templates/gradle/wrapper.tgz     -
_downloadZipped:/Users/wangshenglong/flutter/bin/cache/artifacts/gradle_wrapper
_downloadFile path : /var/folders/qx/yr3zc94x2sbf16ptpv5v5_tr0000gn/T/7XQy4z/download.tgz

所以,解决问题就简单了:

1.浏览器下载https://android.googlesource.com/platform/tools/base/+archive/0b5c1398d1d04ac245a310de98825cb7b3278e2a/templates/gradle/wrapper.tgz,解压到flutter/bin/cache/artifacts/gradle_wrapper
目录下;

2.在flutter/bin/cache/下创建gradle_wrapper.stamp文件,写入内容0b5c1398d1d04ac245a310de98825cb7b3278e2a。完成。

再次运行flutter doctor:

==============isUpToDate? location, version, getStampFor:
name: material_fonts
location: /Users/wangshenglong/flutter/bin/cache/artifacts/material_fonts
version: https://storage.googleapis.com/flutter_infra/flutter/fonts/13ac995daa9dda0a6ba0a45f1fccc541e616a74c/fonts.zip
stamp: https://storage.googleapis.com/flutter_infra/flutter/fonts/13ac995daa9dda0a6ba0a45f1fccc541e616a74c/fonts.zip

==============isUpToDate? location, version, getStampFor:
name: engine
location: /Users/wangshenglong/flutter/bin/cache/artifacts/engine
version: 31d03de019794a4b0e3c98c04cf7be501fb962fb
stamp: 31d03de019794a4b0e3c98c04cf7be501fb962fb

==============isUpToDate? location, version, getStampFor:
name: gradle_wrapper
location: /Users/wangshenglong/flutter/bin/cache/artifacts/gradle_wrapper
version: 0b5c1398d1d04ac245a310de98825cb7b3278e2a
stamp: 0b5c1398d1d04ac245a310de98825cb7b3278e2a
[✓] Flutter (on Mac OS X 10.11.2 15C50, locale zh-Hans, channel alpha)
    • Flutter at /Users/wangshenglong/flutter
    • Framework revision 701d534ba9 (7 days ago), 2017-09-12 14:01:51 -0700
    • Engine revision 31d03de019
    • Tools Dart version 1.25.0-dev.11.0

[✓] Android toolchain - develop for Android devices (Android SDK 25.0.3)
    • Android SDK at /Users/wangshenglong/Documents/DevSoftware/Android_Studio
    • Platform android-25, build-tools 25.0.3
    • ANDROID_HOME = /Users/wangshenglong/Documents/DevSoftware/Android_Studio
    • Java binary at: /Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/bin/java
    • Java version Java(TM) SE Runtime Environment (build 1.7.0_79-b15)

[-] iOS toolchain - develop for iOS devices (Xcode 7.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 7.3, Build version 7D175
    ✗ Flutter requires a minimum Xcode version of 8.0.0.
      Download the latest version or update via the Mac App Store.
    ✗ libimobiledevice and ideviceinstaller are not installed or require updating. To update, run:
        brew uninstall --ignore-dependencies libimobiledevice
        brew install --HEAD libimobiledevice
        brew install ideviceinstaller
    ✗ ios-deploy not installed. To install:
        brew install ios-deploy
    ✗ CocoaPods not installed.
        CocoaPods is used to retrieve the iOS platform side's plugin code that responds to your plugin usage on the Dart side.
        Without resolving iOS dependencies with CocoaPods, plugins will not work on iOS.
        For more info, see https://flutter.io/platform-plugins
      To install:
        brew install cocoapods
        pod setup

[✗] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.io/setup/#android-setup for detailed instructions).

[✓] IntelliJ IDEA Ultimate Edition (version 2017.2.4)
    • Flutter plugin version 17.0
    • Dart plugin version 172.4155.35

[✓] Connected devices
    • Samsung Galaxy S6, 6 0 0, API 23, 1440x2560 • 192.168.62.101:5555 • android-x86 • Android 6.0 (API 23)

大功告成。

附录:

1.logger的用法我也不知道,但是packages/flutter_tools/lib/src/base/logger.dart有源文件,于是就知道了用法:printError,printStatus,writeToStdOut,printTrace,startProgress。

2.File.path我也不知道,于是google,找到https://www.dartlang.org/dart-vm/dart-by-example,查下api就知道了。

你可能感兴趣的:(android)