2026年1月28日 星期三

Fultter APP控制 WOKWI ESP32 RFID+LED (使用flutter_windows_3.19.1-stable Visual studio 1.108.2 )

Fultter APP控制 WOKWI ESP32 RFID+LED (使用flutter_windows_3.19.1-stable  Visual studio  1.108.2 )

1) Android studio 環境設定

2) Visual studio  1.108.2版本  環境設定+ 開發 Flutter APP程式

https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-flutter-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/%E4%BD%BF%E7%94%A8-vs-code-%E9%96%8B%E7%99%BC-flutter-app-%E5%BB%BA%E7%AB%8B%E5%B0%88%E6%A1%88-%E6%89%93%E9%96%8B%E5%B0%88%E6%A1%88%E5%92%8C%E5%95%9F%E5%8B%95%E6%A8%A1%E6%93%AC%E5%99%A8%E5%9F%B7%E8%A1%8C-app-213054edc169

3)  安裝  Flutter  flutter_windows_3.19.1-stable  解壓縮後儲存 於 C:\src\flutter 目錄




WOKWI  ESP32 程式

#include <SPI.h>
#include <MFRC522.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// --- 硬體腳位 (您的指定) ---
#define SS_PIN    5
#define RST_PIN   22
#define LED_PIN   2
#define I2C_SDA   17
#define I2C_SCL   16

// --- 設定區 ---
const char* ssid = "Wokwi-GUEST";
const char* password = "";

// MQTT 設定 (與您的 Python Tkinter 程式對接)
const char* mqtt_server = "mqttgo.io";
const char* TOPIC_RFID_UID = "alex9ufo/rfid/UID";
const char* TOPIC_LED_CONTROL = "alex9ufo/led/control";
const char* TOPIC_LED_STATUS = "alex9ufo/led/status";

// 硬體物件
LiquidCrystal_I2C lcd(0x27, 16, 2);
MFRC522 mfrc522(SS_PIN, RST_PIN);
WiFiClient espClient;
PubSubClient mqttClient(espClient);

// --- FreeRTOS 隊列 ---
QueueHandle_t rfidQueue;
struct RfidMsg { char uid[20]; };

// 全域變數
bool isFlashing = false;

// --- MQTT 接收處理 (來自 Python 控制台) ---
void mqttCallback(char* topic, byte* payload, unsigned int length) {
  String message = "";
  for (int i = 0; i < length; i++) message += (char)payload[i];
 
  Serial.printf("\n[MQTT CMD]: %s\n", message.c_str());
 
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("MQTT Command:");
  lcd.setCursor(0, 1);

  isFlashing = false;
  if (message == "on") {
    digitalWrite(LED_PIN, HIGH);
    lcd.print("LED: ON");
    mqttClient.publish(TOPIC_LED_STATUS, "ON");
  }
  else if (message == "off") {
    digitalWrite(LED_PIN, LOW);
    lcd.print("LED: OFF");
    mqttClient.publish(TOPIC_LED_STATUS, "OFF");
  }
  else if (message == "flash") {
    isFlashing = true;
    lcd.print("MODE: FLASHING");
    mqttClient.publish(TOPIC_LED_STATUS, "FLASHING");
  }
  else if (message == "timer") {
    digitalWrite(LED_PIN, HIGH);
    lcd.print("TIMER: 5 SEC");
    mqttClient.publish(TOPIC_LED_STATUS, "TIMER_START");
    vTaskDelay(5000 / portTICK_PERIOD_MS); // 在 Task 中使用 vTaskDelay 不會卡死整個系統
    digitalWrite(LED_PIN, LOW);
    mqttClient.publish(TOPIC_LED_STATUS, "OFF");
  }
}

// --- Core 0: 負責 WiFi 與 MQTT 通訊 ---
void mqttTask(void *pvParameters) {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) { vTaskDelay(500 / portTICK_PERIOD_MS); }
 
  mqttClient.setServer(mqtt_server, 1883);
  mqttClient.setCallback(mqttCallback);

  RfidMsg rMsg;
  while (true) {
    // 維護 MQTT 連線
    if (!mqttClient.connected()) {
      Serial.print("Connecting to MQTT...");
      if (mqttClient.connect("ESP32_RFID_Gate_NoTG")) {
        Serial.println("Connected");
        mqttClient.subscribe(TOPIC_LED_CONTROL);
      } else {
        vTaskDelay(5000 / portTICK_PERIOD_MS);
      }
    }
    mqttClient.loop();

    // 接收來自 Core 1 的 RFID 訊息並發送到 MQTT
    if (xQueueReceive(rfidQueue, &rMsg, 0) == pdPASS) {
      mqttClient.publish(TOPIC_RFID_UID, rMsg.uid);
      Serial.printf("Sent UID to Python: %s\n", rMsg.uid);
    }

    // 處理閃爍邏輯
    if (isFlashing) {
      digitalWrite(LED_PIN, !digitalRead(LED_PIN));
      vTaskDelay(300 / portTICK_PERIOD_MS);
    }
   
    vTaskDelay(10 / portTICK_PERIOD_MS);
  }
}

