Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

debug正常,但是release无法加载网页 #154

Open
aazainn opened this issue Oct 17, 2024 · 6 comments
Open

debug正常,但是release无法加载网页 #154

aazainn opened this issue Oct 17, 2024 · 6 comments

Comments

@aazainn
Copy link

aazainn commented Oct 17, 2024

所加载的页面使用此开源仓库配合shelf_static搭建:全景图的库mpetroff/pannellum
环境如下:

C:\Users\xxx>flutter doctor
Flutter assets will be downloaded from https://storage.flutter-io.cn. Make sure you trust this source!
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.24.3, on Microsoft Windows [版本 10.0.22631.4317], locale zh-CN)
[✓] Windows Version (Installed version of Windows is version 10 or higher)
[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
[✓] Chrome - develop for the web
[✓] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.11.1)
[✓] Android Studio (version 2024.1)
[✓] IntelliJ IDEA Ultimate Edition (version 2023.3)
[✓] VS Code (version 1.94.2)
[✓] Connected device (3 available)
[✓] Network resources

• No issues found!

打包成release后,打开exe页面呈灰白色,感觉像卡死状态。但是通过--debug打包是可以正常打开的

@SinyimZhi
Copy link
Collaborator

release模式下加载别的网页正常吗?

@aazainn
Copy link
Author

aazainn commented Oct 17, 2024

release模式下加载别的网页正常吗?

试了一下,打开bing.com也不行。稍后我附上代码

@aazainn
Copy link
Author

aazainn commented Oct 17, 2024

附上全部代码(3个资源文件不重要,直接拿bing.com测试就行),运行 flutter build windows --debug 可以正常加载bing.com,运行 flutter build windows 出来的exe执行后如下:
image
再附上一张debug正常的图吧:
image

pubspec.yaml

environment:
  sdk: ^3.5.3

# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies:
  flutter:
    sdk: flutter
  # https://pub-web.flutter-io.cn/packages/get
  get: ^4.6.6
  # https://pub-web.flutter-io.cn/packages/window_manager
  window_manager: ^0.4.2
  # https://pub-web.flutter-io.cn/packages/webview_cef
  webview_cef: ^0.2.0
  # https://pub-web.flutter-io.cn/packages/file_picker
  file_picker: ^8.1.2
  # https://pub-web.flutter-io.cn/packages/shelf
  shelf: ^1.4.1
  # https://pub-web.flutter-io.cn/packages/shelf_static
  shelf_static: ^1.1.3

lib/utils.dart

import 'dart:io';

import 'package:get/get.dart';

extension StringExt on String? {
  String? code() {
    final str = this;
    if (str == null || str.isEmpty) return str;
    try {
      return Uri.encodeFull(str);
    } catch (e) {
      e.printError();
      return null;
    }
  }

  /// toast一个字符串
  void toast([int duration = 1]) async {
    if (this?.isNotEmpty == true) {
      if (SnackbarController.isSnackbarBeingShown) {
        try {
          await SnackbarController.closeCurrentSnackbar();
        } catch (e) {
          e.printError();
        }
      }
      Get.showSnackbar(GetSnackBar(
        message: this,
        duration: Duration(seconds: duration),
      ));
    }
  }
}

extension FileExt on File {
  String name() {
    final up = parent.path;
    return path.replaceFirst(up, '').substring(1);
  }
}

lib/main.dart

import 'dart:io';
import 'dart:math';

import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:quan_jing_tu/utils.dart';
import 'package:webview_cef/webview_cef.dart';
import 'package:window_manager/window_manager.dart';
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_static/shelf_static.dart';

const _staticDir = 'static';
const _imageDir = '$_staticDir/images';
const _maxPort = 9999;
const _domain = 'localhost';
var port = 8080;

HttpServer? _server;

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await windowManager.ensureInitialized();

  await _copyassetsPannellumFromAssets('pannellum.css');
  await _copyassetsPannellumFromAssets('pannellum.htm');
  await _copyassetsPannellumFromAssets('pannellum.js');
  await _copyassetsPannellumFromAssets('index.html');

  var testing = true;
  while (testing && port < _maxPort) {
    try {
      debugPrint('try serve: $port');
      var handler =
          createStaticHandler(_staticDir, defaultDocument: 'pannellum.htm');
      _server = await io.serve(handler, _domain, port);
      testing = false;
    } catch (ex) {
      debugPrint('serve error $ex');
      port++;
      testing = true;
    }
  }
  runApp(const MyApp());
}

