本指南示範如何在 Flutter 應用程式中使用 winapp CLI 來新增套件身份,並將應用程式打包成 MSIX。
套件身份是 Windows app 模型中的核心概念。 它讓你的應用程式能access特定的Windows介面(例如通知、安全、AI API等)、乾淨安裝/卸載體驗,還有更多功能。
先決條件
Flutter SDK:請依 照官方指南安裝 Flutter。
winapp CLI:透過 winget 安裝
winappCLI:winget install Microsoft.winappcli --source winget
1. 建立新的 Flutter 應用程式
請依照官方 Flutter 文件的指南建立新應用程式並執行。
2. 更新代碼以驗證身份
新增 ffi 套件:
flutter pub add ffi
將 lib/main.dart 的內容替換為以下程式碼,使用 Windows GetCurrentPackageFamilyName API 及 Dart FFI 檢查套件身份:
import 'dart:ffi';
import 'dart:io' show Platform;
import 'package:ffi/ffi.dart';
import 'package:flutter/material.dart';
String? getPackageFamilyName() {
if (!Platform.isWindows) return null;
final kernel32 = DynamicLibrary.open('kernel32.dll');
final getCurrentPackageFamilyName = kernel32.lookupFunction<
Int32 Function(Pointer<Uint32>, Pointer<Uint16>),
int Function(
Pointer<Uint32>, Pointer<Uint16>)>('GetCurrentPackageFamilyName');
final length = calloc<Uint32>();
try {
final result =
getCurrentPackageFamilyName(length, Pointer<Uint16>.fromAddress(0));
if (result != 122) return null; // ERROR_INSUFFICIENT_BUFFER = 122
final namePtr = calloc<Uint16>(length.value);
try {
final result2 = getCurrentPackageFamilyName(length, namePtr);
if (result2 == 0) {
return namePtr.cast<Utf16>().toDartString();
}
return null;
} finally {
calloc.free(namePtr);
}
} finally {
calloc.free(length);
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
late final String? _packageFamilyName;
@override
void initState() {
super.initState();
_packageFamilyName = getPackageFamilyName();
}
void _incrementCounter() {
setState(() { _counter++; });
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: const EdgeInsets.all(16),
margin: const EdgeInsets.only(bottom: 24),
decoration: BoxDecoration(
color: _packageFamilyName != null
? Colors.green.shade50
: Colors.orange.shade50,
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: _packageFamilyName != null
? Colors.green
: Colors.orange,
),
),
child: Text(
_packageFamilyName != null
? 'Package Family Name:\n$_packageFamilyName'
: 'Not packaged',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyLarge,
),
),
const Text('You have pushed the button this many times:'),
Text('$_counter',
style: Theme.of(context).textTheme.headlineMedium),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
3. 匿名運行
建立並執行應用程式:
flutter build windows
.\build\windows\x64\runner\Release\flutter_app.exe
你應該會看到應用程式顯示橘色的「未包裝」指示。
4. 使用 Winapp CLI 初始化專案
winapp init
出現提示時:
- 套件名稱:按 Enter 接受預設
- Publisher name:按 Enter 接受預設或輸入你的名字
- 版本:按下 "Enter" 以接受 1.0.0.0
- 入口點:按 Enter 接受預設(flutter_app.exe)
- Setup SDKs:選擇「穩定 SDK」下載 Windows App SDK 並產生 C++ 標頭
使用身份進行除錯
建立應用程式:
flutter build windows套用除錯身份:
winapp create-debug-identity .\build\windows\x64\runner\Release\flutter_app.exe執行執行檔:
.\build\windows\x64\runner\Release\flutter_app.exe
你應該會看到應用程式有綠色指示,顯示套件家族名稱。
備註
執行 flutter clean 或重建後,你必須重新執行 create-debug-identity ,因為執行檔已被替換。
6. MSIX 封裝
為發佈建置:
flutter build windows準備套件目錄:
mkdir dist copy .\build\windows\x64\runner\Release\* .\dist\ -Recurse產生開發證書:
winapp cert generate --if-exists skip包裝與標誌:
winapp pack .\dist --cert .\devcert.pfx安裝憑證 (以管理員身份執行):
winapp cert install .\devcert.pfx安裝套件:
Add-AppxPackage .\flutter-app.msix
小提示
- Microsoft Store 會幫你簽署 MSIX,提交前不需要先簽。
- Azure Trusted Signing 是管理憑證以安全管理 CI/CD pipelines 的絕佳方式。