// --- Core 1: 專門負責 RFID 掃描 (不處理網路) ---
void rfidTask(void *pvParameters) {
  SPI.begin();
  mfrc522.PCD_Init();
  RfidMsg rMsg;
  while (true) {
    if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
      String uidStr = "";
      for (byte i = 0; i < mfrc522.uid.size; i++) {
        uidStr += (mfrc522.uid.uidByte[i] < 0x10 ? "0" : "");
        uidStr += String(mfrc522.uid.uidByte[i], HEX);
      }
      uidStr.toUpperCase();
     
      // 更新 LCD 顯示
      lcd.clear();
      lcd.setCursor(0, 0); lcd.print("RFID Detected!");
      lcd.setCursor(0, 1); lcd.print("ID: " + uidStr);
     
      // 將卡號打包送入隊列,交給 Core 0 發送
      uidStr.toCharArray(rMsg.uid, 20);
      xQueueSend(rfidQueue, &rMsg, portMAX_DELAY);

      mfrc522.PICC_HaltA();
      mfrc522.PCD_StopCrypto1();
    }
    vTaskDelay(200 / portTICK_PERIOD_MS);
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
 
  // 初始化 I2C LCD
  Wire.begin(I2C_SDA, I2C_SCL);
  lcd.init();
  lcd.backlight();
  lcd.print("MQTT Connecting...");

  // 建立隊列
  rfidQueue = xQueueCreate(10, sizeof(RfidMsg));

  if (rfidQueue != NULL) {
    // 建立雙核心任務
    xTaskCreatePinnedToCore(mqttTask, "MQTT_Task", 8192, NULL, 1, NULL, 0);
    xTaskCreatePinnedToCore(rfidTask, "RFID_Task", 4096, NULL, 1, NULL, 1);
  }
}

void loop() {
  // FreeRTOS 架構下 loop 不需執行內容
  vTaskDelay(portMAX_DELAY);
}


VS Code pubspec.yaml

name: rfid
description: "A new Flutter project."
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev

# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+1

environment:
  sdk: '>=3.3.0 <4.0.0'

# 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
  mqtt_client: ^10.2.0  # Or latest version

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.6

dev_dependencies:
  flutter_test:
    sdk: flutter

  # The "flutter_lints" package below contains a set of recommended lints to
  # encourage good coding practices. The lint set provided by the package is
  # activated in the `analysis_options.yaml` file located at the root of your
  # package. See that file for information about deactivating specific lint
  # rules and activating additional ones.
  flutter_lints: ^3.0.0

# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

# The following section is specific to Flutter packages.
flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  # assets:
  #   - images/a_dot_burr.jpeg
  #   - images/a_dot_ham.jpeg

  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.dev/assets-and-images/#resolution-aware

  # For details regarding adding assets from package dependencies, see
  # https://flutter.dev/assets-and-images/#from-packages

  # To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  # example:
  # fonts:
  #   - family: Schyler
  #     fonts:
  #       - asset: fonts/Schyler-Regular.ttf
  #       - asset: fonts/Schyler-Italic.ttf
  #         style: italic
  #   - family: Trajan Pro
  #     fonts:
  #       - asset: fonts/TrajanPro.ttf
  #       - asset: fonts/TrajanPro_Bold.ttf
  #         weight: 700
  #
  # For details regarding fonts from package dependencies,
  # see https://flutter.dev/custom-fonts/#from-packages


VS Code AndroidManifest.xml

<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.WAKE_LOCK" />
    <application
        android:label="rfid"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            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="flutterEmbedding"
            android:value="2" />
    </application>
    <!-- Required to query activities that can process text, see:
         https://developer.android.com/training/package-visibility?hl=en 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>
    </queries>
</manifest>


VS Code main.dart

import 'package:flutter/material.dart';
import 'package:mqtt_client/mqtt_client.dart';
import 'package:mqtt_client/mqtt_server_client.dart';

