Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/only-develop-to-main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: only-develop-to-main

on:
pull_request:
branches: ["main"]

jobs:
enforce:
runs-on: ubuntu-latest
steps:
- name: Allow only develop -> main PRs
run: |
echo "head_ref: ${{ github.head_ref }}"
echo "base_ref: ${{ github.base_ref }}"
if [ "${{ github.base_ref }}" = "main" ] && [ "${{ github.head_ref }}" != "develop" ]; then
echo "Only PRs from 'develop' to 'main' are allowed."
exit 1
fi
39 changes: 39 additions & 0 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Quality

on:
pull_request:
branches: ["develop"]

jobs:
quality:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Setup Dart
uses: dart-lang/setup-dart@v1
with:
sdk: stable

- name: Cache pub
uses: actions/cache@v4
with:
path: |
~/.pub-cache
.dart_tool
key: ${{ runner.os }}-pub-${{ hashFiles('**/pubspec.lock') }}
restore-keys: |
${{ runner.os }}-pub-

- name: Install dependencies
run: dart pub get

- name: Check formatting
run: dart format --set-exit-if-changed .

- name: Static analysis
run: dart analyze

- name: pub.dev dry-run
run: dart pub publish --dry-run
33 changes: 33 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Test

on:
pull_request:
branches: ["develop"]

jobs:
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Setup Dart
uses: dart-lang/setup-dart@v1
with:
sdk: stable

- name: Cache pub
uses: actions/cache@v4
with:
path: |
~/.pub-cache
.dart_tool
key: ${{ runner.os }}-pub-${{ hashFiles('**/pubspec.lock') }}
restore-keys: |
${{ runner.os }}-pub-

- name: Install dependencies
run: dart pub get

- name: Run tests
run: dart test
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.6.0
- **BREAKING**: Removed `requestedPermissions` field from `AppInfo` class to improve performance and reduce memory usage
- Added new API: `getRequestedPermissions(String packageName)` to fetch app permissions on demand
- Added comprehensive unit tests for `AppInfo`, `AppChangeType`, and `AppChangeEvent` classes

## 0.5.1
- Expanded `AppInfo` with additional Android-facing fields: `category`, `targetSdkVersion`, `minSdkVersion`, `enabled`, `processName`, `installLocation`, `requestedPermissions`.

Expand Down
51 changes: 16 additions & 35 deletions lib/flutter_device_apps_platform_interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ class AppInfo {
this.enabled,
this.processName,
this.installLocation,
this.requestedPermissions,
});

/// Creates an [AppInfo] from a map of key-value pairs.
Expand All @@ -52,9 +51,6 @@ class AppInfo {
final bool? enabled = m['enabled'] != null ? bool.tryParse(m['enabled']!.toString()) : null;
final int? installLocation =
m['installLocation'] != null ? int.tryParse(m['installLocation']!.toString()) : null;
final List<String>? requestedPermissions = m['requestedPermissions'] is List<dynamic>
? (m['requestedPermissions']! as List<dynamic>).map((e) => e.toString()).toList()
: null;

return AppInfo(
packageName: m['packageName']?.toString(),
Expand All @@ -72,7 +68,6 @@ class AppInfo {
enabled: enabled,
processName: m['processName']?.toString(),
installLocation: installLocation,
requestedPermissions: requestedPermissions,
);
}

Expand Down Expand Up @@ -100,47 +95,23 @@ class AppInfo {
/// The app icon as raw bytes, if requested and available.
final Uint8List? iconBytes;

/// App category (Android [ApplicationInfo.category], API 26+). Raw int from platform. Null when not set or API < 26.
/// App category (Android ApplicationInfo.category, API 26+). Raw int from platform. Null when not set or API < 26.
final int? category;

/// Target SDK version (Android [ApplicationInfo.targetSdkVersion]).
/// Target SDK version (Android ApplicationInfo.targetSdkVersion).
final int? targetSdkVersion;

/// Min SDK version (Android [ApplicationInfo.minSdkVersion]).
/// Min SDK version (Android ApplicationInfo.minSdkVersion).
final int? minSdkVersion;

/// Whether the app is enabled (Android [ApplicationInfo.enabled]).
/// Whether the app is enabled (Android ApplicationInfo.enabled).
final bool? enabled;

/// Process name (Android [ApplicationInfo.processName]).
/// Process name (Android ApplicationInfo.processName).
final String? processName;

/// Install location (Android [PackageInfo.installLocation]).
/// Install location (Android PackageInfo.installLocation).
final int? installLocation;

/// Requested permissions (Android [PackageInfo.requestedPermissions]).
final List<String>? requestedPermissions;

/// Converts this [AppInfo] to a map representation.
///
/// Useful for serialization to platform channels or other data formats.
Map<String, Object?> toMap() => {
'packageName': packageName,
'appName': appName,
'versionName': versionName,
'versionCode': versionCode,
'firstInstallTime': firstInstallTime?.millisecondsSinceEpoch,
'lastUpdateTime': lastUpdateTime?.millisecondsSinceEpoch,
'isSystem': isSystem,
'iconBytes': iconBytes,
'category': category,
'targetSdkVersion': targetSdkVersion,
'minSdkVersion': minSdkVersion,
'enabled': enabled,
'processName': processName,
'installLocation': installLocation,
'requestedPermissions': requestedPermissions,
};
}

/// Base class every platform implementation must extend.
Expand Down Expand Up @@ -175,6 +146,12 @@ abstract class FlutterDeviceAppsPlatform extends PlatformInterface {
/// Gets details for a single app.
Future<AppInfo?> getApp(String packageName, {bool includeIcon = false});

/// Gets the requested permissions for a specific app.
///
/// Implementations should return the Android PackageInfo.requestedPermissions
/// list for the given [packageName], or null if not available.
Future<List<String>?> getRequestedPermissions(String packageName);

/// Best-effort: launches an app by package name. Returns false if not launchable.
Future<bool> openApp(String packageName);

Expand Down Expand Up @@ -222,6 +199,10 @@ class _UnimplementedPlatform extends FlutterDeviceAppsPlatform {
Future<AppInfo?> getApp(String packageName, {bool includeIcon = false}) =>
Future.error(UnsupportedError('FlutterDeviceAppsPlatform not implemented'));

@override
Future<List<String>?> getRequestedPermissions(String packageName) =>
Future.error(UnsupportedError('FlutterDeviceAppsPlatform not implemented'));

@override
Future<bool> openApp(String packageName) =>
Future.error(UnsupportedError('FlutterDeviceAppsPlatform not implemented'));
Expand Down
5 changes: 3 additions & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: flutter_device_apps_platform_interface
description: Platform-agnostic API contract for flutter_device_apps (federated).
version: 0.5.1
version: 0.6.0
repository: https://github.com/okmsbun/flutter_device_apps_platform_interface
issue_tracker: https://github.com/okmsbun/flutter_device_apps_platform_interface/issues
topics:
Expand All @@ -17,4 +17,5 @@ dependencies:
plugin_platform_interface: ^2.1.8

dev_dependencies:
lints: ^6.0.0
lints: ^6.1.0
test: ^1.29.0
Loading