Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Tam bir çalışma örneği için bu depodaki Flutter örneğine göz atın.
Bu kılavuzda CLI'yi winapp flutter uygulamasıyla kullanarak paket kimliği ekleme ve uygulamanızı MSIX olarak paketleme işlemleri gösterilmektedir.
Paket kimliği, Windows app modelinde temel bir kavramdır. Uygulamanızın belirli Windows API'lerine (Bildirimler, Güvenlik, AI API'leri vb.) erişmesine, temiz bir yükleme/kaldırma deneyimine ve daha fazlasına erişmesine olanak tanır.
Standart flutter Windows derlemesi paket kimliğine sahip değildir. Bu kılavuzda hata ayıklama için nasıl ekleneceği ve ardından dağıtım için nasıl paketleneceği gösterilmektedir.
Önkoşullar
Flutter SDK'sı: Resmi kılavuzu izleyerek Flutter'ı yükleyin.
winapp CLI: CLI'yi
winappwinget aracılığıyla yükleyin (veya zaten yüklüyse güncelleştirin):winget install Microsoft.winappcli --source winget
1. Yeni Bir Flutter Uygulaması Oluşturma
Yeni bir uygulama oluşturmak ve uygulamayı çalıştırmak için resmi Flutter belgelerindeki kılavuzu izleyin.
Varsayılan Flutter sayaç uygulamasını görmeniz gerekir.
2. Kimliği Denetlemek için Kodu Güncelleştirme
Uygulamanın paket kimliğiyle çalışıp çalışmadığını denetlemek için uygulamayı güncelleştireceğiz. Dart FFI kullanarak Windows GetCurrentPackageFamilyName API'sini çağıracağız.
İlk olarak paketi ekleyin ffi :
flutter pub add ffi
Ardından lib/main.dart içeriğini aşağıdaki kodla değiştirin. Bu kod, Windows API'sini kullanarak geçerli paket kimliğini almayı dener. Başarılı olursa, kullanıcı arabiriminde Paket Aile Adı'nı görüntüler; aksi takdirde , "Paketlenmedi" ifadesini gösterir.
import 'dart:ffi';
import 'dart:io' show Platform;
import 'package:ffi/ffi.dart';
import 'package:flutter/material.dart';
/// Returns the Package Family Name if running with package identity, or null.
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 {
// First call to get required buffer length
final result =
getCurrentPackageFamilyName(length, Pointer<Uint16>.fromAddress(0));
if (result != 122) return null; // ERROR_INSUFFICIENT_BUFFER = 122
// Second call with buffer to get the name
final namePtr = calloc<Uint16>(length.value);
try {
final result2 = getCurrentPackageFamilyName(length, namePtr);
if (result2 == 0) {
return namePtr.cast<Utf16>().toDartString(); // ERROR_SUCCESS = 0
}
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. Kimlik Olmadan Çalıştır
Şimdi uygulamayı her zamanki gibi derleyin ve çalıştırın:
flutter build windows
Yürütülebilir dosyayı doğrudan çalıştırın (farklıysa flutter_app değerini proje adınızla değiştirin):
.\build\windows\x64\runner\Release\flutter_app.exe
Tavsiye
Derleme çıkışı, makinenizin mimarisinden bağımsız olarak x64 klasöründedir; flutter'ın Windows derlemesi için bu beklenir.
Uygulamayı turuncu "Paketlenmedi" göstergesiyle görmeniz gerekir. Bu, standart yürütülebilir dosyanın herhangi bir paket kimliği olmadan çalıştığını onaylar.
4. winapp CLI ile Project başlatma
winapp init komutu tek seferde ihtiyacınız olan her şeyi ayarlar: uygulama manifesti, varlıklar ve isteğe bağlı olarak C++ geliştirme için Windows Uygulama SDK'sı üst bilgileri. Manifesto, Windows'un API erişimi vermek için kullandığı uygulamanızın kimliğini (ad, yayımcı, sürüm) tanımlar.
Aşağıdaki komutu çalıştırın ve istemleri izleyin:
winapp init
Sorulduğunda:
- Paket adı: Varsayılanı kabul etmek için Enter tuşuna basın (proje adınızdan türetilir)
- Publisher name: Varsayılanı kabul etmek için Enter tuşuna basın veya adınızı girin
- Sürüm: 1.0.0.0'ı kabul etmek için Enter'a basın
- Description: Varsayılanı kabul etmek için Enter tuşuna basın (Windows Uygulama)
- SDK'ları ayarlama: Windows Uygulama SDK'sı indirmek ve C++ üst bilgileri oluşturmak için "Kararlı SDK'ları" seçin (6. adım için gereklidir)
Bu komut:
- Oluşturma
Package.appxmanifest— uygulamanızın kimliğini tanımlayan bildirim - Klasör oluşturma
Assets— MSIX paketleme ve Mağaza gönderimi için gereken simgeler - Windows Uygulama SDK'sı başlık dosyaları ve kitaplıklarını içeren bir
.winappklasörü oluşturun. - SDK sürümlerini sabitlemek için yapılandırma
winapp.yamldosyası oluşturma
Görüntü adı, yayımcı ve özellikler gibi unsurları daha fazla özelleştirmek için Package.appxmanifest açabilirsiniz.
5. Kimlikle Hata Ayıklama
Uygulamayı tamamen paketlemeden kimlik gerektiren özellikleri (Bildirimler gibi) test etmek için kullanabilirsiniz winapp run. Bu, gevşek bir düzen paketini (gerçek bir MSIX yüklemesi gibi) kaydeder ve uygulamayı bir adımda başlatır. Hata ayıklama için sertifika veya imzalama gerekmez.
Uygulamayı inşa etme
flutter build windowsKimlikle çalıştır:
winapp run .\build\windows\x64\runner\Release
Tavsiye
winapp run ayrıca paketi sisteminize kaydeder. Bu nedenle, 7. adımda yüklemeyi denediğinizde MSIX "zaten yüklü" olarak görünebilir. İşiniz bittiğinde geliştirme paketlerini temizlemek için kullanın winapp unregister .
Şimdi uygulamayı yeşil bir göstergeyle görmeniz gerekir:
Package Family Name: flutterapp.debug_xxxxxxxx
Bu, uygulamanızın geçerli bir paket kimliğiyle çalıştığını onaylar!
Tavsiye
Gelişmiş hata ayıklama iş akışları (hata ayıklayıcıları ekleme, IDE kurulumu, başlatma hata ayıklama) için Hata Ayıklama Kılavuzu'na bakın.
6. Windows Uygulama SDK'sı Kullanma (İsteğe Bağlı)
winapp init sırasında SDK'ları ayarlamayı seçtiyseniz, artık .winapp/include klasöründeki Windows Uygulama SDK'sı C++ üst bilgilerine erişebilirsiniz. Flutter'ın Windows çalıştırıcısı C++ olduğu için, yerel koddan Windows Uygulama SDK'sı API'lerini çağırabilir ve bunları bir yöntem kanalı aracılığıyla Dart'a sunabilirsiniz. Yalnızca dağıtım için paket kimliğine ihtiyacınız varsa 7. adıma atlayabilirsiniz.
şimdi Windows Uygulaması Çalışma Zamanı sürümünü görüntüleyen basit bir örnek ekleyelim.
Yerel Eklenti oluşturma
Oluştur windows/runner/winapp_sdk_plugin.h:
#ifndef RUNNER_WINAPP_SDK_PLUGIN_H_
#define RUNNER_WINAPP_SDK_PLUGIN_H_
#include <flutter/flutter_engine.h>
// Registers a method channel for querying Windows App SDK info.
void RegisterWinAppSdkPlugin(flutter::FlutterEngine* engine);
#endif // RUNNER_WINAPP_SDK_PLUGIN_H_
Oluştur windows/runner/winapp_sdk_plugin.cpp:
#include "winapp_sdk_plugin.h"
#include <flutter/method_channel.h>
#include <flutter/standard_method_codec.h>
#include <winrt/Microsoft.Windows.ApplicationModel.WindowsAppRuntime.h>
#include <string>
void RegisterWinAppSdkPlugin(flutter::FlutterEngine* engine) {
auto channel = std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
engine->messenger(), "com.example/winapp_sdk",
&flutter::StandardMethodCodec::GetInstance());
channel->SetMethodCallHandler(
[](const flutter::MethodCall<flutter::EncodableValue>& call,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
if (call.method_name() == "getRuntimeVersion") {
try {
// Flutter already initializes COM in main.cpp, so we skip
// winrt::init_apartment() here — the apartment is already set up.
auto version = winrt::Microsoft::Windows::ApplicationModel::
WindowsAppRuntime::RuntimeInfo::AsString();
std::string versionStr = winrt::to_string(version);
result->Success(flutter::EncodableValue(versionStr));
} catch (const winrt::hresult_error& e) {
result->Error("WINRT_ERROR", winrt::to_string(e.message()));
} catch (...) {
result->Error("UNKNOWN_ERROR",
"Failed to get Windows App Runtime version");
}
} else {
result->NotImplemented();
}
});
// prevent channel destruction by releasing ownership
channel.release();
}
Güncelleştirme CMakeLists.txt
Üç değişiklik yapmak için windows/runner/CMakeLists.txt düzenleyin.
add_executable Bloğu bulun ve kaynak dosya listesine ekleyin"winapp_sdk_plugin.cpp":
add_executable(${BINARY_NAME} WIN32
"flutter_window.cpp"
"main.cpp"
"utils.cpp"
"win32_window.cpp"
"winapp_sdk_plugin.cpp" # <-- add this line
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
"Runner.rc"
"runner.exe.manifest"
)
Ardından, WinRT kitaplıklarını bağlamak ve Windows Uygulama SDK'sı üst bilgilerini eklemek için dosyanın sonuna şu iki satırı ekleyin:
# Link Windows Runtime libraries for WinRT
target_link_libraries(${BINARY_NAME} PRIVATE "WindowsApp.lib")
# Windows App SDK headers from winapp CLI
target_include_directories(${BINARY_NAME} PRIVATE
"${CMAKE_SOURCE_DIR}/../.winapp/include")
Eklentiyi kaydetme
Dosyanın üst kısmına diğer include'larla birlikte windows/runner/flutter_window.cpp içinde include ekleyin.
#include "winapp_sdk_plugin.h"
Ardından RegisterPlugins çağrısını FlutterWindow::OnCreate() içerisinde bulun ve hemen arkasındaki satıra RegisterWinAppSdkPlugin ekleyin.
RegisterPlugins(flutter_controller_->engine());
RegisterWinAppSdkPlugin(flutter_controller_->engine()); // <-- add this line
main.dart dosyasını güncelleştir
Aşağıdaki içeri aktarmayı, mevcut ithalatlarla birlikte lib/main.dart'nin en üstüne ekleyin.
import 'package:flutter/services.dart';
Bu işlevi mevcut getPackageFamilyName() işlevin altına ekleyin (herhangi bir sınıfın dışında):
/// Queries the Windows App Runtime version via a native method channel.
Future<String?> getWindowsAppRuntimeVersion() async {
if (!Platform.isWindows) return null;
try {
const channel = MethodChannel('com.example/winapp_sdk');
final version = await channel.invokeMethod<String>('getRuntimeVersion');
return version;
} catch (_) {
return null;
}
}
_MyHomePageState sınıfında, var olan _packageFamilyNameöğesinin yanına yeni bir alan ekleyin:
late final String? _packageFamilyName;
String? _runtimeVersion; // <-- add this line
Yeni işlevi çağırmak için güncelleştirin initState() :
@override
void initState() {
super.initState();
_packageFamilyName = getPackageFamilyName();
// Fetch the runtime version asynchronously
getWindowsAppRuntimeVersion().then((version) {
setState(() {
_runtimeVersion = version;
});
});
}
Son olarak, build yönteminde çalışma süresi sürümünü görüntüleyin. Bu pencere öğesini, paket kimliğinin gösterildiği Container'den hemen sonra, Column alt öğe listesi içine ekleyin.
if (_runtimeVersion != null)
Padding(
padding: const EdgeInsets.only(bottom: 16),
child: Text(
'Windows App Runtime: $_runtimeVersion',
style: Theme.of(context).textTheme.bodyLarge,
),
),
Derleme ve Çalıştırma
Uygulamayı yeniden derleyin:
flutter build windows
winapp run .\build\windows\x64\runner\Release
Şimdi aşağıdaki gibi bir çıkış görmeniz gerekir:
Package Family Name: flutterapp.debug_xxxxxxxx
Windows App Runtime: 8000.731.1532.0
.winapp/include dizini, Windows Uygulama SDK'sı için gerekli tüm üst bilgileri içerir, örneğin:
-
winrt/- Windows Çalışma Zamanı API'lerine erişmek için WinRT C++ projeksiyon başlık dosyaları -
Microsoft.UI.*.h- Modern kullanıcı arabirimi bileşenleri için WinUI 3 üst bilgileri -
MddBootstrap.h- Windows Uygulama SDK'sı başlatma -
WindowsAppSDK-VersionInfo.h- Sürüm bilgileri - Ve daha birçok Windows Uygulama SDK'sı bileşeni
Daha gelişmiş Windows Uygulama SDK'sı kullanımı için Windows Uygulama SDK'sı belgelerine göz atın.
7. MSIX ile paketle
Uygulamanızı dağıtmaya hazır olduğunuzda, aynı bildirimi kullanarak bir MSIX olarak paketleyebilirsiniz.
Paket Dizinini Hazırlama
İlk olarak, uygulamanızı yayın modunda derleyin:
flutter build windows
Ardından, yayın dosyalarınızı içeren bir dizin oluşturun:
mkdir dist
copy .\build\windows\x64\runner\Release\* .\dist\ -Recurse
Flutter Windows derleme çıkışı yürütülebilir dosya, flutter_windows.dll ve data klasörünü içerir; bunların tümü gereklidir.
Geliştirme Sertifikası Oluşturma
Paketlemeden önce imzalama için bir geliştirme sertifikasına ihtiyacınız vardır. Henüz oluşturmadıysanız bir tane oluşturun:
winapp cert generate --if-exists skip
İmzala ve Paketle
Artık paketleyip imzalayabilirsiniz:
winapp pack .\dist --cert .\devcert.pfx
Not:
packkomutu, geçerli dizininizdenPackage.appxmanifestdeğerini otomatik olarak kullanır ve paketlemeden önce hedef klasöre kopyalar.
Sertifikayı Yükleme
MSIX paketini yükleyebilmeniz için önce makinenizdeki geliştirme sertifikasına güvenmeniz gerekir. Bu komutu yönetici olarak çalıştırın (bunu sertifika başına yalnızca bir kez yapmanız gerekir):
winapp cert install .\devcert.pfx
Yükleme ve Çalıştırma
Tavsiye
5. adımda kullandıysanız winapp run paket sisteminizde zaten kayıtlı olabilir. Önce geliştirme kaydını kaldırmak için kullanın winapp unregister , ardından yayın paketini yükleyin.
Oluşturulan .msix dosyaya çift tıklayarak veya PowerShell kullanarak paketi yükleyin:
Add-AppxPackage .\flutterapp.msix
Tavsiye
MSIX dosya adı sürümü ve mimariyi içerir (örn. flutterapplication1_1.0.0.0_x64.msix). Tam dosya adı için dizininizi denetleyin. Kod değişikliklerinden sonra yeniden paketleme yapmanız gerekiyorsa, Windows yüklü bir paketi güncellemek için daha yüksek bir sürüm numarasına ihtiyaç duyduğundan, Version içindeki Package.appxmanifest artırmanız gerekir.
Tips
- Dağıtıma hazır olduğunuzda, kullanıcılarınızın otomatik olarak imzalanan bir sertifika yüklemesini gerektirmeyecek şekilde MSIX'inizi Sertifika Yetkilisi'nden bir kod imzalama sertifikasıyla imzalayabilirsiniz.
- Azure Güvenilen İmzalama hizmeti, sertifikalarınızı güvenli bir şekilde yönetmenin ve CI/CD işlem hattınızda oturum açmayı tümleştirmenin harika bir yoludur.
- Microsoft Store MSIX'i sizin için imzalar, göndermeden önce imzalamanız gerekmez.
Sonraki Adımlar
- winget aracılığıyla dağıtın: MSIX'inizi Windows Paket Yöneticisi Topluluk Deposu'na gönderin
Microsoft Store: Paketinizi göndermek için kullanın -
CI/CD'yi ayarlayın: İşlem hattınızda paketlemeyi otomatikleştirmek için
setup-WinAppCliGitHub Eylemi'ni kullanın - Explore Windows API'leri: Paket kimliğiyle, artık Notifications, on-device AI ve diğer identity bağımlı API'leri kullanabilirsiniz
Windows developer