void main() => runApp(const MaterialApp(home: RFIDControlApp()));

class RFIDControlApp extends StatefulWidget {
  const RFIDControlApp({super.key});

  @override
  State<RFIDControlApp> createState() => _RFIDControlAppState();
}

class _RFIDControlAppState extends State<RFIDControlApp> {
  final String server = "mqttgo.io";
  final String topicUID = "alex9ufo/rfid/UID";
  final String topicControl = "alex9ufo/led/control";
  final String topicStatus = "alex9ufo/led/status";
 
  late MqttServerClient client;
  String lastUID = "No Card Scanned";
  String ledStatus = "Unknown";
  bool isConnected = false;

  @override
  void initState() {
    super.initState();
    _setupMqtt();
  }

  Future<void> _setupMqtt() async {
    client = MqttServerClient(server, 'flutter_client_${DateTime.now().millisecondsSinceEpoch}');
    client.port = 1883;
    client.keepAlivePeriod = 20;
    client.onDisconnected = () => setState(() => isConnected = false);

    try {
      await client.connect();
      setState(() => isConnected = true);
     
      // Subscribe to UID and LED Status
      client.subscribe(topicUID, MqttQos.atMostOnce);
      client.subscribe(topicStatus, MqttQos.atMostOnce);

      client.updates!.listen((List<MqttReceivedMessage<MqttMessage>> c) {
        final MqttPublishMessage recMess = c[0].payload as MqttPublishMessage;
        final String pt = MqttPublishPayload.bytesToStringAsString(recMess.payload.message);

        setState(() {
          if (c[0].topic == topicUID) {
            lastUID = pt;
          } else if (c[0].topic == topicStatus) {
            ledStatus = pt;
          }
        });
      });
    } catch (e) {
      print('Connection failed: $e');
      client.disconnect();
    }
  }

  void _sendCommand(String command) {
    if (!isConnected) return;
    final builder = MqttClientPayloadBuilder();
    builder.addString(command);
    client.publishMessage(topicControl, MqttQos.atLeastOnce, builder.payload!);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("ESP32 RFID & LED Control"),
        backgroundColor: isConnected ? Colors.green : Colors.red,
      ),
      body: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          children: [
            // RFID Display Card
            Card(
              elevation: 4,
              child: ListTile(
                leading: const Icon(Icons.credit_card, size: 40),
                title: const Text("Last Scanned UID"),
                subtitle: Text(lastUID, style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: Colors.blue)),
              ),
            ),
            const SizedBox(height: 20),
            // LED Status Display
            Text("Current LED Status: $ledStatus", style: const TextStyle(fontSize: 18)),
            const Divider(height: 40),
            // Control Buttons
            Wrap(
              spacing: 20,
              runSpacing: 20,
              children: [
                _buildControlBtn("ON", Colors.green, () => _sendCommand("on")),
                _buildControlBtn("OFF", Colors.red, () => _sendCommand("off")),
                _buildControlBtn("FLASH", Colors.orange, () => _sendCommand("flash")),
                _buildControlBtn("TIMER (5s)", Colors.purple, () => _sendCommand("timer")),
              ],
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildControlBtn(String label, Color color, VoidCallback onPressed) {
    return ElevatedButton(
      style: ElevatedButton.styleFrom(backgroundColor: color, minimumSize: const Size(120, 50)),
      onPressed: isConnected ? onPressed : null,
      child: Text(label, style: const TextStyle(color: Colors.white)),
    );
  }
}

VS Code android/gradle/wrapper/gradle-wrapper.properties

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip


VS Code android/settings.gradle
pluginManagement {
    def flutterSdkPath = {
        def properties = new Properties()
        file("local.properties").withInputStream { properties.load(it) }
        def flutterSdkPath = properties.getProperty("flutter.sdk")
        assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
        return flutterSdkPath
    }()

    includeBuild("${flutterSdkPath}/packages/flutter_tools/gradle")

    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

plugins {
    // 1. 將這裡的版本改為 8.2.1 或更高
    id "com.android.application" version "8.2.1" apply false
    // 2. 如果有 kotlin,建議也升級到 1.9.10 以上
    id "org.jetbrains.kotlin.android" version "1.9.10" apply false
    id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false
}


VS Code android/app/build.gradle

plugins {
    id "com.android.application"
    id "kotlin-android"
    id "dev.flutter.flutter-gradle-plugin"
}

def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
    localPropertiesFile.withReader('UTF-8') { reader ->
        localProperties.load(reader)
    }
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
    flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
    flutterVersionName = '1.0'
}

android {
    namespace "com.example.rfid"
    compileSdk flutter.compileSdkVersion
    ndkVersion flutter.ndkVersion

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "com.example.rfid"
        // You can update the following values to match your application needs.
        // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
        minSdkVersion flutter.minSdkVersion
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

    buildTypes {
        release {
            // TODO: Add your own signing config for the release build.
            // Signing with the debug keys for now, so `flutter run --release` works.
            signingConfig signingConfigs.debug
        }
    }
}

flutter {
    source '../..'
}






PowerShell
# 1. 清除 Flutter 緩存
flutter clean

# 2. 重新取得套件
flutter pub get

# 3. 重新編譯
flutter build apk --release --split-per-abi


2026年1月26日 星期一

設定並測試 Flutter