Future<void> _copyassetsPannellumFromAssets(name) async {
  final dir = Directory(_staticDir);
  if (!dir.existsSync()) dir.createSync(recursive: true);
  final to = File('${dir.path}/$name');
  if (to.existsSync()) return;
  try {
    final bytes = await rootBundle.load('assets/pannellum/$name');
    await to.writeAsBytes(bytes.buffer.asUint8List());
  } catch (ex) {
    debugPrint('copy error $ex');
  }
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with WindowListener {
  WebViewController? _controller;
  final _imageList = <String>[];

  void _incrementCounter() async {
    // _controller?.loadUrl('https://www.bing.com');
    FilePickerResult? result = await FilePicker.platform
        .pickFiles(allowMultiple: true, type: FileType.image);
    if (result != null) {
      var index = 0;
      List<File> files = result.paths.map((path) => File(path!)).toList();
      debugPrint('files = $files');
      files.where((f) {
        final name = f.path.toLowerCase();
        return name.endsWith('.jpg') || name.endsWith(".jepg");
      }).forEach((f) {
        final dir = Directory(_imageDir);
        if (!dir.existsSync()) dir.createSync(recursive: true);
        final pre = '${DateTime.now().millisecondsSinceEpoch}_${index++}';
        final to = File('${dir.path}/$pre-${f.name()}');
        debugPrint('to = $to');
        f.copySync(to.path);
      });
      _loadImages();
    } else {
      '未选择文件'.toast();
    }
  }

  @override
  void initState() {
    windowManager.addListener(this);
    _controller =
        WebviewManager().createWebView(loading: const Text("not initialized"));
    super.initState();
    initPlatformState();
  }

  @override
  void dispose() {
    super.dispose();
    windowManager.removeListener(this);
  }

  @override
  void onWindowClose() async {
    try {
      _controller?.dispose();
      WebviewManager().quit();
    } catch (ex) {
      debugPrint('close webview error: $ex');
    }
    try {
      _server?.close(force: true);
    } catch (ex) {
      debugPrint('close server error: $ex');
    }
    try {
      final dir = Directory(_imageDir);
      if (dir.existsSync()) {
        dir.deleteSync(recursive: true);
      }
    } catch (ex) {
      debugPrint('delete images error: $ex');
    }
  }

  Future<void> initPlatformState() async {
    await WebviewManager().initialize(userAgent: "test/userAgent");

    _controller?.setWebviewListener(WebviewEventsListener());

    await _controller?.initialize('https://www.bing.com');

    await _loadImages();
  }

  Future<void> _loadImages() async {
    final dir = Directory(_imageDir);
    if (!dir.existsSync()) {
      dir.createSync(recursive: true);
    } else {
      final files = dir.listSync();
      final list =
          files.map((f) => File(f.path).name()).map((p) => 'images/$p');
      _imageList.clear();
      _imageList.addAll(list);
      setState(() {
        if (_imageList.isNotEmpty) {
          _controller?.loadUrl(
              'http://$_domain:$port?panorama=${_imageList[0]}&autoLoad=true&minHfov=10&hfov=110&maxHfov=120');
        }
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          ValueListenableBuilder(
            valueListenable: _controller!,
            builder: (context, value, child) {
              return _controller!.value
                  ? Expanded(child: _controller!.webviewWidget)
                  : _controller!.loadingWidget;
            },
          ),
          Opacity(
            opacity: 0.5, // 设置透明度为 50%
            child: Align(
              alignment: Alignment.bottomCenter, // 底部居中
              child: Container(
                constraints: const BoxConstraints(
                  maxHeight: 100, // 设置最小高度
                ),
                child: ListView.builder(
                  shrinkWrap: true,
                  itemCount: _imageList.length,
                  itemBuilder: (ctx, index) {
                    return InkWell(
                      onTap: () {
                        _controller?.loadUrl(
                            'http://$_domain:$port?panorama=${_imageList[index]}&autoLoad=true&minHfov=10&hfov=110&maxHfov=120');
                      },
                      child: Container(
                        width: 100,
                        height: 100,
                        margin: const EdgeInsets.symmetric(horizontal: 5),
                        child: Image.network(
                            'http://$_domain:$port/${_imageList[index]}'),
                      ),
                    );
                  },
                  scrollDirection: Axis.horizontal,
                ),
              ),
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

@xuyf455487
Copy link

这个问题解决了吗?我现在也遇到和你一样的问题

@aazainn
Copy link
Author

aazainn commented Nov 8, 2024

这个问题解决了吗?我现在也遇到和你一样的问题

目前没解决,我打包debug版给别人用了……
上述代码中,有一个

MaterialApp(
      debugShowCheckedModeBanner: false
)

是用来隐藏debug标志的。然后打包出来的包,运行时会缺一些 xxx_d.dll,这些dll无法通过安装vs运行库解决,因为都是debug的。所以需要在自己电脑上提取后,在安装时将dll放到目标电脑的system32目录

@xuyf455487
Copy link

谢谢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants