refactor: clean code

This commit is contained in:
Max 2026-04-01 16:48:55 +08:00
parent 8799a62544
commit 7f1b8afa70
28 changed files with 0 additions and 3612 deletions

View File

@ -1,45 +0,0 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
/coverage/
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release

View File

@ -1,45 +0,0 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "90673a4eef275d1a6692c26ac80d6d746d41a73a"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a
base_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a
- platform: android
create_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a
base_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a
- platform: ios
create_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a
base_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a
- platform: linux
create_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a
base_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a
- platform: macos
create_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a
base_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a
- platform: web
create_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a
base_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a
- platform: windows
create_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a
base_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

View File

@ -1,7 +0,0 @@
# web_android_shell已迁移
> ⚠️ 本包为旧版入口,已迁移至 Monorepo 架构。
当前用途:为旧版 `MainActivity` 提供壳层入口,调用 `web_shell_core` 启动应用。
新品牌应用请使用 `apps/` 目录下的独立应用,参考 [`apps/quanxue/`](../../apps/quanxue/)。

View File

@ -1,9 +0,0 @@
# Dart 分析器配置,用于在开发阶段发现错误、警告和代码规范问题。
# 可通过 `flutter analyze` 执行静态检查。
include: package:flutter_lints/flutter.yaml
linter:
# 如需自定义规则,可在此处开启或关闭指定 lint。
rules:
# avoid_print: false # 取消注释后可关闭 `avoid_print` 规则。
# prefer_single_quotes: true # 取消注释后可开启 `prefer_single_quotes` 规则。

View File

@ -1,14 +0,0 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
.cxx/
# Remember to never publicly share your keystore.
# See https://flutter.dev/to/reference-keystore
key.properties
**/*.keystore
**/*.jks

View File

@ -1,99 +0,0 @@
plugins {
id("com.android.application")
id("kotlin-android")
// Flutter Gradle 插件必须放在 Android 与 Kotlin Gradle 插件之后应用。
id("dev.flutter.flutter-gradle-plugin")
}
import java.io.File
import java.io.FileInputStream
import java.util.Properties
val keystoreProperties = Properties()
val keystorePropertiesFile = rootProject.file("key.properties")
if (keystorePropertiesFile.exists()) {
FileInputStream(keystorePropertiesFile).use { keystoreProperties.load(it) }
}
val defaultReleaseStoreFile = rootProject.file("../../../tool/key.jks")
fun resolveKeystoreFile(rawPath: String?): File {
val candidate = rawPath?.trim().orEmpty()
if (candidate.isEmpty()) {
return defaultReleaseStoreFile
}
val expandedHome = if (candidate.startsWith("~/") || candidate == "~") {
candidate.replaceFirst("~", System.getProperty("user.home"))
} else {
candidate
}
val normalized = expandedHome.replace('\\', File.separatorChar).replace('/', File.separatorChar)
val storeFile = File(normalized)
if (storeFile.isAbsolute) {
return storeFile
}
val rootRelativeFile = rootProject.file(normalized)
if (rootRelativeFile.exists()) {
return rootRelativeFile
}
val moduleRelativeFile = project.file(normalized)
if (moduleRelativeFile.exists()) {
return moduleRelativeFile
}
return rootRelativeFile
}
val releaseStoreFile = resolveKeystoreFile(keystoreProperties["storeFile"] as String?)
val releaseKeyAlias = keystoreProperties["keyAlias"] as String? ?: "my-key-alias"
val releaseKeyPassword = keystoreProperties["keyPassword"] as String? ?: "123456"
val releaseStorePassword = keystoreProperties["storePassword"] as String? ?: "123456"
android {
namespace = "com.yuanxuan.webshell.web_android_shell"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
}
defaultConfig {
// 待补充:请替换成你自己的唯一应用标识。
applicationId = "com.yuanxuan.webshell.web_android_shell"
// 下面这些值可以按应用实际需求调整。
// 更多说明可参考https://flutter.dev/to/review-gradle-config。
minSdk = flutter.minSdkVersion
// 为兼容旧版系统 WebView这里保持稳定的 targetSdk。
targetSdk = 34
versionCode = flutter.versionCode
versionName = flutter.versionName
}
signingConfigs {
create("release") {
keyAlias = releaseKeyAlias
keyPassword = releaseKeyPassword
storeFile = releaseStoreFile
storePassword = releaseStorePassword
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
}
}
}
flutter {
source = "../.."
}

View File

@ -1,7 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@ -1,129 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission
android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30"/>
<uses-permission
android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission
android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32"/>
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"/>
<uses-feature
android:name="android.hardware.camera"
android:required="false"/>
<uses-feature
android:name="android.hardware.microphone"
android:required="false"/>
<uses-feature
android:name="android.hardware.bluetooth"
android:required="false"/>
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="false"/>
<application
android:label="web_android_shell"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:enableOnBackInvokedCallback="true"
android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:screenOrientation="sensorPortrait"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="io.flutter.embedding.android.EnableImpeller"
android:value="false" />
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
<intent>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent>
<intent>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http"/>
</intent>
<intent>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="https"/>
</intent>
<intent>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="tel"/>
</intent>
<intent>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="sms"/>
</intent>
<intent>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="mailto"/>
</intent>
<intent>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="market"/>
</intent>
<intent>
<action android:name="android.intent.action.VIEW"/>
<data android:mimeType="application/vnd.android.package-archive"/>
</intent>
</queries>
</manifest>

View File

@ -1,241 +0,0 @@
package com.yuanxuan.webshell.web_android_shell;
import android.app.ActivityManager;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.Process;
import android.os.SystemClock;
import android.webkit.CookieManager;
import android.webkit.WebStorage;
import android.webkit.WebView;
import androidx.annotation.NonNull;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
public class MainActivity extends FlutterActivity {
private static final String DEVICE_CHANNEL = "app_shell/device";
private static final String DEBUG_PROCESS_PREFS = "app_shell_debug_process";
private static final String DEBUG_PROCESS_PID_KEY = "pid";
private String webViewDataDirectorySuffix;
@Override
protected void onCreate(Bundle savedInstanceState) {
terminatePreviousDebugProcessIfNeeded();
prepareWebViewDataDirectory();
super.onCreate(savedInstanceState);
registerCurrentDebugProcess();
}
@Override
protected void onDestroy() {
clearCurrentDebugProcessRegistration();
super.onDestroy();
}
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
new MethodChannel(
flutterEngine.getDartExecutor().getBinaryMessenger(),
DEVICE_CHANNEL
).setMethodCallHandler((call, result) -> {
switch (call.method) {
case "getAndroidWebViewInfo":
result.success(buildAndroidWebViewInfo());
break;
case "resetAndroidWebViewState":
resetAndroidWebViewState(result);
break;
default:
result.notImplemented();
break;
}
});
}
private Map<String, Object> buildAndroidWebViewInfo() {
final Map<String, Object> info = new HashMap<>();
info.put("sdkInt", Build.VERSION.SDK_INT);
info.put("manufacturer", Build.MANUFACTURER);
info.put("brand", Build.BRAND);
info.put("model", Build.MODEL);
if (webViewDataDirectorySuffix != null) {
info.put("webViewDataDirectorySuffix", webViewDataDirectorySuffix);
}
final PackageInfo currentWebViewPackage = getCurrentWebViewPackageCompat();
if (currentWebViewPackage != null) {
info.put("webViewPackageName", currentWebViewPackage.packageName);
if (currentWebViewPackage.versionName != null) {
info.put("webViewVersionName", currentWebViewPackage.versionName);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
info.put(
"webViewLongVersionCode",
currentWebViewPackage.getLongVersionCode()
);
} else {
info.put(
"webViewLongVersionCode",
(long) currentWebViewPackage.versionCode
);
}
}
return info;
}
private void prepareWebViewDataDirectory() {
webViewDataDirectorySuffix = null;
if (!isDebuggableBuild() || Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
return;
}
clearLegacyDebugWebViewData();
}
private void terminatePreviousDebugProcessIfNeeded() {
if (!isDebuggableBuild()) {
return;
}
final SharedPreferences preferences = getSharedPreferences(
DEBUG_PROCESS_PREFS,
MODE_PRIVATE
);
final int currentPid = Process.myPid();
final int previousPid = preferences.getInt(DEBUG_PROCESS_PID_KEY, -1);
if (previousPid <= 0 || previousPid == currentPid) {
return;
}
if (!isSamePackageProcessRunning(previousPid)) {
preferences.edit().remove(DEBUG_PROCESS_PID_KEY).apply();
return;
}
try {
Process.killProcess(previousPid);
SystemClock.sleep(180);
} catch (RuntimeException ignored) {
// 忽略终止旧进程失败的情况并继续使用当前进程启动
}
}
private void registerCurrentDebugProcess() {
if (!isDebuggableBuild()) {
return;
}
getSharedPreferences(DEBUG_PROCESS_PREFS, MODE_PRIVATE)
.edit()
.putInt(DEBUG_PROCESS_PID_KEY, Process.myPid())
.apply();
}
private void clearCurrentDebugProcessRegistration() {
if (!isDebuggableBuild()) {
return;
}
final SharedPreferences preferences = getSharedPreferences(
DEBUG_PROCESS_PREFS,
MODE_PRIVATE
);
if (preferences.getInt(DEBUG_PROCESS_PID_KEY, -1) != Process.myPid()) {
return;
}
preferences.edit().remove(DEBUG_PROCESS_PID_KEY).apply();
}
private boolean isSamePackageProcessRunning(int pid) {
final ActivityManager activityManager =
(ActivityManager) getSystemService(ACTIVITY_SERVICE);
if (activityManager == null) {
return false;
}
for (final ActivityManager.RunningAppProcessInfo processInfo
: activityManager.getRunningAppProcesses()) {
if (processInfo.pid == pid) {
return getPackageName().equals(processInfo.processName);
}
}
return false;
}
private void clearLegacyDebugWebViewData() {
try {
final File appWebViewDir = new File(getApplicationInfo().dataDir, "app_webview");
deleteRecursively(appWebViewDir);
deleteDatabase("webview.db");
deleteDatabase("webviewCache.db");
} catch (RuntimeException ignored) {
// 忽略旧设备上的清理失败继续执行启动流程
}
}
private boolean isDebuggableBuild() {
return (getApplicationInfo().flags & android.content.pm.ApplicationInfo.FLAG_DEBUGGABLE) != 0;
}
private void deleteRecursively(File target) {
if (target == null || !target.exists()) {
return;
}
if (target.isDirectory()) {
final File[] children = target.listFiles();
if (children != null) {
for (final File child : children) {
deleteRecursively(child);
}
}
}
target.delete();
}
private PackageInfo getCurrentWebViewPackageCompat() {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return WebView.getCurrentWebViewPackage();
}
} catch (RuntimeException ignored) {
return null;
}
return null;
}
private void resetAndroidWebViewState(@NonNull MethodChannel.Result result) {
try {
WebStorage.getInstance().deleteAllData();
final CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeSessionCookies(null);
cookieManager.removeAllCookies(value -> {
try {
cookieManager.flush();
WebView.clearClientCertPreferences(() -> result.success(true));
} catch (RuntimeException error) {
result.error(
"webview_reset_failed",
error.toString(),
null
);
}
});
} catch (RuntimeException error) {
result.error("webview_reset_failed", error.toString(), null);
}
}
}

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -1,7 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@ -1,24 +0,0 @@
allprojects {
repositories {
google()
mavenCentral()
}
}
val newBuildDir: Directory =
rootProject.layout.buildDirectory
.dir("../../build")
.get()
rootProject.layout.buildDirectory.value(newBuildDir)
subprojects {
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
project.layout.buildDirectory.value(newSubprojectBuildDir)
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register<Delete>("clean") {
delete(rootProject.layout.buildDirectory)
}

View File

@ -1,6 +0,0 @@
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
org.gradle.parallel=false
org.gradle.caching=false
org.gradle.vfs.watch=false
org.gradle.workers.max=1
android.useAndroidX=true

View File

@ -1,5 +0,0 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.14-bin.zip

View File

@ -1,26 +0,0 @@
pluginManagement {
val flutterSdkPath =
run {
val properties = java.util.Properties()
file("local.properties").inputStream().use { properties.load(it) }
val flutterSdkPath = properties.getProperty("flutter.sdk")
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
flutterSdkPath
}
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.11.1" apply false
id("org.jetbrains.kotlin.android") version "2.2.20" apply false
}
include(":app")

File diff suppressed because it is too large Load Diff

View File

@ -1,578 +0,0 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
args:
dependency: transitive
description:
name: args
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.7.0"
async:
dependency: transitive
description:
name: async
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.13.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.2"
characters:
dependency: transitive
description:
name: characters
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.4.1"
clock:
dependency: transitive
description:
name: clock
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.2"
collection:
dependency: transitive
description:
name: collection
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.19.1"
cross_file:
dependency: transitive
description:
name: cross_file
sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.3.5+2"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.8"
dbus:
dependency: transitive
description:
name: dbus
sha256: d0c98dcd4f5169878b6cf8f6e0a52403a9dff371a3e2f019697accbf6f44a270
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.7.12"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.3"
ffi:
dependency: transitive
description:
name: ffi
sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.0"
file_picker:
dependency: "direct main"
description:
name: file_picker
sha256: "57d9a1dd5063f85fa3107fb42d1faffda52fdc948cefd5fe5ea85267a5fc7343"
url: "https://pub.flutter-io.cn"
source: hosted
version: "10.3.10"
file_selector_linux:
dependency: transitive
description:
name: file_selector_linux
sha256: "2567f398e06ac72dcf2e98a0c95df2a9edd03c2c2e0cacd4780f20cdf56263a0"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.9.4"
file_selector_macos:
dependency: transitive
description:
name: file_selector_macos
sha256: "5e0bbe9c312416f1787a68259ea1505b52f258c587f12920422671807c4d618a"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.9.5"
file_selector_platform_interface:
dependency: transitive
description:
name: file_selector_platform_interface
sha256: "35e0bd61ebcdb91a3505813b055b09b79dfdc7d0aee9c09a7ba59ae4bb13dc85"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.7.0"
file_selector_windows:
dependency: transitive
description:
name: file_selector_windows
sha256: "62197474ae75893a62df75939c777763d39c2bc5f73ce5b88497208bc269abfd"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.9.3+5"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1"
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.0.0"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
sha256: ee8068e0e1cd16c4a82714119918efdeed33b3ba7772c54b5d094ab53f9b7fd1
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.33"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
http:
dependency: transitive
description:
name: http
sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.6.0"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.1.2"
image_picker:
dependency: "direct main"
description:
name: image_picker
sha256: "784210112be18ea55f69d7076e2c656a4e24949fa9e76429fe53af0c0f4fa320"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.1"
image_picker_android:
dependency: transitive
description:
name: image_picker_android
sha256: eda9b91b7e266d9041084a42d605a74937d996b87083395c5e47835916a86156
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.8.13+14"
image_picker_for_web:
dependency: transitive
description:
name: image_picker_for_web
sha256: "66257a3191ab360d23a55c8241c91a6e329d31e94efa7be9cf7a212e65850214"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.1"
image_picker_ios:
dependency: transitive
description:
name: image_picker_ios
sha256: b9c4a438a9ff4f60808c9cf0039b93a42bb6c2211ef6ebb647394b2b3fa84588
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.8.13+6"
image_picker_linux:
dependency: transitive
description:
name: image_picker_linux
sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.2.2"
image_picker_macos:
dependency: transitive
description:
name: image_picker_macos
sha256: "86f0f15a309de7e1a552c12df9ce5b59fe927e71385329355aec4776c6a8ec91"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.2.2+1"
image_picker_platform_interface:
dependency: transitive
description:
name: image_picker_platform_interface
sha256: "567e056716333a1647c64bb6bd873cff7622233a5c3f694be28a583d4715690c"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.11.1"
image_picker_windows:
dependency: transitive
description:
name: image_picker_windows
sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.2.2"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
url: "https://pub.flutter-io.cn"
source: hosted
version: "11.0.2"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.10"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.2"
lints:
dependency: transitive
description:
name: lints
sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df"
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.1.0"
matcher:
dependency: transitive
description:
name: matcher
sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.12.18"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.13.0"
meta:
dependency: transitive
description:
name: meta
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.17.0"
mime:
dependency: transitive
description:
name: mime
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.0"
path:
dependency: transitive
description:
name: path
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.9.1"
permission_handler:
dependency: "direct main"
description:
name: permission_handler
sha256: bc917da36261b00137bbc8896bf1482169cd76f866282368948f032c8c1caae1
url: "https://pub.flutter-io.cn"
source: hosted
version: "12.0.1"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
sha256: "1e3bc410ca1bf84662104b100eb126e066cb55791b7451307f9708d4007350e6"
url: "https://pub.flutter-io.cn"
source: hosted
version: "13.0.1"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023
url: "https://pub.flutter-io.cn"
source: hosted
version: "9.4.7"
permission_handler_html:
dependency: transitive
description:
name: permission_handler_html
sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.1.3+5"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.3.0"
permission_handler_windows:
dependency: transitive
description:
name: permission_handler_windows
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.2.1"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675"
url: "https://pub.flutter-io.cn"
source: hosted
version: "7.0.2"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.8"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
source_span:
dependency: transitive
description:
name: source_span
sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.10.2"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.12.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.4"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.4.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.2"
test_api:
dependency: transitive
description:
name: test_api
sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.7.9"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.4.0"
url_launcher:
dependency: "direct main"
description:
name: url_launcher
sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.3.2"
url_launcher_android:
dependency: transitive
description:
name: url_launcher_android
sha256: "767344bf3063897b5cf0db830e94f904528e6dd50a6dfaf839f0abf509009611"
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.3.28"
url_launcher_ios:
dependency: transitive
description:
name: url_launcher_ios
sha256: "580fe5dfb51671ae38191d316e027f6b76272b026370708c2d898799750a02b0"
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.4.1"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.2.2"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.2.5"
url_launcher_platform_interface:
dependency: transitive
description:
name: url_launcher_platform_interface
sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.3.2"
url_launcher_web:
dependency: transitive
description:
name: url_launcher_web
sha256: d0412fcf4c6b31ecfdb7762359b7206ffba3bbffd396c6d9f9c4616ece476c1f
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.2"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.5"
vector_math:
dependency: transitive
description:
name: vector_math
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.0"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60"
url: "https://pub.flutter-io.cn"
source: hosted
version: "15.0.2"
web:
dependency: transitive
description:
name: web
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.1"
webview_flutter:
dependency: "direct main"
description:
name: webview_flutter
sha256: a3da219916aba44947d3a5478b1927876a09781174b5a2b67fa5be0555154bf9
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.13.1"
webview_flutter_android:
dependency: "direct main"
description:
name: webview_flutter_android
sha256: "2a03df01df2fd30b075d1e7f24c28aee593f2e5d5ac4c3c4283c5eda63717b24"
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.10.13"
webview_flutter_platform_interface:
dependency: transitive
description:
name: webview_flutter_platform_interface
sha256: "63d26ee3aca7256a83ccb576a50272edd7cfc80573a4305caa98985feb493ee0"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.14.0"
webview_flutter_wkwebview:
dependency: transitive
description:
name: webview_flutter_wkwebview
sha256: "2df8fd9ada04d699b9db8e79aa783a16e5d89b69e5b74009b87e16b59912cf98"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.24.0"
win32:
dependency: transitive
description:
name: win32
sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e
url: "https://pub.flutter-io.cn"
source: hosted
version: "5.15.0"
xml:
dependency: transitive
description:
name: xml
sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025"
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.6.1"
sdks:
dart: ">=3.11.0 <4.0.0"
flutter: ">=3.38.0"

View File

@ -1,35 +0,0 @@
name: web_android_shell
description: "H5壳子项目."
# 阻止误发布到 pub.dev。
publish_to: 'none'
# Android 应用版本号:`build-name` 对应 `versionName``build-number` 对应 `versionCode`。
version: 1.0.0+1
environment:
sdk: ^3.11.0
# 应用运行依赖。
dependencies:
flutter:
sdk: flutter
# Material 图标已覆盖主要场景;此依赖保留以兼容历史代码。
cupertino_icons: ^1.0.8
webview_flutter: ^4.13.1
webview_flutter_android: ^4.10.13
image_picker: ^1.2.1
file_picker: ^10.3.10
permission_handler: ^12.0.1
url_launcher: ^6.3.2
dev_dependencies:
flutter_test:
sdk: flutter
# 推荐的 Flutter lint 规则集合。
flutter_lints: ^6.0.0
flutter:
# 启用 Material 图标字体。
uses-material-design: true

View File

@ -1,10 +0,0 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:web_android_shell/main.dart';
void main() {
test('WebShellApp can be created', () {
expect(const WebShellApp(), isA<Widget>());
});
}

View File

@ -1,187 +0,0 @@
[CmdletBinding()]
param(
[ValidateSet('Auto', 'Disable', 'Enable', 'Keep')]
[string]$WebViewMultiprocess = 'Auto',
[Parameter(ValueFromRemainingArguments = $true)]
[string[]]$FlutterArgs
)
$ErrorActionPreference = 'Stop'
$projectRoot = Split-Path -Parent $PSScriptRoot
$localPropertiesPath = Join-Path $projectRoot 'android\local.properties'
$packageName = 'com.yuanxuan.webshell.web_android_shell'
function Get-LocalPropertyValue {
param(
[string]$Path,
[string]$Name
)
if (-not (Test-Path $Path)) {
return $null
}
$escapedName = [regex]::Escape($Name)
foreach ($line in Get-Content $Path) {
if ($line -match "^$escapedName=(.+)$") {
return $matches[1].Trim() -replace '\\\\', '\'
}
}
return $null
}
function Get-DeviceIdFromArgs {
param([string[]]$ArgsToScan)
for ($index = 0; $index -lt $ArgsToScan.Length; $index += 1) {
$arg = $ArgsToScan[$index]
if ($arg -eq '-d' -or $arg -eq '--device-id') {
if ($index + 1 -lt $ArgsToScan.Length) {
return $ArgsToScan[$index + 1]
}
}
if ($arg.StartsWith('--device-id=')) {
return $arg.Substring('--device-id='.Length)
}
}
return $null
}
function Get-DeviceModel {
param(
[string]$AdbPath,
[string[]]$AdbArgsPrefix
)
return ((& $AdbPath @AdbArgsPrefix shell getprop ro.product.model) | Out-String).Trim()
}
function Get-WebViewUpdateState {
param(
[string]$AdbPath,
[string[]]$AdbArgsPrefix
)
return (& $AdbPath @AdbArgsPrefix shell dumpsys webviewupdate | Out-String)
}
function Get-WebViewInfo {
param(
[string]$AdbPath,
[string[]]$AdbArgsPrefix
)
$state = Get-WebViewUpdateState -AdbPath $AdbPath -AdbArgsPrefix $AdbArgsPrefix
$multiprocessEnabled = $state -match 'Multiprocess enabled:\s+true'
$versionName = $null
if ($state -match 'Current WebView package \(name, version\): \([^\),]+,\s*([^\)]+)\)') {
$versionName = $matches[1].Trim()
}
$majorVersion = $null
if ($versionName) {
$majorToken = $versionName.Split('.')[0]
$parsedMajor = 0
if ([int]::TryParse($majorToken, [ref]$parsedMajor)) {
$majorVersion = $parsedMajor
}
}
return @{
MultiprocessEnabled = $multiprocessEnabled
VersionName = $versionName
MajorVersion = $majorVersion
RawState = $state
}
}
function Set-WebViewMultiprocessState {
param(
[string]$AdbPath,
[string[]]$AdbArgsPrefix,
[bool]$Enabled
)
$command = if ($Enabled) { 'enable-multiprocess' } else { 'disable-multiprocess' }
& $AdbPath @AdbArgsPrefix shell cmd webviewupdate $command | Out-Host
Start-Sleep -Seconds 1
}
$sdkDir = Get-LocalPropertyValue -Path $localPropertiesPath -Name 'sdk.dir'
$adbPath = $null
if ($sdkDir) {
$candidate = Join-Path $sdkDir 'platform-tools\adb.exe'
if (Test-Path $candidate) {
$adbPath = $candidate
}
}
if (-not $adbPath) {
$adbCommand = Get-Command adb.exe -ErrorAction SilentlyContinue
if ($adbCommand) {
$adbPath = $adbCommand.Source
}
}
if (-not $adbPath) {
throw "未找到 adb.exe请检查 android/local.properties 中的 sdk.dir。"
}
$deviceId = Get-DeviceIdFromArgs -ArgsToScan $FlutterArgs
$adbArgsPrefix = @()
if ($deviceId) {
$adbArgsPrefix = @('-s', $deviceId)
}
Write-Host "Using adb: $adbPath"
if ($deviceId) {
Write-Host "Target device: $deviceId"
}
& $adbPath @adbArgsPrefix start-server | Out-Null
$deviceModel = Get-DeviceModel -AdbPath $adbPath -AdbArgsPrefix $adbArgsPrefix
$webViewInfo = Get-WebViewInfo -AdbPath $adbPath -AdbArgsPrefix $adbArgsPrefix
Write-Host "Device model: $deviceModel"
if ($webViewInfo.VersionName) {
Write-Host "System WebView: $($webViewInfo.VersionName)"
}
Write-Host "WebView multiprocess enabled: $($webViewInfo.MultiprocessEnabled)"
$shouldDisableMultiprocess = $false
switch ($WebViewMultiprocess) {
'Disable' {
$shouldDisableMultiprocess = $true
}
'Auto' {
$shouldDisableMultiprocess =
$deviceModel -eq 'F136A' -or
($webViewInfo.MajorVersion -ne $null -and $webViewInfo.MajorVersion -le 101)
}
}
if ($shouldDisableMultiprocess -and $webViewInfo.MultiprocessEnabled) {
Write-Host "Disabling Android WebView multiprocess for compatibility..."
Set-WebViewMultiprocessState -AdbPath $adbPath -AdbArgsPrefix $adbArgsPrefix -Enabled:$false
} elseif ($WebViewMultiprocess -eq 'Enable' -and -not $webViewInfo.MultiprocessEnabled) {
Write-Host "Re-enabling Android WebView multiprocess..."
Set-WebViewMultiprocessState -AdbPath $adbPath -AdbArgsPrefix $adbArgsPrefix -Enabled:$true
}
Write-Host "Force-stopping previous app process: $packageName"
& $adbPath @adbArgsPrefix shell am force-stop $packageName | Out-Null
Start-Sleep -Milliseconds 800
Write-Host "Starting flutter run..."
& flutter run @FlutterArgs
exit $LASTEXITCODE