 設定並測試 Flutter

https://docs.flutter.dev/install/quick

使用基於開源軟體的編輯器(例如 VS Code)在您的裝置上安裝 Flutter,即可開始使用 Flutter 開發您的第一個多平台應用程式!

學習如何使用任何基於開源軟體的編輯器(例如 VS Code)來設定 Flutter 開發環境,並體驗 Flutter 的開發者體驗。

如果您之前使用過 Flutter 進行開發,或者您喜歡使用其他編輯器或 IDE,您可以按照自訂設定說明進行操作。

確認您的開發平台

本頁的說明旨在指導如何在Windows裝置 上安裝和試用 Flutter 

如果您想按照其他作業系統的說明進行操作,請選擇以下選項之一。

下載必備軟體

為了獲得最流暢的 Flutter 安裝體驗,請先安裝以下工具。

  1. 安裝適用於 Windows 的 Git

    下載並安裝最新版本的Git for Windows

    如需有關 Git 安裝或故障排除方面的協助,請參閱Git 文件

  2. 下載並安裝 Visual Studio Code

    要快速安裝 Flutter,然後編輯和偵錯您的應用程序, 請安裝並設定 Visual Studio Code

    您也可以安裝並使用任何其他支援 VS Code 擴充功能的開源程式碼編輯器。如果您選擇這樣做,那麼在本文的其餘部分,請假定 VS Code 指的是您選擇的編輯器。

安裝並設定 Flutter

現在您已經安裝了 Git 和 VS Code,請按照以下步驟使用 VS Code 安裝和設定 Flutter。

  1. 啟動 VS Code

    如果 VS Code 尚未打開,請使用 Spotlight 搜尋或從其安裝目錄手動開啟它。

  2. 將 Flutter 擴充功能加入到 VS Code

    若要將 Dart 和 Flutter 擴充功能新增至 VS Code,請造訪Flutter 擴充功能的 Marketplace 頁面,然後按一下「安裝」。如果瀏覽器提示,請允許其開啟 VS Code。

  3. 使用 VS Code 安裝 Flutter

    1. 在 VS Code 中開啟命令面板。

      前往“視圖” “命令面板” 或按ControlShiftP

    2. 在命令面板中,輸入flutter.

    3. 選擇Flutter:新項目

    4. VS Code 會提示您在電腦上尋找 Flutter SDK。選擇“下載 SDK”

    5. 當顯示「選擇 Flutter SDK 資料夾」對話方塊時,選擇要安裝 Flutter 的位置。

    6. 點擊克隆 Flutter

      在下載 Flutter 時,VS Code 會顯示以下彈出通知:

      Downloading the Flutter SDK. This may take a few minutes.
      

      此下載過程需要幾分鐘。如果您懷疑下載卡住了,請點擊「取消」,然後重新開始安裝。

    7. 點擊“將 SDK 新增至 PATH”

      成功後,將顯示通知:

      The Flutter SDK was added to your PATH
      
    8. VS Code 可能會顯示 Google Analytics 通知。

      如果您同意,請點選確定

    9. 為了確保 Flutter 在所有終端機中都可用:

      1. 關閉所有終端機窗口,然後重新開啟。
      2. 重啟 VS Code。
  4. 排查安裝問題

    如果在安裝過程中遇到任何問題,請查看Flutter 安裝故障排除

試試 Flutter

現在你已經設定好了 VS Code 和 Flutter,是時候創建一個應用程式並嘗試 Flutter 開發了!

  1. 建立一個新的 Flutter 應用

    1. 在 VS Code 中開啟命令面板。

      前往“視圖” “命令面板” 或按ControlShiftP

    2. 在命令面板中,開始輸入flutter:

      VS Code 應該會顯示 Flutter 外掛程式中的命令。

