이 가이드에서는 Flutter 애플리케이션에서 winapp CLI를 사용하여 패키지 ID를 추가하고 앱을 MSIX로 패키지하는 방법을 보여 줍니다.
패키지 ID는 Windows app 모델의 핵심 개념입니다. 이를 통해 애플리케이션은 알림, 보안, AI API 등과 같은 특정 Windows API를 access, 깨끗한 설치/제거 환경 등을 사용할 수 있습니다.
필수 조건
Flutter SDK: 공식 가이드에 따라 Flutter를 설치합니다.
winapp CLI: winget을 사용하여
winappCLI를 설치하십시오.winget install Microsoft.winappcli --source winget
1. 새 Flutter 앱 만들기
공식 Flutter 문서의 가이드에 따라 새 애플리케이션을 만들고 실행합니다.
2. ID를 확인하도록 코드 업데이트
ffi 패키지를 추가합니다.
flutter pub add ffi
lib/main.dart의 내용을 Windows GetCurrentPackageFamilyName API를 통해 다트 FFI를 사용하여 패키지 ID를 확인하는 다음 코드로 바꿉니다.
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. ID 없이 실행
앱을 빌드하고 실행합니다.
flutter build windows
.\build\windows\x64\runner\Release\flutter_app.exe
주황색 "패키지되지 않음" 표시기가 있는 앱이 표시됩니다.
4. winapp CLI를 사용하여 project 초기화
winapp init
프롬프트가 표시되면
- 패키지 이름: Enter 키를 눌러 기본값 적용
- Publisher 이름: Enter 키를 눌러 기본값을 적용하거나 이름을 입력합니다.
- 버전: Enter 키를 눌러 1.0.0.0 허용
- 진입점: Enter 키를 눌러 기본값(flutter_app.exe)을 적용합니다.
- SDK 설정: "안정적인 SDK"를 선택하여 Windows App SDK 다운로드하고 C++ 헤더를 생성합니다.
5. ID를 사용하여 디버그
앱을 빌드합니다.
flutter build windows디버그 ID 적용:
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 신뢰할 수 있는 서명 CI/CD pipelines 대한 인증서를 안전하게 관리하는 좋은 방법입니다.
관련 토픽
Windows developer