Flutter windows 使用指定浏览器打开指定网址。
以 打开Chrome为例 :我们需要三步走
1、找到注册表的应用程序安装路径。
参考文献:zhidao.baidu.com/question/73…
第一次尝试使用的注册表地址是
Software\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome
发现部分电脑装了chrome 但是在这个路径下面没有找到 chrome的安装路径
最终使用的是
Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\MuiCache
研究表明,此路径下的大部分电脑都是可以找到相应的应用程序安装路径。
2、使用win32第三方库、从注册表获取Chrome安装路径。
win32这个库、就是给Flutter调用windows API 使用的。 自行 pub.dev 查看。
添加依赖之后、可以创建一个dart文件, 专门用于获取注册表信息。 例如我的...
import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'package:win32/win32.dart';
// 注册表应用程序安装路径
const regChromeKey =
r'Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\MuiCache';
const MAX_ITEMLENGTH = 1024;
class RegistryKeyValuePair {
final String key;
final String value;
const RegistryKeyValuePair(this.key, this.value);
}
int getRegistryKeyHandle(int hive, String key) {
final phKey = calloc<HANDLE>();
final lpKeyPath = key.toNativeUtf16();
try {
if (RegOpenKeyEx(hive, lpKeyPath, 0, KEY_READ, phKey) != ERROR_SUCCESS) {
throw Exception("Can't open registry key");
}
return phKey.value;
} finally {
free(phKey);
free(lpKeyPath);
}
}
RegistryKeyValuePair? enumerateKey(int hKey, int index) {
final lpValueName = wsalloc(MAX_PATH);
final lpcchValueName = calloc<DWORD>()..value = MAX_PATH;
final lpType = calloc<DWORD>();
final lpData = calloc<BYTE>(MAX_ITEMLENGTH);
final lpcbData = calloc<DWORD>()..value = MAX_ITEMLENGTH;
try {
final status = RegEnumValue(hKey, index, lpValueName, lpcchValueName,
nullptr, lpType, lpData, lpcbData);
switch (status) {
case ERROR_SUCCESS:
if (lpType.value != REG_SZ) throw Exception('Non-string content.');
return RegistryKeyValuePair(
lpValueName.toDartString(), lpData.cast<Utf16>().toDartString());
case ERROR_MORE_DATA:
throw Exception('An item required more than $MAX_ITEMLENGTH bytes.');
case ERROR_NO_MORE_ITEMS:
return null;
default:
throw Exception('unknown error');
}
} finally {
free(lpValueName);
free(lpcchValueName);
free(lpType);
free(lpData);
free(lpcbData);
}
}
调用
// 获取 chrome 安装路径
static String getChromePath() {
String chromePath = "";
var hKey;
var dwIndex = 1;
RegistryKeyValuePair? item;
try {
hKey = getRegistryKeyHandle(HKEY_CURRENT_USER, regChromeKey);
item = enumerateKey(hKey, dwIndex);
} catch (e) {
return "";
}
while (item != null) {
if (item.key.isNotEmpty && item.key.contains("chrome.exe")) {
chromePath = item.key;
break;
}
dwIndex++;
try {
item = enumerateKey(hKey, dwIndex);
} catch (e) {
return "";
}
}
return chromePath;
}
结束、调用方法即可获取 chrome 安装路径
3、使用C++调用 cmd 打开chrome 并打开指定网址
Flutter 吗。大家都知道的写windows,很多API还是要考C++来完成。
拿到chrome 安装路径之后, 就是帮路径传给 C++ 然后执行cmd
前提:大家可以提前试一下哈。 在你们的 cmd 中输入如下命令 是可以打开指定浏览器并访问指定网址的。
start chromePath www.baidu.com
chromePath 是你的chrome安装路径哈,不要整句复制过去了。
言归正传。 调用 C++ 打开指定网址。
C++和Flutter交互代码都在 flutter_windows.cpp 中。这个就不多介绍了。 具体代码如下
if (methodName.compare("openUrl") == 0) {
const flutter::EncodableValue* args = call.arguments();
const flutter::EncodableList arg_list = std::get<flutter::EncodableList>(*args);
std::string path = std::get<std::string>(arg_list[0]);
std::string path2 = "start " + path;
system(path2.c_str());
result->Success();
}
Flutter 代码如下
我这里采用的方案是,优先使用chrome打开网址,如果打不开。会使用 url_launcher 打开默认浏览器并访问网址。 (url_launcher 也是一个flutter第三方库哈,需要的话可以pub.dev看看)
import 'package:url_launcher/url_launcher.dart';
import 'package:win32/win32.dart';
import 'package:wxwork_helper/main.dart';
import 'package:wxwork_helper/wuneng/CommonUtils/JCRegistry.dart';
class JCLaunch {
// 1、获取chrome安装路径
// 2、调用C++执行 cmd start path baidu.com
static openUrl(String urlString) {
String chromePath = getChromePath();
if (chromePath.isNotEmpty) {
print("user have install chrome : " + chromePath);
List pathList = chromePath.split("chrome.exe");
if (pathList.isNotEmpty) {
chromePath = pathList[0].toString() + "chrome.exe";
mainMethodChannel
.invokeMethod("openUrl", [chromePath + " " + urlString]);
}
} else {
print("user have not install chrome");
launch(urlString);
}
}
}