    3. 選擇Flutter:新專案指令。

      您的作業系統或 VS Code 可能會要求存取您的文檔,請同意以繼續下一步。

    4. 選擇申請範本。

      VS Code 會提示您「選擇哪個 Flutter 範本?」。選擇“Application”範本即可快速建立一個簡單的計數器應用程式。

    5. 建立或選擇新應用程式資料夾的父目錄。

      應該會彈出一個文件對話框。

      1. 選擇或建立要建立專案的父目錄。
      2. 若要確認您的選擇,請按一下「選擇要建立項目的資料夾」
    6. 請輸入您的應用程式名稱。

      VS Code 會提示您輸入新套用的名稱。輸入“app”trying_flutter或類似lowercase_with_underscores 名稱。若要確認您的選擇,請按 Enter 鍵Enter

    7. 等待項目初始化完成。

      任務進度通常會以通知的形式顯示在右下角,也可以從「輸出」面板存取。

    8. 開啟lib目錄,然後main.dart開啟檔案。

      如果您想了解程式碼的每個部分的作用,請查看文件中前面的註釋。

  2. 在網頁上執行您的應用

    雖然 Flutter 應用程式可以在許多平台上運行,但請嘗試在 Web 上運行您的新應用程式。

    1. 在 VS Code 中開啟命令面板。

      前往“視圖” “命令面板” 或按ControlShiftP

    2. 在命令面板中,開始輸入flutter:

      VS Code 應該會顯示 Flutter 外掛程式中的命令。

    3. 選擇Flutter: 選擇設備指令。

    4. 在「選擇設備」提示中,選擇Chrome

    5. 運行或開始調試您的應用程式。

      前往“運行” “開始調試”或按F5

      flutter run用於建置和啟動您的應用程序,然後應該會打開一個新的 Chrome 實例並開始運行您新創建的應用程式。

  3. 嘗試熱重載

    Flutter 提供快速的開發週期,並具備狀態熱重載功能,能夠在不重新啟動應用或遺失應用程式狀態的情況下重新載入正在執行的應用程式的程式碼。

    您可以變更應用程式的原始程式碼,在 VS Code 中執行熱重載命令,然後在正在執行的應用程式中查看變更。

    1. 在跑步應用程式中,點擊按鈕嘗試幾次增加計數器遞增(+) 。

    2. 在應用程式仍在運行的情況下,對文件進行更改lib/main.dart

      修改方法_counter++中的那行程式碼_incrementCounter,改為遞減該_counter欄位的值。

      setState(() {
        // ...
        _counter++;
        _counter--;
      });
      
    3. 儲存變更(檔案 > 全部儲存)或點選熱重載 熱重載圖標 按鈕。

      Flutter 會在不遺失任何現有狀態的情況下更新正在執行的應用程式。請注意,現有值保持不變。

    4. 再點擊 遞增(+) 一次按鈕。你會發現數值反而減少了,而不是增加了。

  4. 瀏覽 Flutter 側邊欄

    Flutter 外掛程式為 VS Code 新增了一個專用的側邊欄,用於管理 Flutter 偵錯會話和設備,查看程式碼和元件的概要,以及存取 Dart 和 Flutter DevTools。

    1. 如果你的應用程式無法運行,請重新開始調試。

      前往“運行” “開始調試”或按F5

    2. 在 VS Code 中開啟 Flutter 側邊欄。

      您可以使用 VS Code 側邊欄中的 Flutter 按鈕打開它,也可以透過執行Flutter: Focus on Flutter Sidebar ViewFlutter 標誌命令 從命令面板打開它

    3. 在 Flutter 側邊欄的「開發者工具」下,點選Flutter Inspector按鈕。

      VS Code 中應該會開啟一個單獨的Widget Inspector面板。

      在元件檢查器中,您可以查看應用程式的元件樹,查看每個元件的屬性和佈局等等。

    4. 在組件檢查器中,嘗試按一下頂層MyHomePage組件。

      應該打開其屬性和佈局的視圖,並且 VS Code 編輯器應該導航到並聚焦到包含該小部件的行。

    5. 探索並嘗試小部件檢查器和 Flutter 側邊欄中的其他功能。

Fultter APP控制 WOKWI ESP32 RFID+LED (使用flutter_windows_3.19.1-stable Visual studio 1.108.2 )

Fultter APP控制 WOKWI ESP32 RFID+LED (使用flutter_windows_3.19.1-stable  Visual studio  1.108.2 ) 1) Android studio 環境設定 2) Visual studio  1.108...