diff --git a/.github/labeler.yml b/.github/labeler.yml
index dbb0844b6..c600ee321 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -41,6 +41,8 @@
- packages/tizen_app_manager/**/*
'p: tizen_audio_manager':
- packages/tizen_audio_manager/**/*
+'p: tizen_package_manager':
+ - packages/tizen_package_manager/**/*
'p: url_launcher':
- packages/url_launcher/**/*
'p: video_player':
diff --git a/.github/recipe.yaml b/.github/recipe.yaml
index 4b70f85d4..ae13d4c7a 100644
--- a/.github/recipe.yaml
+++ b/.github/recipe.yaml
@@ -14,6 +14,7 @@ plugins:
sqflite: ["wearable-5.5", "tv-6.0"]
tizen_app_manager: ["wearable-5.5", "tv-6.0"]
tizen_audio_manager: ["wearable-5.5", "tv-6.0"]
+ tizen_package_manager: ["wearable-5.5", "tv-6.0"]
wakelock: ["wearable-5.5"]
# Not supported by emulators.
diff --git a/README.md b/README.md
index e35d4d7cf..44a5772b3 100644
--- a/README.md
+++ b/README.md
@@ -37,6 +37,7 @@ The _"non-endorsed"_ status means that the plugin is not endorsed by the origina
| [**tizen_app_manager**](packages/tizen_app_manager) | (Tizen-only) | [](https://pub.dev/packages/tizen_app_manager) | N/A |
| [**tizen_audio_manager**](packages/tizen_audio_manager) | (Tizen-only) | [](https://pub.dev/packages/tizen_audio_manager) | N/A |
| [**tizen_notification**](packages/tizen_notification) | (Tizen-only) | [](https://pub.dev/packages/tizen_notification) | N/A |
+| [**tizen_package_manager**](packages/tizen_package_manager) | (Tizen-only) | [](https://pub.dev/packages/tizen_package_manager) | N/A |
| [**url_launcher_tizen**](packages/url_launcher) | [url_launcher](https://github.com/flutter/plugins/tree/master/packages/url_launcher) (1st-party) | [](https://pub.dev/packages/url_launcher_tizen) | No |
| [**video_player_tizen**](packages/video_player) | [video_player](https://github.com/flutter/plugins/tree/master/packages/video_player) (1st-party) | [](https://pub.dev/packages/video_player_tizen) | No |
| [**wakelock_tizen**](packages/wakelock) | [wakelock](https://github.com/creativecreatorormaybenot/wakelock) (3rd-party) | [](https://pub.dev/packages/wakelock_tizen) | No |
@@ -70,6 +71,7 @@ The _"non-endorsed"_ status means that the plugin is not endorsed by the origina
| [**tizen_app_manager**](packages/tizen_app_manager) | ✔️ | ✔️ | ✔️ | ✔️ |
| [**tizen_audio_manager**](packages/tizen_audio_manager) | ✔️ | ✔️ | ✔️ | ✔️ |
| [**tizen_notification**](packages/tizen_notification) | ❌ | ✔️ | ✔️ | ✔️ | API not supported |
+| [**tizen_package_manager**](packages/tizen_package_manager) | ✔️ | ✔️ | ✔️ | ✔️ |
| [**url_launcher_tizen**](packages/url_launcher) | ✔️ | ❌ | ✔️ | ❌ | No browser app |
| [**video_player_tizen**](packages/video_player) | ✔️ | ✔️ | ⚠️ | ❌ | Functional limitations (see README) TV emulator issue |
| [**wakelock_tizen**](packages/wakelock) | ✔️ | ✔️ | ❌ | ❌ | Cannot override system display setting |
diff --git a/packages/tizen_package_manager/.gitignore b/packages/tizen_package_manager/.gitignore
new file mode 100644
index 000000000..e9dc58d3d
--- /dev/null
+++ b/packages/tizen_package_manager/.gitignore
@@ -0,0 +1,7 @@
+.DS_Store
+.dart_tool/
+
+.packages
+.pub/
+
+build/
diff --git a/packages/tizen_package_manager/CHANGELOG.md b/packages/tizen_package_manager/CHANGELOG.md
new file mode 100644
index 000000000..802b87e00
--- /dev/null
+++ b/packages/tizen_package_manager/CHANGELOG.md
@@ -0,0 +1,4 @@
+## 0.1.0
+
+* Initial release.
+
diff --git a/packages/tizen_package_manager/LICENSE b/packages/tizen_package_manager/LICENSE
new file mode 100644
index 000000000..487f7b1dc
--- /dev/null
+++ b/packages/tizen_package_manager/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the names of the copyright holders nor the names of the
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/packages/tizen_package_manager/README.md b/packages/tizen_package_manager/README.md
new file mode 100644
index 000000000..ce36899b8
--- /dev/null
+++ b/packages/tizen_package_manager/README.md
@@ -0,0 +1,58 @@
+# tizen_package_manager
+
+ [](https://pub.dev/packages/tizen_package_manager)
+
+Tizen package manager API. Used for getting installed package info.
+
+## Usage
+
+To use this package, add `tizen_package_manager` as a dependency in your `pubspec.yaml` file.
+
+```yaml
+dependencies:
+ tizen_package_manager: ^0.1.0
+```
+
+### Retrieving specific package info
+
+To retrieve information of a specific package, use the `getPackageInfo` method which returns an instance of `PackageInfo`.
+
+```dart
+var packageId = 'org.tizen.settings';
+var packageInfo = await PackageManager.getPackageInfo(packageId);
+```
+
+### Retrieving all packages' info
+
+To retrieve information of all packages installed on a Tizen device, use `getPackagesInfo` method.
+
+```dart
+var packageList = await PackageManager.getPackagesInfo();
+for (var package in packageList) {
+ // Handle each package's info.
+}
+```
+
+### Monitoring package events
+
+You can listen for package events using `onInstallProgressChanged`, `onUninstallProgressChanged`, and `onUpdateProgressChanged`.
+
+```dart
+_subscription = PackageManager.onInstallProgressChanged.listen((event) {
+ // A package is being installed.
+});
+...
+_subscription.cancel();
+```
+
+## Required privileges
+
+Privileges are required to use the package manager functionality. Add required privileges in tizen-manifest.xml of your application.
+
+```xml
+
+ http://tizen.org/privilege/packagemanager.info
+
+ http://tizen.org/privilege/packagemanager.admin
+
+```
diff --git a/packages/tizen_package_manager/example/.gitignore b/packages/tizen_package_manager/example/.gitignore
new file mode 100644
index 000000000..0fa6b675c
--- /dev/null
+++ b/packages/tizen_package_manager/example/.gitignore
@@ -0,0 +1,46 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+
+# 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
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Web related
+lib/generated_plugin_registrant.dart
+
+# 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
diff --git a/packages/tizen_package_manager/example/README.md b/packages/tizen_package_manager/example/README.md
new file mode 100644
index 000000000..480068aea
--- /dev/null
+++ b/packages/tizen_package_manager/example/README.md
@@ -0,0 +1,7 @@
+# tizen_package_manager_example
+
+Demonstrates how to use the tizen_package_manager plugin.
+
+## Getting Started
+
+To run this app on your Tizen device, use [flutter-tizen](https://github.com/flutter-tizen/flutter-tizen).
diff --git a/packages/tizen_package_manager/example/integration_test/tizen_package_manager_test.dart b/packages/tizen_package_manager/example/integration_test/tizen_package_manager_test.dart
new file mode 100644
index 000000000..44219cb4f
--- /dev/null
+++ b/packages/tizen_package_manager/example/integration_test/tizen_package_manager_test.dart
@@ -0,0 +1,32 @@
+// Copyright 2022 Samsung Electronics Co., Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter_test/flutter_test.dart';
+import 'package:integration_test/integration_test.dart';
+import 'package:tizen_package_manager/package_manager.dart';
+
+import 'package:tizen_package_manager_example/main.dart';
+
+void main() {
+ IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+
+ testWidgets('Can get current package info', (WidgetTester tester) async {
+ // These test are based on the example app.
+ final PackageInfo info =
+ await PackageManager.getPackageInfo(currentPackageId);
+ expect(info.packageId, 'com.example.tizen_package_manager_example');
+ expect(info.label, 'tizen_package_manager_example');
+ expect(info.packageType, PackageType.tpk);
+ expect(info.version, '1.0.0');
+ expect(info.isPreloaded, false);
+ expect(info.isSystem, false);
+ expect(info.isRemovable, true);
+ });
+
+ testWidgets('Can get all installed packages info',
+ (WidgetTester tester) async {
+ final List infos = await PackageManager.getPackagesInfo();
+ expect(infos.isNotEmpty, true);
+ });
+}
diff --git a/packages/tizen_package_manager/example/lib/main.dart b/packages/tizen_package_manager/example/lib/main.dart
new file mode 100644
index 000000000..20c929946
--- /dev/null
+++ b/packages/tizen_package_manager/example/lib/main.dart
@@ -0,0 +1,188 @@
+// Copyright 2022 Samsung Electronics Co., Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/material.dart';
+import 'package:tizen_package_manager/package_manager.dart';
+
+/// The example app package ID.
+const String currentPackageId = 'com.example.tizen_package_manager_example';
+
+/// The main entry point for the UI app.
+void main() {
+ runApp(const MyApp());
+}
+
+/// The main UI app widget.
+class MyApp extends StatelessWidget {
+ /// The constructor of the main UI app widget.
+ const MyApp({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ title: 'Package manager demo',
+ theme: ThemeData(primarySwatch: Colors.blue),
+ home: const _MyHomePage(),
+ );
+ }
+}
+
+class _MyHomePage extends StatefulWidget {
+ const _MyHomePage({Key? key}) : super(key: key);
+
+ @override
+ _MyHomePageState createState() => _MyHomePageState();
+}
+
+class _MyHomePageState extends State<_MyHomePage> {
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(title: const Text('Package manager demo')),
+ body: Center(
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ TextButton(
+ onPressed: () {
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (BuildContext context) =>
+ _CurrentPackageInfoScreen(),
+ ),
+ );
+ },
+ child: const Text('Current app package info'),
+ ),
+ TextButton(
+ onPressed: () {
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (BuildContext context) => _PackagesListScreen(),
+ ),
+ );
+ },
+ child: const Text('Installed packages list'),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
+
+class _CurrentPackageInfoScreen extends StatefulWidget {
+ @override
+ _CurrentPackageInfoScreenState createState() =>
+ _CurrentPackageInfoScreenState();
+}
+
+class _CurrentPackageInfoScreenState extends State<_CurrentPackageInfoScreen> {
+ PackageInfo _packageInfo = PackageInfo(
+ packageId: '',
+ label: '',
+ packageType: PackageType.unknown,
+ iconPath: '',
+ version: '',
+ installedStorageType: '',
+ isSystem: false,
+ isPreloaded: false,
+ isRemovable: false,
+ );
+
+ @override
+ void initState() {
+ super.initState();
+
+ PackageManager.getPackageInfo(currentPackageId).then(
+ (PackageInfo packageInfo) {
+ setState(() {
+ _packageInfo = packageInfo;
+ });
+ },
+ );
+ }
+
+ Widget _infoTile(String title, String subtitle) {
+ return ListTile(
+ title: Text(title),
+ subtitle: Text(subtitle.isNotEmpty ? subtitle : 'Not set'),
+ );
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(title: const Text('Current app package info')),
+ body: ListView(
+ children: [
+ _infoTile('Package ID', _packageInfo.packageId),
+ _infoTile('Label', _packageInfo.label),
+ _infoTile('Version', _packageInfo.version),
+ _infoTile('Package type', _packageInfo.packageType.name),
+ _infoTile('Icon path', _packageInfo.iconPath ?? ''),
+ _infoTile('Is system app', _packageInfo.isSystem.toString()),
+ _infoTile('Is preloaded app', _packageInfo.isPreloaded.toString()),
+ _infoTile('Is removable', _packageInfo.isRemovable.toString()),
+ ],
+ ),
+ );
+ }
+}
+
+class _PackagesListScreen extends StatefulWidget {
+ @override
+ _PackagesListScreenState createState() => _PackagesListScreenState();
+}
+
+class _PackagesListScreenState extends State<_PackagesListScreen> {
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(title: const Text('Package list')),
+ body: _PackagesListScreenContent(key: GlobalKey()),
+ );
+ }
+}
+
+class _PackagesListScreenContent extends StatelessWidget {
+ const _PackagesListScreenContent({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return FutureBuilder>(
+ future: PackageManager.getPackagesInfo(),
+ builder: (BuildContext context, AsyncSnapshot> data) {
+ if (data.data == null) {
+ return const Center(child: CircularProgressIndicator());
+ } else {
+ final List packages = data.data!;
+
+ return Scrollbar(
+ child: ListView.builder(
+ itemBuilder: (BuildContext context, int position) {
+ final PackageInfo package = packages[position];
+ return Column(
+ children: [
+ ListTile(
+ title: Text(package.label),
+ subtitle: Text('Package Id: ${package.packageId}\n'
+ 'Version: ${package.version}\n'
+ 'type: ${package.packageType}\n'
+ 'isSystem: ${package.isSystem}\n'),
+ ),
+ const Divider(height: 1.0)
+ ],
+ );
+ },
+ itemCount: packages.length,
+ ),
+ );
+ }
+ },
+ );
+ }
+}
diff --git a/packages/tizen_package_manager/example/pubspec.yaml b/packages/tizen_package_manager/example/pubspec.yaml
new file mode 100644
index 000000000..6db186ba4
--- /dev/null
+++ b/packages/tizen_package_manager/example/pubspec.yaml
@@ -0,0 +1,26 @@
+name: tizen_package_manager_example
+description: Demonstrates how to use the tizen_package_manager plugin.
+version: 1.0.0
+publish_to: 'none'
+
+environment:
+ sdk: ">=2.14.1 <3.0.0"
+
+dependencies:
+ flutter:
+ sdk: flutter
+ tizen_package_manager:
+ path: ../
+
+dev_dependencies:
+ flutter_driver:
+ sdk: flutter
+ flutter_test:
+ sdk: flutter
+ integration_test:
+ sdk: flutter
+ integration_test_tizen:
+ path: ../../integration_test/
+
+flutter:
+ uses-material-design: true
diff --git a/packages/tizen_package_manager/example/test_driver/integration_test.dart b/packages/tizen_package_manager/example/test_driver/integration_test.dart
new file mode 100644
index 000000000..b38629cca
--- /dev/null
+++ b/packages/tizen_package_manager/example/test_driver/integration_test.dart
@@ -0,0 +1,3 @@
+import 'package:integration_test/integration_test_driver.dart';
+
+Future main() => integrationDriver();
diff --git a/packages/tizen_package_manager/example/tizen/.gitignore b/packages/tizen_package_manager/example/tizen/.gitignore
new file mode 100644
index 000000000..750f3af1b
--- /dev/null
+++ b/packages/tizen_package_manager/example/tizen/.gitignore
@@ -0,0 +1,5 @@
+flutter/
+.vs/
+*.user
+bin/
+obj/
diff --git a/packages/tizen_package_manager/example/tizen/App.cs b/packages/tizen_package_manager/example/tizen/App.cs
new file mode 100644
index 000000000..6dd4a6356
--- /dev/null
+++ b/packages/tizen_package_manager/example/tizen/App.cs
@@ -0,0 +1,20 @@
+using Tizen.Flutter.Embedding;
+
+namespace Runner
+{
+ public class App : FlutterApplication
+ {
+ protected override void OnCreate()
+ {
+ base.OnCreate();
+
+ GeneratedPluginRegistrant.RegisterPlugins(this);
+ }
+
+ static void Main(string[] args)
+ {
+ var app = new App();
+ app.Run(args);
+ }
+ }
+}
diff --git a/packages/tizen_package_manager/example/tizen/Runner.csproj b/packages/tizen_package_manager/example/tizen/Runner.csproj
new file mode 100644
index 000000000..c3c43aed9
--- /dev/null
+++ b/packages/tizen_package_manager/example/tizen/Runner.csproj
@@ -0,0 +1,26 @@
+
+
+
+ Exe
+ tizen40
+
+
+
+ portable
+
+
+ none
+
+
+
+
+
+
+
+
+
+ %(RecursiveDir)
+
+
+
+
diff --git a/packages/tizen_package_manager/example/tizen/shared/res/ic_launcher.png b/packages/tizen_package_manager/example/tizen/shared/res/ic_launcher.png
new file mode 100644
index 000000000..4d6372eeb
Binary files /dev/null and b/packages/tizen_package_manager/example/tizen/shared/res/ic_launcher.png differ
diff --git a/packages/tizen_package_manager/example/tizen/shared/res/org.example.simplehome.tpk b/packages/tizen_package_manager/example/tizen/shared/res/org.example.simplehome.tpk
new file mode 100644
index 000000000..658f2ad1a
Binary files /dev/null and b/packages/tizen_package_manager/example/tizen/shared/res/org.example.simplehome.tpk differ
diff --git a/packages/tizen_package_manager/example/tizen/tizen-manifest.xml b/packages/tizen_package_manager/example/tizen/tizen-manifest.xml
new file mode 100644
index 000000000..57965bb31
--- /dev/null
+++ b/packages/tizen_package_manager/example/tizen/tizen-manifest.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ tizen_package_manager_example
+ ic_launcher.png
+
+
+
+
+ http://tizen.org/privilege/packagemanager.info
+
+
diff --git a/packages/tizen_package_manager/lib/package_manager.dart b/packages/tizen_package_manager/lib/package_manager.dart
new file mode 100644
index 000000000..13b523c5a
--- /dev/null
+++ b/packages/tizen_package_manager/lib/package_manager.dart
@@ -0,0 +1,304 @@
+// Copyright 2022 Samsung Electronics Co., Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:flutter/services.dart';
+
+/// Enumeration for the package type.
+enum PackageType {
+ /// A special application package installed using the RPM spec.
+ /// Only some preloaded packages can have this type.
+ rpm,
+
+ /// Tizen native application pacakge.
+ tpk,
+
+ /// Tizen web/hybrid application package.
+ wgt,
+
+ /// Unknown package.
+ unknown,
+}
+
+/// Enumeration for the package manager event types.
+enum PackageEventType {
+ /// Install event.
+ install,
+
+ /// Uninstall event.
+ uninstall,
+
+ /// Update event.
+ update,
+
+ /// Move event.
+ move,
+
+ /// Clear data event.
+ clearData,
+}
+
+/// Enumeration for the package manager event state.
+enum PackageEventState {
+ /// Processing started.
+ started,
+
+ /// Processing state.
+ processing,
+
+ /// Processing completed.
+ completed,
+
+ /// Processing failed.
+ failed,
+}
+
+/// The package manager provides information about installed packages.
+/// This information includes the pacakge name, label, path of icon, version,
+/// type and installed storage.
+///
+/// For detailed information on Tizen's Package Manager, see:
+/// https://docs.tizen.org/application/dotnet/guides/app-management/package-manager/
+class PackageManager {
+ PackageManager._();
+
+ static const MethodChannel _channel = MethodChannel('tizen/package_manager');
+
+ static const EventChannel _installEventChannel =
+ EventChannel('tizen/package_manager/install_event');
+
+ static const EventChannel _uninstallEventChannel =
+ EventChannel('tizen/package_manager/uninstall_event');
+
+ static const EventChannel _updateEventChannel =
+ EventChannel('tizen/package_manager/update_event');
+
+ /// Gets the package information for the given package ID.
+ static Future getPackageInfo(String packageId) async {
+ if (packageId.isEmpty) {
+ throw ArgumentError('Must not be empty', 'packageId');
+ }
+
+ final Map map = await _channel
+ .invokeMapMethod(
+ 'getPackage', {'packageId': packageId}) ??
+ {};
+
+ return PackageInfo.fromMap(map);
+ }
+
+ /// Retrieves the package information of all installed packages.
+ static Future> getPackagesInfo() async {
+ final List? packages =
+ await _channel.invokeMethod>('getPackages');
+
+ final List list = [];
+ if (packages != null) {
+ for (final dynamic package in packages) {
+ list.add(PackageInfo.fromMap(package));
+ }
+ }
+ return list;
+ }
+
+ /// Installs the package located at the given path.
+ ///
+ /// The `http://tizen.org/privilege/packagemanager.admin` platform privilege
+ /// is required to use this API.
+ static Future install(String packagePath) async {
+ if (packagePath.isEmpty) {
+ throw ArgumentError('Must not be empty', 'packagePath');
+ }
+
+ final bool ret = await _channel.invokeMethod(
+ 'install', {'path': packagePath}) ??
+ false;
+ return ret;
+ }
+
+ /// Uninstalls the package with the given package ID.
+ ///
+ /// The `http://tizen.org/privilege/packagemanager.admin` platform privilege
+ /// is required to use this API.
+ static Future uninstall(String packageId) async {
+ if (packageId.isEmpty) {
+ throw ArgumentError('Must not be empty', 'packageId');
+ }
+
+ final bool ret = await _channel.invokeMethod(
+ 'uninstall', {'packageId': packageId}) ??
+ false;
+ return ret;
+ }
+
+ /// A stream of events occurring when a package is getting installed
+ /// and the progress of the request to the package manager is changed.
+ static Stream get onInstallProgressChanged =>
+ _installEventChannel
+ .receiveBroadcastStream()
+ .map((dynamic event) => PackageEvent.fromMap(event));
+
+ /// A stream of events occurring when a package is getting uninstalled
+ /// and the progress of the request to the package manager is changed.
+ static Stream get onUninstallProgressChanged =>
+ _uninstallEventChannel
+ .receiveBroadcastStream()
+ .map((dynamic event) => PackageEvent.fromMap(event));
+
+ /// A stream of events occurring when a package is getting updated
+ /// and the progress of the request to the package manager is changed.
+ static Stream get onUpdateProgressChanged => _updateEventChannel
+ .receiveBroadcastStream()
+ .map((dynamic event) => PackageEvent.fromMap(event));
+}
+
+/// Represents information of specific package.
+class PackageInfo {
+ /// Creates an instance of [PackageInfo] with the given parameters.
+ PackageInfo({
+ required this.packageId,
+ required this.label,
+ required this.packageType,
+ required this.iconPath,
+ required this.version,
+ required this.installedStorageType,
+ required this.isSystem,
+ required this.isPreloaded,
+ required this.isRemovable,
+ });
+
+ /// The package ID.
+ final String packageId;
+
+ /// Label of the package.
+ final String label;
+
+ /// Type of the package.
+ final PackageType packageType;
+
+ /// The path to the icon image.
+ final String? iconPath;
+
+ /// Version of the package.
+ final String version;
+
+ /// Installed storage type for the package.
+ /// the return value is either internal storage or external storage.
+ final String installedStorageType;
+
+ /// Whether the package is a system package.
+ final bool isSystem;
+
+ /// Whether the package is a preload package.
+ final bool isPreloaded;
+
+ /// Whether the package is a removable package.
+ final bool isRemovable;
+
+ /// Creates an instance of [PackageInfo] with the map parameter.
+ static PackageInfo fromMap(dynamic map) {
+ final Object? packageType = map['type'];
+ PackageType type = PackageType.unknown;
+ switch (packageType) {
+ case 'rpm':
+ type = PackageType.rpm;
+ break;
+ case 'wgt':
+ type = PackageType.wgt;
+ break;
+ case 'tpk':
+ type = PackageType.tpk;
+ break;
+ case 'unknown':
+ type = PackageType.unknown;
+ }
+
+ return PackageInfo(
+ packageId: map['packageId'] as String,
+ label: map['label'] as String,
+ iconPath: map['iconPath'] as String?,
+ packageType: type,
+ version: map['version'] as String,
+ installedStorageType: map['installedStorageType'] as String,
+ isSystem: map['isSystem'] as bool,
+ isPreloaded: map['isPreloaded'] as bool,
+ isRemovable: map['isRemovable'] as bool,
+ );
+ }
+}
+
+/// Represents the event arguments of [PackageManager] events.
+class PackageEvent {
+ /// Creates an instance of [PackageEvent] with the given parameters.
+ PackageEvent({
+ required this.packageId,
+ required this.packageType,
+ required this.eventType,
+ required this.eventState,
+ required this.progress,
+ });
+
+ /// The package ID.
+ final String packageId;
+
+ /// Type of the package.
+ final String packageType;
+
+ /// The package manager event types
+ final PackageEventType eventType;
+
+ /// The package manager event state.
+ final PackageEventState eventState;
+
+ /// Progress for the request being processed by the package manager (in percent).
+ final int progress;
+
+ /// Creates an instance of [PackageEvent] with the map parameter.
+ static PackageEvent fromMap(dynamic map) {
+ PackageEventType type = PackageEventType.install;
+ PackageEventState state = PackageEventState.started;
+ final String eventType = map['eventType'] as String;
+ final String eventState = map['eventState'] as String;
+
+ switch (eventType) {
+ case 'install':
+ type = PackageEventType.install;
+ break;
+ case 'uninstall':
+ type = PackageEventType.uninstall;
+ break;
+ case 'update':
+ type = PackageEventType.update;
+ break;
+ case 'cleardata':
+ type = PackageEventType.clearData;
+ break;
+ case 'move':
+ type = PackageEventType.move;
+ }
+
+ switch (eventState) {
+ case 'started':
+ state = PackageEventState.started;
+ break;
+ case 'processing':
+ state = PackageEventState.processing;
+ break;
+ case 'completed':
+ state = PackageEventState.completed;
+ break;
+ case 'failed':
+ state = PackageEventState.failed;
+ }
+
+ return PackageEvent(
+ packageId: map['packageId'] as String,
+ packageType: map['type'] as String,
+ eventType: type,
+ eventState: state,
+ progress: map['progress'] as int,
+ );
+ }
+}
diff --git a/packages/tizen_package_manager/pubspec.yaml b/packages/tizen_package_manager/pubspec.yaml
new file mode 100644
index 000000000..34e594536
--- /dev/null
+++ b/packages/tizen_package_manager/pubspec.yaml
@@ -0,0 +1,21 @@
+name: tizen_package_manager
+description: Tizen package manager APIs. Used to get detailed information on the installed packages on the Tizen device.
+homepage: https://github.com/flutter-tizen/plugins
+repository: https://github.com/flutter-tizen/plugins/tree/master/packages/tizen_package_manager
+version: 0.1.0
+
+environment:
+ sdk: ">=2.15.1 <3.0.0"
+ flutter: ">=2.5.0"
+
+dependencies:
+ flutter:
+ sdk: flutter
+
+flutter:
+ plugin:
+ platforms:
+ tizen:
+ pluginClass: TizenPackageManagerPlugin
+ fileName: tizen_package_manager_plugin.h
+
diff --git a/packages/tizen_package_manager/tizen/.gitignore b/packages/tizen_package_manager/tizen/.gitignore
new file mode 100644
index 000000000..a2a7d62b1
--- /dev/null
+++ b/packages/tizen_package_manager/tizen/.gitignore
@@ -0,0 +1,5 @@
+.cproject
+.sign
+crash-info/
+Debug/
+Release/
diff --git a/packages/tizen_package_manager/tizen/inc/tizen_package_manager_plugin.h b/packages/tizen_package_manager/tizen/inc/tizen_package_manager_plugin.h
new file mode 100644
index 000000000..da92b5561
--- /dev/null
+++ b/packages/tizen_package_manager/tizen/inc/tizen_package_manager_plugin.h
@@ -0,0 +1,27 @@
+// Copyright 2022 Samsung Electronics Co., Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FLUTTER_PLUGIN_TIZEN_PACKAGE_MANAGER_PLUGIN_H_
+#define FLUTTER_PLUGIN_TIZEN_PACKAGE_MANAGER_PLUGIN_H_
+
+#include
+
+#ifdef FLUTTER_PLUGIN_IMPL
+#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default")))
+#else
+#define FLUTTER_PLUGIN_EXPORT
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+FLUTTER_PLUGIN_EXPORT void TizenPackageManagerPluginRegisterWithRegistrar(
+ FlutterDesktopPluginRegistrarRef registrar);
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif
+
+#endif // FLUTTER_PLUGIN_TIZEN_PACKAGE_MANAGER_PLUGIN_H_
diff --git a/packages/tizen_package_manager/tizen/project_def.prop b/packages/tizen_package_manager/tizen/project_def.prop
new file mode 100644
index 000000000..06562b4d0
--- /dev/null
+++ b/packages/tizen_package_manager/tizen/project_def.prop
@@ -0,0 +1,24 @@
+# See https://docs.tizen.org/application/tizen-studio/native-tools/project-conversion
+# for details.
+
+APPNAME = tizen_package_manager_plugin
+type = staticLib
+profile = common-4.0
+
+# Source files
+USER_SRCS += src/*.cc
+
+# User defines
+USER_DEFS =
+USER_UNDEFS =
+USER_CPP_DEFS = FLUTTER_PLUGIN_IMPL
+USER_CPP_UNDEFS =
+
+# Compiler flags
+USER_CFLAGS_MISC =
+USER_CPPFLAGS_MISC =
+
+# User includes
+USER_INC_DIRS = inc src
+USER_INC_FILES =
+USER_CPP_INC_FILES =
diff --git a/packages/tizen_package_manager/tizen/src/log.h b/packages/tizen_package_manager/tizen/src/log.h
new file mode 100644
index 000000000..04abb8b4e
--- /dev/null
+++ b/packages/tizen_package_manager/tizen/src/log.h
@@ -0,0 +1,24 @@
+#ifndef __LOG_H__
+#define __LOG_H__
+
+#include
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "TizenPackageManagerPlugin"
+
+#ifndef __MODULE__
+#define __MODULE__ strrchr("/" __FILE__, '/') + 1
+#endif
+
+#define LOG(prio, fmt, arg...) \
+ dlog_print(prio, LOG_TAG, "%s: %s(%d) > " fmt, __MODULE__, __func__, \
+ __LINE__, ##arg)
+
+#define LOG_DEBUG(fmt, args...) LOG(DLOG_DEBUG, fmt, ##args)
+#define LOG_INFO(fmt, args...) LOG(DLOG_INFO, fmt, ##args)
+#define LOG_WARN(fmt, args...) LOG(DLOG_WARN, fmt, ##args)
+#define LOG_ERROR(fmt, args...) LOG(DLOG_ERROR, fmt, ##args)
+
+#endif // __LOG_H__
diff --git a/packages/tizen_package_manager/tizen/src/package_manager_utils.cc b/packages/tizen_package_manager/tizen/src/package_manager_utils.cc
new file mode 100644
index 000000000..0654a4c7a
--- /dev/null
+++ b/packages/tizen_package_manager/tizen/src/package_manager_utils.cc
@@ -0,0 +1,173 @@
+// Copyright 2022 Samsung Electronics Co., Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "package_manager_utils.h"
+
+namespace package_manager_utils {
+
+bool ExtractValueFromMap(const flutter::EncodableValue &arguments,
+ const char *key, std::string &out_value) {
+ if (std::holds_alternative(arguments)) {
+ flutter::EncodableMap map = std::get(arguments);
+ auto iter = map.find(flutter::EncodableValue(key));
+ if (iter != map.end() && !iter->second.IsNull()) {
+ if (auto pval = std::get_if(&iter->second)) {
+ out_value = *pval;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+int GetPackageData(package_info_h package_info, flutter::EncodableMap &value) {
+ char *pkg_name = nullptr;
+ char *label = nullptr;
+ char *type = nullptr;
+ char *icon_path = nullptr;
+ char *version = nullptr;
+ package_info_installed_storage_type_e installed_storage_type =
+ PACKAGE_INFO_INTERNAL_STORAGE;
+ bool is_system = false;
+ bool is_preloaded = false;
+ bool is_removable = true;
+
+ int ret = package_info_get_package(package_info, &pkg_name);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE || pkg_name == nullptr) {
+ LOG_ERROR("get package name error! : %s", get_error_message(ret));
+ goto cleanup;
+ }
+
+ ret = package_info_get_label(package_info, &label);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE || label == nullptr) {
+ LOG_ERROR("get package label error! : %s", get_error_message(ret));
+ goto cleanup;
+ }
+
+ ret = package_info_get_type(package_info, &type);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE || type == nullptr) {
+ LOG_ERROR("get package type error! : %s", get_error_message(ret));
+ goto cleanup;
+ }
+
+ ret = package_info_get_icon(package_info, &icon_path);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE || icon_path == nullptr) {
+ // because some service app doesn't have icon,
+ // just print error log, and pass it
+ LOG_ERROR("get icon path error! : %s", get_error_message(ret));
+ }
+
+ ret = package_info_get_version(package_info, &version);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE || version == nullptr) {
+ LOG_ERROR("get version error! : %s", get_error_message(ret));
+ goto cleanup;
+ }
+
+ ret =
+ package_info_get_installed_storage(package_info, &installed_storage_type);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+ LOG_ERROR("get installed storage error! : %s", get_error_message(ret));
+ goto cleanup;
+ }
+
+ ret = package_info_is_system_package(package_info, &is_system);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+ LOG_ERROR("check system package error! : %s", get_error_message(ret));
+ goto cleanup;
+ }
+
+ ret = package_info_is_preload_package(package_info, &is_preloaded);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+ LOG_ERROR("check preload package error! : %s", get_error_message(ret));
+ goto cleanup;
+ }
+
+ ret = package_info_is_removable_package(package_info, &is_removable);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+ LOG_ERROR("check removable package error! : %s", get_error_message(ret));
+ goto cleanup;
+ }
+
+ value[flutter::EncodableValue("packageId")] =
+ flutter::EncodableValue(std::string(pkg_name));
+ value[flutter::EncodableValue("label")] =
+ flutter::EncodableValue(std::string(label));
+ value[flutter::EncodableValue("type")] =
+ flutter::EncodableValue(std::string(type));
+ value[flutter::EncodableValue("version")] =
+ flutter::EncodableValue(std::string(version));
+ value[flutter::EncodableValue("installedStorageType")] =
+ flutter::EncodableValue(StorageTypeToString(installed_storage_type));
+ value[flutter::EncodableValue("isSystem")] =
+ flutter::EncodableValue(is_system);
+ value[flutter::EncodableValue("isPreloaded")] =
+ flutter::EncodableValue(is_preloaded);
+ value[flutter::EncodableValue("isRemovable")] =
+ flutter::EncodableValue(is_removable);
+ if (icon_path) {
+ value[flutter::EncodableValue("iconPath")] =
+ flutter::EncodableValue(std::string(icon_path));
+ }
+
+cleanup:
+ if (pkg_name) {
+ free(pkg_name);
+ }
+ if (label) {
+ free(label);
+ }
+ if (type) {
+ free(type);
+ }
+ if (icon_path) {
+ free(icon_path);
+ }
+ if (version) {
+ free(version);
+ }
+
+ return ret;
+}
+
+std::string StorageTypeToString(package_info_installed_storage_type_e value) {
+ switch (value) {
+ case PACKAGE_INFO_EXTERNAL_STORAGE:
+ return "External storage";
+ case PACKAGE_INFO_INTERNAL_STORAGE:
+ default:
+ return "Internal storage";
+ }
+}
+
+std::string PacakgeEventTypeToString(package_manager_event_type_e type) {
+ switch (type) {
+ case PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL:
+ return "uninstall";
+ case PACKAGE_MANAGER_EVENT_TYPE_UPDATE:
+ return "update";
+ case PACKAGE_MANAGER_EVENT_TYPE_MOVE:
+ return "move";
+ case PACKAGE_MANAGER_EVENT_TYPE_CLEAR:
+ return "cleardata";
+ case PACKAGE_MANAGER_EVENT_TYPE_INSTALL:
+ default:
+ return "install";
+ }
+}
+
+std::string PacakgeEventStateToString(package_manager_event_state_e state) {
+ switch (state) {
+ case PACKAGE_MANAGER_EVENT_STATE_STARTED:
+ return "started";
+ case PACKAGE_MANAGER_EVENT_STATE_PROCESSING:
+ return "processing";
+ case PACKAGE_MANAGER_EVENT_STATE_FAILED:
+ return "failed";
+ case PACKAGE_MANAGER_EVENT_STATE_COMPLETED:
+ default:
+ return "completed";
+ }
+}
+
+} // namespace package_manager_utils
diff --git a/packages/tizen_package_manager/tizen/src/package_manager_utils.h b/packages/tizen_package_manager/tizen/src/package_manager_utils.h
new file mode 100644
index 000000000..4d3b594f6
--- /dev/null
+++ b/packages/tizen_package_manager/tizen/src/package_manager_utils.h
@@ -0,0 +1,30 @@
+// Copyright 2022 Samsung Electronics Co., Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FLUTTER_PLUGIN_PACKAGE_MANAGER_UTILS_H_
+#define FLUTTER_PLUGIN_PACKAGE_MANAGER_UTILS_H_
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "log.h"
+
+namespace package_manager_utils {
+bool ExtractValueFromMap(const flutter::EncodableValue &arguments,
+ const char *key, std::string &out_value);
+int GetPackageData(package_info_h package_info, flutter::EncodableMap &value);
+
+std::string StorageTypeToString(package_info_installed_storage_type_e value);
+std::string PacakgeEventTypeToString(package_manager_event_type_e type);
+std::string PacakgeEventStateToString(package_manager_event_state_e state);
+} // namespace package_manager_utils
+
+#endif
diff --git a/packages/tizen_package_manager/tizen/src/tizen_package_manager_plugin.cc b/packages/tizen_package_manager/tizen/src/tizen_package_manager_plugin.cc
new file mode 100644
index 000000000..36f5e5268
--- /dev/null
+++ b/packages/tizen_package_manager/tizen/src/tizen_package_manager_plugin.cc
@@ -0,0 +1,421 @@
+// Copyright 2022 Samsung Electronics Co., Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tizen_package_manager_plugin.h"
+
+#include
+#include
+#include
+
+#include "package_manager_utils.h"
+
+const char kPackageTypeUnkown[] = "unknown";
+const char kPackageTypeTpk[] = "tpk";
+const char kPackageTypeWgt[] = "wgt";
+
+class TizenPackageManagerPlugin : public flutter::Plugin {
+ public:
+ using MethodResultPtr =
+ std::unique_ptr>;
+
+ static void RegisterWithRegistrar(flutter::PluginRegistrar *registrar) {
+ auto plugin = std::make_unique();
+ plugin->SetupChannels(registrar);
+ registrar->AddPlugin(std::move(plugin));
+ }
+
+ TizenPackageManagerPlugin() {}
+
+ virtual ~TizenPackageManagerPlugin() { UnregisterObserver(); }
+
+ private:
+ void HandleMethodCall(
+ const flutter::MethodCall &method_call,
+ MethodResultPtr result) {
+ const auto &arguments = *method_call.arguments();
+
+ if (method_call.method_name().compare("getPackage") == 0) {
+ GetPackageInfo(arguments, std::move(result));
+ } else if (method_call.method_name().compare("getPackages") == 0) {
+ GetAllPackagesInfo(std::move(result));
+ } else if (method_call.method_name().compare("install") == 0) {
+ Install(arguments, std::move(result));
+ } else if (method_call.method_name().compare("uninstall") == 0) {
+ Uninstall(arguments, std::move(result));
+ } else {
+ result->NotImplemented();
+ }
+ }
+
+ void RegisterObserver(
+ std::unique_ptr> &&events) {
+ int ret = PACKAGE_MANAGER_ERROR_NONE;
+ LOG_INFO("RegisterObserver");
+
+ if (package_manager_h_ == nullptr) {
+ ret = package_manager_create(&package_manager_h_);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+ char *err_msg = get_error_message(ret);
+ LOG_ERROR("Failed package_manager_create : %s", err_msg);
+ events->Error("Failed to create package manager handle",
+ std::string(err_msg));
+ return;
+ }
+ }
+
+ package_manager_set_event_status(package_manager_h_,
+ PACKAGE_MANAGER_STATUS_TYPE_INSTALL |
+ PACKAGE_MANAGER_STATUS_TYPE_UNINSTALL |
+ PACKAGE_MANAGER_STATUS_TYPE_UPGRADE);
+ ret = package_manager_set_event_cb(package_manager_h_, PackageEventCB,
+ (void *)this);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+ char *err_msg = get_error_message(ret);
+ LOG_ERROR("Failed package_manager_set_event_cb : %s", err_msg);
+ events->Error("Failed to add callback", std::string(err_msg));
+ return;
+ }
+ is_event_callback_registered_ = true;
+ }
+
+ void UnregisterObserver() {
+ LOG_INFO("UnregisterObserver");
+ if (is_event_callback_registered_ && package_manager_h_) {
+ int ret = package_manager_unset_event_cb(package_manager_h_);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+ LOG_ERROR("Failed package_manager_unset_event_cb : %s",
+ get_error_message(ret));
+ }
+
+ package_manager_destroy(package_manager_h_);
+ package_manager_h_ = nullptr;
+ is_event_callback_registered_ = false;
+ }
+ install_events_ = nullptr;
+ uninstall_events_ = nullptr;
+ update_events_ = nullptr;
+ }
+
+ void GetPackageInfo(const flutter::EncodableValue &arguments,
+ MethodResultPtr result) {
+ std::string id = "";
+ const char *package_id;
+ char *err_msg;
+ package_info_h package_info = nullptr;
+ flutter::EncodableMap value;
+
+ if (!package_manager_utils::ExtractValueFromMap(arguments, "packageId",
+ id)) {
+ result->Error("InvalidArguments", "Please check packageId");
+ return;
+ }
+ package_id = id.c_str();
+ LOG_INFO("GetPackageInfo() package_id : %s", package_id);
+
+ int ret = package_info_create(package_id, &package_info);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE || package_info == nullptr) {
+ err_msg = get_error_message(ret);
+ LOG_ERROR("Failed to get package_info handler : %s", err_msg);
+ result->Error(std::to_string(ret),
+ "Failed to create package_info handler.",
+ flutter::EncodableValue(std::string(err_msg)));
+ goto cleanup;
+ }
+
+ ret = package_manager_utils::GetPackageData(package_info, value);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+ err_msg = get_error_message(ret);
+ result->Error(std::to_string(ret), "Failed to package info.",
+ flutter::EncodableValue(std::string(err_msg)));
+ goto cleanup;
+ }
+ result->Success(flutter::EncodableValue(value));
+
+ cleanup:
+ if (package_info) {
+ package_info_destroy(package_info);
+ }
+ }
+
+ void GetAllPackagesInfo(MethodResultPtr result) {
+ LOG_INFO("GetAllPackagesInfo()");
+ packages_.erase(packages_.begin(), packages_.end());
+ int ret = package_manager_foreach_package_info(PackageInfoCB, (void *)this);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+ char *err_msg = get_error_message(ret);
+ LOG_ERROR("package_manager_foreach_package_info error: %s", err_msg);
+ result->Error(std::to_string(ret),
+ "package_manager_foreach_package_info error.",
+ flutter::EncodableValue(std::string(err_msg)));
+ }
+ result->Success(flutter::EncodableValue(packages_));
+ }
+
+ void Install(const flutter::EncodableValue &arguments,
+ MethodResultPtr result) {
+ std::string path = "";
+ const char *package_path;
+ char *err_msg;
+ package_manager_request_h package_manager_request = nullptr;
+ int request_id;
+
+ if (!package_manager_utils::ExtractValueFromMap(arguments, "path", path)) {
+ result->Error("InvalidArguments", "Please check path");
+ return;
+ }
+ package_path = path.c_str();
+ LOG_INFO("Install() package_path : %s", package_path);
+
+ int ret = package_manager_request_create(&package_manager_request);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE ||
+ package_manager_request == nullptr) {
+ err_msg = get_error_message(ret);
+ LOG_ERROR("Failed to get package_manager_request handler : %s", err_msg);
+ result->Error(std::to_string(ret),
+ "Failed to create package_manager_request handler.",
+ flutter::EncodableValue(std::string(err_msg)));
+ goto cleanup;
+ }
+
+ ret = package_manager_request_install(package_manager_request, package_path,
+ &request_id);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+ err_msg = get_error_message(ret);
+ result->Error(std::to_string(ret), "Failed to install.",
+ flutter::EncodableValue(std::string(err_msg)));
+ goto cleanup;
+ }
+ result->Success(flutter::EncodableValue(true));
+
+ cleanup:
+ if (package_manager_request) {
+ package_manager_request_destroy(package_manager_request);
+ }
+ }
+
+ void Uninstall(const flutter::EncodableValue &arguments,
+ MethodResultPtr result) {
+ std::string id = "";
+ const char *package_id;
+ char *err_msg;
+ package_manager_request_h package_manager_request = nullptr;
+ int request_id;
+
+ if (!package_manager_utils::ExtractValueFromMap(arguments, "packageId",
+ id)) {
+ result->Error("InvalidArguments", "Please check packageId");
+ return;
+ }
+ package_id = id.c_str();
+ LOG_INFO("Uninstall() package_id : %s", package_id);
+
+ int ret = package_manager_request_create(&package_manager_request);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE ||
+ package_manager_request == nullptr) {
+ err_msg = get_error_message(ret);
+ LOG_ERROR("Failed to get package_manager_request handler : %s", err_msg);
+ result->Error(std::to_string(ret),
+ "Failed to create package_manager_request handler.",
+ flutter::EncodableValue(std::string(err_msg)));
+ goto cleanup;
+ }
+
+ ret = package_manager_request_set_type(package_manager_request,
+ kPackageTypeUnkown);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+ err_msg = get_error_message(ret);
+ LOG_ERROR("Failed to set request type : %s", err_msg);
+ result->Error(std::to_string(ret), "Failed to set request type.",
+ flutter::EncodableValue(std::string(err_msg)));
+ goto cleanup;
+ }
+
+ ret = package_manager_request_uninstall(package_manager_request, package_id,
+ &request_id);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+ err_msg = get_error_message(ret);
+ result->Error(std::to_string(ret), "Failed to uninstall.",
+ flutter::EncodableValue(std::string(err_msg)));
+ goto cleanup;
+ }
+ result->Success(flutter::EncodableValue(true));
+
+ cleanup:
+ if (package_manager_request) {
+ package_manager_request_destroy(package_manager_request);
+ }
+ }
+
+ void SetupChannels(flutter::PluginRegistrar *registrar) {
+ auto method_channel =
+ std::make_unique>(
+ registrar->messenger(), "tizen/package_manager",
+ &flutter::StandardMethodCodec::GetInstance());
+
+ method_channel->SetMethodCallHandler([this](const auto &call, auto result) {
+ this->HandleMethodCall(call, std::move(result));
+ });
+
+ auto install_event_channel =
+ std::make_unique>(
+ registrar->messenger(), "tizen/package_manager/install_event",
+ &flutter::StandardMethodCodec::GetInstance());
+
+ auto uninstall_event_channel =
+ std::make_unique>(
+ registrar->messenger(), "tizen/package_manager/uninstall_event",
+ &flutter::StandardMethodCodec::GetInstance());
+
+ auto update_event_channel =
+ std::make_unique>(
+ registrar->messenger(), "tizen/package_manager/update_event",
+ &flutter::StandardMethodCodec::GetInstance());
+
+ auto install_event_channel_handler =
+ std::make_unique>(
+ [this](const flutter::EncodableValue *arguments,
+ std::unique_ptr> &&events)
+ -> std::unique_ptr> {
+ LOG_INFO("OnListen install");
+ install_events_ = std::move(events);
+ if (registered_cnt_ == 0) {
+ this->RegisterObserver(std::move(events));
+ }
+ registered_cnt_++;
+ return nullptr;
+ },
+ [this](const flutter::EncodableValue *arguments)
+ -> std::unique_ptr> {
+ registered_cnt_--;
+ LOG_INFO("OnCancel install");
+ if (registered_cnt_ == 0) {
+ this->UnregisterObserver();
+ }
+ install_events_ = nullptr;
+ return nullptr;
+ });
+
+ auto uninstall_event_channel_handler =
+ std::make_unique>(
+ [this](const flutter::EncodableValue *arguments,
+ std::unique_ptr> &&events)
+ -> std::unique_ptr> {
+ LOG_INFO("OnListen uninstall");
+ uninstall_events_ = std::move(events);
+ if (registered_cnt_ == 0) {
+ this->RegisterObserver(std::move(events));
+ }
+ registered_cnt_++;
+ return nullptr;
+ },
+ [this](const flutter::EncodableValue *arguments)
+ -> std::unique_ptr> {
+ LOG_INFO("OnCancel uninstall");
+ registered_cnt_--;
+ if (registered_cnt_ == 0) {
+ this->UnregisterObserver();
+ }
+ uninstall_events_ = nullptr;
+ return nullptr;
+ });
+
+ auto update_event_channel_handler =
+ std::make_unique>(
+ [this](const flutter::EncodableValue *arguments,
+ std::unique_ptr> &&events)
+ -> std::unique_ptr> {
+ LOG_INFO("OnListen update");
+ update_events_ = std::move(events);
+ if (registered_cnt_ == 0) {
+ this->RegisterObserver(std::move(events));
+ }
+ registered_cnt_++;
+ return nullptr;
+ },
+ [this](const flutter::EncodableValue *arguments)
+ -> std::unique_ptr> {
+ LOG_INFO("OnCancel update");
+ registered_cnt_--;
+ if (registered_cnt_ == 0) {
+ this->UnregisterObserver();
+ }
+ update_events_ = nullptr;
+ return nullptr;
+ });
+
+ install_event_channel->SetStreamHandler(
+ std::move(install_event_channel_handler));
+ uninstall_event_channel->SetStreamHandler(
+ std::move(uninstall_event_channel_handler));
+ update_event_channel->SetStreamHandler(
+ std::move(update_event_channel_handler));
+ }
+
+ static bool PackageInfoCB(package_info_h package_info, void *user_data) {
+ if (package_info) {
+ TizenPackageManagerPlugin *plugin =
+ (TizenPackageManagerPlugin *)user_data;
+ flutter::EncodableMap value;
+ int ret = package_manager_utils::GetPackageData(package_info, value);
+ if (ret == PACKAGE_MANAGER_ERROR_NONE) {
+ plugin->packages_.push_back(flutter::EncodableValue(value));
+ }
+ return true;
+ }
+ return false;
+ }
+
+ static void PackageEventCB(const char *type, const char *package,
+ package_manager_event_type_e event_type,
+ package_manager_event_state_e event_state,
+ int progress, package_manager_error_e error,
+ void *user_data) {
+ LOG_INFO("PackageEventCB, packageId : %s, type: %s", package, type);
+ LOG_INFO(
+ "event_type: %s, event_state: %s, progress : %d ",
+ package_manager_utils::PacakgeEventTypeToString(event_type).c_str(),
+ package_manager_utils::PacakgeEventStateToString(event_state).c_str(),
+ progress);
+
+ TizenPackageManagerPlugin *plugin = (TizenPackageManagerPlugin *)user_data;
+ flutter::EncodableMap msg;
+ msg[flutter::EncodableValue("packageId")] =
+ flutter::EncodableValue(std::string(package));
+ msg[flutter::EncodableValue("type")] =
+ flutter::EncodableValue(std::string(type));
+ msg[flutter::EncodableValue("eventType")] = flutter::EncodableValue(
+ package_manager_utils::PacakgeEventTypeToString(event_type));
+ msg[flutter::EncodableValue("eventState")] = flutter::EncodableValue(
+ package_manager_utils::PacakgeEventStateToString(event_state));
+ msg[flutter::EncodableValue("progress")] =
+ flutter::EncodableValue(progress);
+
+ if (event_type == PACKAGE_MANAGER_EVENT_TYPE_INSTALL &&
+ plugin->install_events_) {
+ plugin->install_events_->Success(flutter::EncodableValue(msg));
+ } else if (event_type == PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL &&
+ plugin->uninstall_events_) {
+ plugin->uninstall_events_->Success(flutter::EncodableValue(msg));
+ } else if (event_type == PACKAGE_MANAGER_EVENT_TYPE_UPDATE &&
+ plugin->update_events_) {
+ plugin->update_events_->Success(flutter::EncodableValue(msg));
+ }
+ }
+
+ flutter::EncodableList packages_;
+ std::unique_ptr> install_events_;
+ std::unique_ptr>
+ uninstall_events_;
+ std::unique_ptr> update_events_;
+ bool is_event_callback_registered_ = false;
+ int registered_cnt_ = 0;
+ package_manager_h package_manager_h_ = nullptr;
+};
+
+void TizenPackageManagerPluginRegisterWithRegistrar(
+ FlutterDesktopPluginRegistrarRef registrar) {
+ TizenPackageManagerPlugin::RegisterWithRegistrar(
+ flutter::PluginRegistrarManager::GetInstance()
+ ->GetRegistrar(registrar));
+}